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

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

Issue 2878543003: Hook up Reader Mode InfoBar (Closed)
Patch Set: fix disabled test Created 3 years, 7 months 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.dom_distiller; 5 package org.chromium.chrome.browser.dom_distiller;
6 6
7 import android.content.Context; 7 import android.content.Context;
8 import android.text.TextUtils; 8 import android.text.TextUtils;
9 9
10 import org.chromium.base.CommandLine; 10 import org.chromium.base.CommandLine;
11 import org.chromium.base.SysUtils;
12 import org.chromium.base.VisibleForTesting;
13 import org.chromium.base.library_loader.LibraryLoader; 11 import org.chromium.base.library_loader.LibraryLoader;
14 import org.chromium.base.metrics.RecordHistogram; 12 import org.chromium.base.metrics.RecordHistogram;
15 import org.chromium.chrome.browser.ChromeActivity; 13 import org.chromium.chrome.browser.ChromeActivity;
16 import org.chromium.chrome.browser.ChromeSwitches; 14 import org.chromium.chrome.browser.ChromeSwitches;
17 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState;
18 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChange Reason; 15 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChange Reason;
19 import org.chromium.chrome.browser.compositor.bottombar.readermode.ReaderModePan el; 16 import org.chromium.chrome.browser.infobar.ReaderModeInfoBar;
20 import org.chromium.chrome.browser.infobar.InfoBar;
21 import org.chromium.chrome.browser.infobar.InfoBarContainer;
22 import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarContainerObse rver;
23 import org.chromium.chrome.browser.rappor.RapporServiceBridge; 17 import org.chromium.chrome.browser.rappor.RapporServiceBridge;
24 import org.chromium.chrome.browser.tab.Tab; 18 import org.chromium.chrome.browser.tab.Tab;
25 import org.chromium.chrome.browser.tabmodel.TabCreatorManager; 19 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
26 import org.chromium.chrome.browser.tabmodel.TabModel; 20 import org.chromium.chrome.browser.tabmodel.TabModel;
27 import org.chromium.chrome.browser.tabmodel.TabModelSelector; 21 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
28 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; 22 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
29 import org.chromium.chrome.browser.util.AccessibilityUtil; 23 import org.chromium.chrome.browser.util.AccessibilityUtil;
30 import org.chromium.chrome.browser.widget.findinpage.FindToolbarObserver;
31 import org.chromium.components.dom_distiller.content.DistillablePageUtils; 24 import org.chromium.components.dom_distiller.content.DistillablePageUtils;
32 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; 25 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
33 import org.chromium.content_public.browser.LoadUrlParams; 26 import org.chromium.content_public.browser.LoadUrlParams;
27 import org.chromium.content_public.browser.NavigationController;
28 import org.chromium.content_public.browser.NavigationEntry;
34 import org.chromium.content_public.browser.WebContents; 29 import org.chromium.content_public.browser.WebContents;
35 import org.chromium.content_public.browser.WebContentsObserver; 30 import org.chromium.content_public.browser.WebContentsObserver;
36 import org.chromium.ui.UiUtils; 31 import org.chromium.ui.UiUtils;
37 import org.chromium.ui.base.DeviceFormFactor;
38 import org.chromium.ui.base.PageTransition; 32 import org.chromium.ui.base.PageTransition;
39 33
40 import java.util.HashMap; 34 import java.util.HashMap;
41 import java.util.Map; 35 import java.util.Map;
42 import java.util.concurrent.TimeUnit; 36 import java.util.concurrent.TimeUnit;
43 37
44 /** 38 /**
45 * Manages UI effects for reader mode including hiding and showing the 39 * Manages UI effects for reader mode including hiding and showing the
46 * reader mode and reader mode preferences toolbar icon and hiding the 40 * reader mode and reader mode preferences toolbar icon and hiding the
47 * browser controls when a reader mode page has finished loading. 41 * browser controls when a reader mode page has finished loading.
48 */ 42 */
49 public class ReaderModeManager extends TabModelSelectorTabObserver 43 public class ReaderModeManager
50 implements InfoBarContainerObserver, ReaderModeManagerDelegate { 44 extends TabModelSelectorTabObserver implements ReaderModeManagerDelegate {
51 45 /** POSSIBLE means reader mode can be entered. */
52 /**
53 * POSSIBLE means reader mode can be entered.
54 */
55 public static final int POSSIBLE = 0; 46 public static final int POSSIBLE = 0;
56 47
57 /** 48 /** NOT_POSSIBLE means reader mode cannot be entered. */
58 * NOT_POSSIBLE means reader mode cannot be entered.
59 */
60 public static final int NOT_POSSIBLE = 1; 49 public static final int NOT_POSSIBLE = 1;
61 50
62 /** 51 /** STARTED means reader mode is currently in reader mode. */
63 * STARTED means reader mode is currently in reader mode.
64 */
65 public static final int STARTED = 2; 52 public static final int STARTED = 2;
66 53
67 // The url of the last page visited if the last page was reader mode page. Otherwise null. 54 /** The url of the last page visited if the last page was reader mode page. Otherwise null. */
68 private String mReaderModePageUrl; 55 private String mReaderModePageUrl;
69 56
70 // Whether the fact that the current web page was distillable or not has bee n recorded. 57 /** Whether the fact that the current web page was distillable or not has be en recorded. */
71 private boolean mIsUmaRecorded; 58 private boolean mIsUmaRecorded;
72 59
73 // The per-tab state of distillation. 60 /** The per-tab state of distillation. */
74 protected Map<Integer, ReaderModeTabInfo> mTabStatusMap; 61 protected Map<Integer, ReaderModeTabInfo> mTabStatusMap;
75 62
76 // The current tab ID. This will change as the user switches between tabs. 63 /** The current tab ID. This will change as the user switches between tabs. */
77 private int mTabId; 64 private int mTabId;
78 65
79 // The ReaderModePanel that this class is managing. 66 /** The ChromeActivity that this panel exists in. */
80 protected ReaderModePanel mReaderModePanel;
81
82 // The ChromeActivity that this panel exists in.
83 private ChromeActivity mChromeActivity; 67 private ChromeActivity mChromeActivity;
84 68
85 // The primary means of getting the currently active tab. 69 /** The primary means of getting the currently active tab. */
86 private TabModelSelector mTabModelSelector; 70 private TabModelSelector mTabModelSelector;
87 71
88 private boolean mIsFullscreenModeEntered; 72 /** If Reader Mode is detecting all pages as distillable. */
89 private boolean mIsFindToolbarShowing;
90 private boolean mIsKeyboardShowing;
91
92 // InfoBar tracking.
93 private boolean mIsInfoBarContainerShown;
94
95 // If Reader Mode is detecting all pages as distillable.
96 private boolean mIsReaderHeuristicAlwaysTrue; 73 private boolean mIsReaderHeuristicAlwaysTrue;
97 74
75 /** Whether or not the previous navigation should be removed. */
76 private boolean mShouldRemovePreviousNavigation;
77
78 /** The index of the last committed distiller page in history. */
79 private int mLastDistillerPageIndex;
98 80
99 public ReaderModeManager(TabModelSelector selector, ChromeActivity activity) { 81 public ReaderModeManager(TabModelSelector selector, ChromeActivity activity) {
100 super(selector); 82 super(selector);
101 mTabId = Tab.INVALID_TAB_ID; 83 mTabId = Tab.INVALID_TAB_ID;
102 mTabModelSelector = selector; 84 mTabModelSelector = selector;
103 mChromeActivity = activity; 85 mChromeActivity = activity;
104 mTabStatusMap = new HashMap<>(); 86 mTabStatusMap = new HashMap<>();
105 mIsReaderHeuristicAlwaysTrue = isDistillerHeuristicAlwaysTrue(); 87 mIsReaderHeuristicAlwaysTrue = isDistillerHeuristicAlwaysTrue();
106 } 88 }
107 89
(...skipping 14 matching lines...) Expand all
122 for (Map.Entry<Integer, ReaderModeTabInfo> e : mTabStatusMap.entrySet()) { 104 for (Map.Entry<Integer, ReaderModeTabInfo> e : mTabStatusMap.entrySet()) {
123 if (e.getValue().getWebContentsObserver() != null) { 105 if (e.getValue().getWebContentsObserver() != null) {
124 e.getValue().getWebContentsObserver().destroy(); 106 e.getValue().getWebContentsObserver().destroy();
125 } 107 }
126 } 108 }
127 mTabStatusMap.clear(); 109 mTabStatusMap.clear();
128 110
129 DomDistillerUIUtils.destroy(this); 111 DomDistillerUIUtils.destroy(this);
130 112
131 mChromeActivity = null; 113 mChromeActivity = null;
132 mReaderModePanel = null;
133 mTabModelSelector = null; 114 mTabModelSelector = null;
134 } 115 }
135 116
136 /**
137 * @return A FindToolbarObserver capable of hiding the Reader Mode panel.
138 */
139 public FindToolbarObserver getFindToolbarObserver() {
140 return new FindToolbarObserver() {
141 @Override
142 public void onFindToolbarShown() {
143 mIsFindToolbarShowing = true;
144 closeReaderPanel(StateChangeReason.UNKNOWN, true);
145 }
146
147 @Override
148 public void onFindToolbarHidden() {
149 mIsFindToolbarShowing = false;
150 requestReaderPanelShow(StateChangeReason.UNKNOWN);
151 }
152 };
153 }
154
155 // TabModelSelectorTabObserver: 117 // TabModelSelectorTabObserver:
156 118
157 @Override 119 @Override
158 public void onShown(Tab shownTab) { 120 public void onShown(Tab shownTab) {
159 if (mTabModelSelector == null) return; 121 if (mTabModelSelector == null) return;
160 122
161 int shownTabId = shownTab.getId(); 123 int shownTabId = shownTab.getId();
162 Tab previousTab = mTabModelSelector.getTabById(mTabId);
163 mTabId = shownTabId; 124 mTabId = shownTabId;
164 125
165 // If the reader panel was dismissed, stop here. 126 // If the reader panel was dismissed, stop here.
166 if (mTabStatusMap.containsKey(shownTabId) 127 if (mTabStatusMap.containsKey(shownTabId)
167 && mTabStatusMap.get(shownTabId).isDismissed()) { 128 && mTabStatusMap.get(shownTabId).isDismissed()) {
168 return; 129 return;
169 } 130 }
170 131
171 // Set this manager as the active one for the UI utils. 132 // Set this manager as the active one for the UI utils.
172 DomDistillerUIUtils.setReaderModeManagerDelegate(this); 133 DomDistillerUIUtils.setReaderModeManagerDelegate(this);
173 134
174 // Update infobar state based on current tab.
175 if (shownTab.getInfoBarContainer() != null) {
176 mIsInfoBarContainerShown = shownTab.getInfoBarContainer().hasInfoBar s();
177 }
178
179 // Remove the infobar observer from the previous tab and attach it to th e current one.
180 if (previousTab != null && previousTab.getInfoBarContainer() != null) {
181 previousTab.getInfoBarContainer().removeObserver(this);
182 }
183
184 if (shownTab.getInfoBarContainer() != null) {
185 shownTab.getInfoBarContainer().addObserver(this);
186 }
187
188 // If there is no state info for this tab, create it. 135 // If there is no state info for this tab, create it.
189 ReaderModeTabInfo tabInfo = mTabStatusMap.get(shownTabId); 136 ReaderModeTabInfo tabInfo = mTabStatusMap.get(shownTabId);
190 if (tabInfo == null) { 137 if (tabInfo == null) {
191 tabInfo = new ReaderModeTabInfo(); 138 tabInfo = new ReaderModeTabInfo();
192 tabInfo.setStatus(NOT_POSSIBLE); 139 tabInfo.setStatus(NOT_POSSIBLE);
193 tabInfo.setUrl(shownTab.getUrl()); 140 tabInfo.setUrl(shownTab.getUrl());
194 mTabStatusMap.put(shownTabId, tabInfo); 141 mTabStatusMap.put(shownTabId, tabInfo);
195 } 142 }
196 143
197 // Make sure there is a WebContentsObserver on this tab's WebContents. 144 // Make sure there is a WebContentsObserver on this tab's WebContents.
198 if (tabInfo.getWebContentsObserver() == null) { 145 if (tabInfo.getWebContentsObserver() == null) {
199 tabInfo.setWebContentsObserver(createWebContentsObserver(shownTab.ge tWebContents())); 146 tabInfo.setWebContentsObserver(createWebContentsObserver(shownTab.ge tWebContents()));
200 } 147 }
201 148
202 // Make sure there is a distillability delegate set on the WebContents. 149 // Make sure there is a distillability delegate set on the WebContents.
203 setDistillabilityCallback(shownTabId); 150 setDistillabilityCallback(shownTabId);
204 151
205 requestReaderPanelShow(StateChangeReason.UNKNOWN); 152 tryShowingInfoBar();
206 } 153 }
207 154
208 @Override 155 @Override
209 public void onHidden(Tab tab) { 156 public void onHidden(Tab tab) {
210 closeReaderPanel(StateChangeReason.UNKNOWN, false); 157 closeReaderPanel(StateChangeReason.UNKNOWN, false);
211 } 158 }
212 159
213 @Override 160 @Override
214 public void onDestroyed(Tab tab) { 161 public void onDestroyed(Tab tab) {
215 if (tab == null) return; 162 if (tab == null) return;
216 if (tab.getInfoBarContainer() != null) { 163
217 tab.getInfoBarContainer().removeObserver(this);
218 }
219 // If the panel was not shown for the previous navigation, record it now . 164 // If the panel was not shown for the previous navigation, record it now .
220 ReaderModeTabInfo info = mTabStatusMap.get(tab.getId()); 165 ReaderModeTabInfo info = mTabStatusMap.get(tab.getId());
221 if (info != null && !info.isPanelShowRecorded()) { 166 if (info != null && !info.isPanelShowRecorded()) {
222 recordPanelVisibilityForNavigation(false); 167 recordPanelVisibilityForNavigation(false);
223 } 168 }
224 removeTabState(tab.getId()); 169 removeTabState(tab.getId());
225 } 170 }
226 171
172 @Override
173 public void onPageLoadStarted(Tab tab, String url) {
174 // Reader Mode should not pollute the navigation stack. To avoid this, w atch for navigations
175 // and prepare to remove any that are "chrome-distiller" urls.
176 NavigationController controller = tab.getWebContents().getNavigationCont roller();
177 int index = controller.getLastCommittedEntryIndex();
178 NavigationEntry entry = controller.getEntryAtIndex(index);
179 if (entry == null) return;
180
181 if (DomDistillerUrlUtils.isDistilledPage(entry.getUrl())) {
182 mShouldRemovePreviousNavigation = true;
183 mLastDistillerPageIndex = index;
184 }
185 }
186
187 @Override
188 public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame ,
189 boolean isErrorPage, boolean hasCommitted, boolean isSameDocument,
190 boolean isFragmentNavigation, Integer pageTransition, int errorCode,
191 int httpStatusCode) {
192 if (!hasCommitted || !mShouldRemovePreviousNavigation || !isInMainFrame) return;
193
194 mShouldRemovePreviousNavigation = false;
195 NavigationController controller = tab.getWebContents().getNavigationCont roller();
196 controller.removeEntryAtIndex(mLastDistillerPageIndex);
197 }
198
227 /** 199 /**
228 * Clean up the state associated with a tab. 200 * Clean up the state associated with a tab.
229 * @param tabId The target tab ID. 201 * @param tabId The target tab ID.
230 */ 202 */
231 private void removeTabState(int tabId) { 203 private void removeTabState(int tabId) {
232 if (!mTabStatusMap.containsKey(tabId)) return; 204 if (!mTabStatusMap.containsKey(tabId)) return;
233 ReaderModeTabInfo tabInfo = mTabStatusMap.get(tabId); 205 ReaderModeTabInfo tabInfo = mTabStatusMap.get(tabId);
234 if (tabInfo.getWebContentsObserver() != null) { 206 if (tabInfo.getWebContentsObserver() != null) {
235 tabInfo.getWebContentsObserver().destroy(); 207 tabInfo.getWebContentsObserver().destroy();
236 } 208 }
(...skipping 20 matching lines...) Expand all
257 if (tab.getWebContents() != null) { 229 if (tab.getWebContents() != null) {
258 tabInfo.setWebContentsObserver(createWebContentsObserver(tab.getWebC ontents())); 230 tabInfo.setWebContentsObserver(createWebContentsObserver(tab.getWebC ontents()));
259 if (DomDistillerUrlUtils.isDistilledPage(tab.getUrl())) { 231 if (DomDistillerUrlUtils.isDistilledPage(tab.getUrl())) {
260 tabInfo.setStatus(STARTED); 232 tabInfo.setStatus(STARTED);
261 mReaderModePageUrl = tab.getUrl(); 233 mReaderModePageUrl = tab.getUrl();
262 closeReaderPanel(StateChangeReason.CONTENT_CHANGED, true); 234 closeReaderPanel(StateChangeReason.CONTENT_CHANGED, true);
263 } 235 }
264 // Make sure there is a distillability delegate set on the WebConten ts. 236 // Make sure there is a distillability delegate set on the WebConten ts.
265 setDistillabilityCallback(tab.getId()); 237 setDistillabilityCallback(tab.getId());
266 } 238 }
267
268 if (tab.getInfoBarContainer() != null) tab.getInfoBarContainer().addObse rver(this);
269 }
270
271 @Override
272 public void onToggleFullscreenMode(Tab tab, boolean enable) {
273 // Temporarily hide the reader mode panel while fullscreen is enabled.
274 if (enable) {
275 mIsFullscreenModeEntered = true;
276 closeReaderPanel(StateChangeReason.FULLSCREEN_ENTERED, false);
277 } else {
278 mIsFullscreenModeEntered = false;
279 requestReaderPanelShow(StateChangeReason.FULLSCREEN_EXITED);
280 }
281 }
282
283 // InfoBarContainerObserver:
284
285 @Override
286 public void onAddInfoBar(InfoBarContainer container, InfoBar infoBar, boolea n isFirst) {
287 mIsInfoBarContainerShown = true;
288 // If the panel is opened past the peeking state, obscure the infobar.
289 if (mReaderModePanel != null && mReaderModePanel.isPanelOpened() && cont ainer != null) {
290 container.setIsObscuredByOtherView(true);
291 } else if (isFirst) {
292 // Temporarily hides the reader mode button while the infobars are s hown.
293 closeReaderPanel(StateChangeReason.INFOBAR_SHOWN, false);
294 }
295 }
296
297 @Override
298 public void onRemoveInfoBar(InfoBarContainer container, InfoBar infoBar, boo lean isLast) {
299 // Re-shows the reader mode button if necessary once the infobars are di smissed.
300 if (isLast) {
301 mIsInfoBarContainerShown = false;
302 requestReaderPanelShow(StateChangeReason.INFOBAR_HIDDEN);
303 }
304 }
305
306 @Override
307 public void onInfoBarContainerAttachedToWindow(boolean hasInfoBars) {
308 mIsInfoBarContainerShown = hasInfoBars;
309 if (mIsInfoBarContainerShown) {
310 closeReaderPanel(StateChangeReason.INFOBAR_SHOWN, false);
311 } else {
312 requestReaderPanelShow(StateChangeReason.INFOBAR_HIDDEN);
313 }
314 } 239 }
315 240
316 // ReaderModeManagerDelegate: 241 // ReaderModeManagerDelegate:
317 242
318 @Override 243 @Override
319 public void setReaderModePanel(ReaderModePanel panel) {
320 mReaderModePanel = panel;
321 }
322
323 @Override
324 public ChromeActivity getChromeActivity() { 244 public ChromeActivity getChromeActivity() {
325 return mChromeActivity; 245 return mChromeActivity;
326 } 246 }
327 247
328 @Override 248 @Override
329 public void onPanelShown() { 249 public void onPanelShown() {
330 if (mTabModelSelector == null) return; 250 if (mTabModelSelector == null) return;
331 int tabId = mTabModelSelector.getCurrentTabId(); 251 int tabId = mTabModelSelector.getCurrentTabId();
332 252
333 ReaderModeTabInfo info = mTabStatusMap.get(tabId); 253 ReaderModeTabInfo info = mTabStatusMap.get(tabId);
(...skipping 10 matching lines...) Expand all
344 /** 264 /**
345 * Record if the panel became visible on the current page. This can be overr idden for testing. 265 * Record if the panel became visible on the current page. This can be overr idden for testing.
346 * @param visible If the panel was visible at any time. 266 * @param visible If the panel was visible at any time.
347 */ 267 */
348 protected void recordPanelVisibilityForNavigation(boolean visible) { 268 protected void recordPanelVisibilityForNavigation(boolean visible) {
349 RecordHistogram.recordBooleanHistogram("DomDistiller.ReaderShownForPageL oad", visible); 269 RecordHistogram.recordBooleanHistogram("DomDistiller.ReaderShownForPageL oad", visible);
350 } 270 }
351 271
352 @Override 272 @Override
353 public void onClosed(StateChangeReason reason) { 273 public void onClosed(StateChangeReason reason) {
354 if (mReaderModePanel == null || mTabModelSelector == null) return; 274 if (mTabModelSelector == null) return;
355
356 restoreInfobars();
357 275
358 // Only dismiss the panel if the close was a result of user interaction. 276 // Only dismiss the panel if the close was a result of user interaction.
359 if (reason != StateChangeReason.FLING && reason != StateChangeReason.SWI PE 277 if (reason != StateChangeReason.FLING && reason != StateChangeReason.SWI PE
Theresa 2017/05/11 22:31:19 StateChangeReason doesn't really apply anymore rig
mdjones 2017/05/12 19:13:10 Done.
360 && reason != StateChangeReason.CLOSE_BUTTON) { 278 && reason != StateChangeReason.CLOSE_BUTTON) {
361 return; 279 return;
362 } 280 }
363 281
364 // Record close button usage. 282 RecordHistogram.recordBooleanHistogram("DomDistiller.InfoBarUsage", fals e);
365 if (reason == StateChangeReason.CLOSE_BUTTON) {
366 RecordHistogram.recordBooleanHistogram("DomDistiller.BarCloseButtonU sage",
367 mReaderModePanel.getPanelState() == PanelState.EXPANDED
368 || mReaderModePanel.getPanelState() == PanelState.MAXIMIZED) ;
369 }
370 283
371 int currentTabId = mTabModelSelector.getCurrentTabId(); 284 int currentTabId = mTabModelSelector.getCurrentTabId();
372 if (!mTabStatusMap.containsKey(currentTabId)) return; 285 if (!mTabStatusMap.containsKey(currentTabId)) return;
373 mTabStatusMap.get(currentTabId).setIsDismissed(true); 286 mTabStatusMap.get(currentTabId).setIsDismissed(true);
374 } 287 }
375 288
376 @Override 289 @Override
377 public void onPeek() {
378 restoreInfobars();
379 }
380
381 /**
382 * Restore any infobars that may have been hidden by Reader Mode.
383 */
384 private void restoreInfobars() {
385 if (!mIsInfoBarContainerShown) return;
386
387 Tab curTab = mTabModelSelector.getCurrentTab();
388 if (curTab == null) return;
389
390 InfoBarContainer container = curTab.getInfoBarContainer();
391 if (container == null) return;
392
393 container.setIsObscuredByOtherView(false);
394
395 // Temporarily hides the reader mode button while the infobars are shown .
396 closeReaderPanel(StateChangeReason.INFOBAR_SHOWN, false);
397 }
398
399 @Override
400 public WebContents getBasePageWebContents() { 290 public WebContents getBasePageWebContents() {
401 Tab tab = mTabModelSelector.getCurrentTab(); 291 Tab tab = mTabModelSelector.getCurrentTab();
402 if (tab == null) return null; 292 if (tab == null) return null;
403 293
404 return tab.getWebContents(); 294 return tab.getWebContents();
405 } 295 }
406 296
407 @Override 297 @Override
408 public void closeReaderPanel(StateChangeReason reason, boolean animate) { 298 public void closeReaderPanel(StateChangeReason reason, boolean animate) {
409 if (mReaderModePanel == null) return; 299 // TODO(mdjones): Remove this method and dependencies.
Theresa 2017/05/11 22:31:19 InfoBar handles automatically dismissing itself?
mdjones 2017/05/12 19:13:10 In most cases where we want it, yes. That's the ni
410 mReaderModePanel.closePanel(reason, animate);
411 } 300 }
412 301
413 @Override 302 @Override
414 public void recordTimeSpentInReader(long timeMs) { 303 public void recordTimeSpentInReader(long timeMs) {
415 RecordHistogram.recordLongTimesHistogram("DomDistiller.Time.ViewingReade rModePanel", 304 RecordHistogram.recordLongTimesHistogram("DomDistiller.Time.ViewingReade rModePanel",
416 timeMs, TimeUnit.MILLISECONDS); 305 timeMs, TimeUnit.MILLISECONDS);
417 } 306 }
418 307
419 @Override
420 public void onLayoutChanged() {
421 if (isKeyboardShowing()) {
422 mIsKeyboardShowing = true;
423 closeReaderPanel(StateChangeReason.KEYBOARD_SHOWN, false);
424 } else if (mIsKeyboardShowing) {
425 mIsKeyboardShowing = false;
426 requestReaderPanelShow(StateChangeReason.KEYBOARD_HIDDEN);
427 }
428 }
429
430 /** 308 /**
431 * @return True if the keyboard might be showing. This is not 100% accurate; see 309 * @return True if the keyboard might be showing. This is not 100% accurate; see
432 * UiUtils.isKeyboardShowing(...). 310 * UiUtils.isKeyboardShowing(...).
433 */ 311 */
434 protected boolean isKeyboardShowing() { 312 protected boolean isKeyboardShowing() {
435 return mChromeActivity != null && UiUtils.isKeyboardShowing(mChromeActiv ity, 313 return mChromeActivity != null && UiUtils.isKeyboardShowing(mChromeActiv ity,
436 mChromeActivity.findViewById(android.R.id.content)); 314 mChromeActivity.findViewById(android.R.id.content));
437 } 315 }
438 316
439 protected WebContentsObserver createWebContentsObserver(WebContents webConte nts) { 317 protected WebContentsObserver createWebContentsObserver(WebContents webConte nts) {
(...skipping 16 matching lines...) Expand all
456 if (tabInfo == null) return; 334 if (tabInfo == null) return;
457 335
458 tabInfo.setUrl(url); 336 tabInfo.setUrl(url);
459 if (DomDistillerUrlUtils.isDistilledPage(url)) { 337 if (DomDistillerUrlUtils.isDistilledPage(url)) {
460 tabInfo.setStatus(STARTED); 338 tabInfo.setStatus(STARTED);
461 mReaderModePageUrl = url; 339 mReaderModePageUrl = url;
462 } 340 }
463 } 341 }
464 342
465 @Override 343 @Override
466 public void didFinishNavigation(String url, boolean isInMainFrame, b oolean isErrorPage, 344 public void didFinishNavigation(String url, boolean isInMainFrame, b oolean isErrorPage,
Theresa 2017/05/11 22:31:19 When is this called vs onDidFinishNavigation?
mdjones 2017/05/12 19:13:10 Not a big difference, I'll move those functions in
467 boolean hasCommitted, boolean isSameDocument, boolean isFrag mentNavigation, 345 boolean hasCommitted, boolean isSameDocument, boolean isFrag mentNavigation,
468 Integer pageTransition, int errorCode, String errorDescripti on, 346 Integer pageTransition, int errorCode, String errorDescripti on,
469 int httpStatusCode) { 347 int httpStatusCode) {
470 // TODO(cjhopman): This should possibly ignore navigations that replace the entry 348 // TODO(cjhopman): This should possibly ignore navigations that replace the entry
471 // (like those from history.replaceState()). 349 // (like those from history.replaceState()).
472 if (!hasCommitted || !isInMainFrame || isSameDocument) return; 350 if (!hasCommitted || !isInMainFrame || isSameDocument) return;
473 if (DomDistillerUrlUtils.isDistilledPage(url)) return;
474 351
475 // Make sure the tab was not destroyed. 352 // Make sure the tab was not destroyed.
476 ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId); 353 ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId);
477 if (tabInfo == null) return; 354 if (tabInfo == null) return;
478 355
479 tabInfo.setStatus(POSSIBLE); 356 tabInfo.setStatus(POSSIBLE);
480 if (!TextUtils.equals(url, 357 if (!TextUtils.equals(url,
481 DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl( 358 DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(
482 mReaderModePageUrl))) { 359 mReaderModePageUrl))) {
483 tabInfo.setStatus(NOT_POSSIBLE); 360 tabInfo.setStatus(NOT_POSSIBLE);
484 mIsUmaRecorded = false; 361 mIsUmaRecorded = false;
485 } 362 }
486 mReaderModePageUrl = null; 363 mReaderModePageUrl = null;
487 364
488 if (tabInfo.getStatus() != POSSIBLE) { 365 if (tabInfo.getStatus() != POSSIBLE) {
489 closeReaderPanel(StateChangeReason.UNKNOWN, false); 366 closeReaderPanel(StateChangeReason.UNKNOWN, false);
490 } else { 367 } else {
491 requestReaderPanelShow(StateChangeReason.UNKNOWN); 368 tryShowingInfoBar();
492 } 369 }
493 } 370 }
494 371
495 @Override 372 @Override
496 public void navigationEntryCommitted() { 373 public void navigationEntryCommitted() {
497 // Make sure the tab was not destroyed. 374 // Make sure the tab was not destroyed.
498 ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId); 375 ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId);
499 if (tabInfo == null) return; 376 if (tabInfo == null) return;
500 // Reset closed state of reader mode in this tab once we know a navigation is 377 // Reset closed state of reader mode in this tab once we know a navigation is
501 // happening. 378 // happening.
502 tabInfo.setIsDismissed(false); 379 tabInfo.setIsDismissed(false);
503 380
504 // If the panel was not shown for the previous navigation, recor d it now. 381 // If the panel was not shown for the previous navigation, recor d it now.
505 Tab curTab = mTabModelSelector.getTabById(readerTabId); 382 Tab curTab = mTabModelSelector.getTabById(readerTabId);
506 if (curTab != null && !curTab.isNativePage() && !curTab.isBeingR estored()) { 383 if (curTab != null && !curTab.isNativePage() && !curTab.isBeingR estored()) {
507 recordPanelVisibilityForNavigation(false); 384 recordPanelVisibilityForNavigation(false);
508 } 385 }
509 tabInfo.setIsPanelShowRecorded(false); 386 tabInfo.setIsPanelShowRecorded(false);
510 } 387 }
511 }; 388 };
512 } 389 }
513 390
514 /** 391 /**
515 * This is a wrapper for "requestPanelShow" that checks if reader mode is po ssible before 392 * Try showing the reader mode infobar.
516 * showing.
517 * @param reason The reason the panel is requesting to be shown.
518 */ 393 */
519 protected void requestReaderPanelShow(StateChangeReason reason) { 394 protected void tryShowingInfoBar() {
520 if (mTabModelSelector == null) return; 395 if (mTabModelSelector == null) return;
521 396
522 int currentTabId = mTabModelSelector.getCurrentTabId(); 397 int currentTabId = mTabModelSelector.getCurrentTabId();
523 if (currentTabId == Tab.INVALID_TAB_ID) return; 398 if (currentTabId == Tab.INVALID_TAB_ID) return;
524 399
525 // Test if the user is requesting the desktop site. Ignore this if disti ller is set to 400 // Test if the user is requesting the desktop site. Ignore this if disti ller is set to
526 // ALWAYS_TRUE. 401 // ALWAYS_TRUE.
527 boolean usingRequestDesktopSite = getBasePageWebContents() != null 402 boolean usingRequestDesktopSite = getBasePageWebContents() != null
528 && getBasePageWebContents().getNavigationController().getUseDesk topUserAgent() 403 && getBasePageWebContents().getNavigationController().getUseDesk topUserAgent()
529 && !mIsReaderHeuristicAlwaysTrue; 404 && !mIsReaderHeuristicAlwaysTrue;
530 405
531 if (mReaderModePanel == null || !mTabStatusMap.containsKey(currentTabId) 406 if (!mTabStatusMap.containsKey(currentTabId) || usingRequestDesktopSite
532 || usingRequestDesktopSite
533 || mTabStatusMap.get(currentTabId).getStatus() != POSSIBLE 407 || mTabStatusMap.get(currentTabId).getStatus() != POSSIBLE
534 || mTabStatusMap.get(currentTabId).isDismissed() 408 || mTabStatusMap.get(currentTabId).isDismissed()
535 || mIsInfoBarContainerShown
536 || mIsFindToolbarShowing
537 || mIsFullscreenModeEntered
538 || mIsKeyboardShowing
539 || AccessibilityUtil.isAccessibilityEnabled()) { 409 || AccessibilityUtil.isAccessibilityEnabled()) {
540 return; 410 return;
541 } 411 }
542 412
543 mReaderModePanel.requestPanelShow(reason); 413 ReaderModeInfoBar.showReaderModeInfoBar(mTabModelSelector.getCurrentTab( ), this);
544 } 414 }
545 415
546 /** 416 /**
417 * Navigate the current tab to a Reader Mode URL.
418 */
419 public void navigateToReaderMode() {
420 RecordHistogram.recordBooleanHistogram("DomDistiller.InfoBarUsage", true );
421
422 WebContents baseWebContents = getBasePageWebContents();
423 if (baseWebContents == null || mChromeActivity == null || mTabModelSelec tor == null) return;
424
425 String url = baseWebContents.getUrl();
426 if (url == null) return;
427
428 DomDistillerTabUtils.distillCurrentPageAndView(getBasePageWebContents()) ;
429 }
430
431 /**
547 * Open a link from the panel in a new tab. 432 * Open a link from the panel in a new tab.
548 * @param url The URL to load. 433 * @param url The URL to load.
549 */ 434 */
550 @Override 435 @Override
551 public void createNewTab(String url) { 436 public void createNewTab(String url) {
552 if (mChromeActivity == null) return; 437 if (mChromeActivity == null) return;
553 438
554 Tab currentTab = mTabModelSelector.getCurrentTab(); 439 Tab currentTab = mTabModelSelector.getCurrentTab();
555 if (currentTab == null) return; 440 if (currentTab == null) return;
556 441
557 TabCreatorManager.TabCreator tabCreator = 442 TabCreatorManager.TabCreator tabCreator =
558 mChromeActivity.getTabCreator(currentTab.isIncognito()); 443 mChromeActivity.getTabCreator(currentTab.isIncognito());
559 if (tabCreator == null) return; 444 if (tabCreator == null) return;
560 445
561 tabCreator.createNewTab(new LoadUrlParams(url, PageTransition.LINK), 446 tabCreator.createNewTab(new LoadUrlParams(url, PageTransition.LINK),
562 TabModel.TabLaunchType.FROM_LINK, mChromeActivity.getActivityTab ()); 447 TabModel.TabLaunchType.FROM_LINK, mChromeActivity.getActivityTab ());
563 } 448 }
564 449
565 /** 450 /**
566 * @return Whether the Reader Mode panel is opened (state is EXPANDED or MAX IMIZED).
567 */
568 public boolean isPanelOpened() {
569 if (mReaderModePanel == null) return false;
570 return mReaderModePanel.isPanelOpened();
571 }
572
573 /**
574 * @return The ReaderModePanel for testing.
575 */
576 @VisibleForTesting
577 public ReaderModePanel getPanelForTesting() {
578 return mReaderModePanel;
579 }
580
581 /**
582 * Set the callback for updating reader mode status based on whether or not the page should 451 * Set the callback for updating reader mode status based on whether or not the page should
583 * be viewed in reader mode. 452 * be viewed in reader mode.
584 * @param tabId The ID of the tab having its callback set. 453 * @param tabId The ID of the tab having its callback set.
585 */ 454 */
586 private void setDistillabilityCallback(final int tabId) { 455 private void setDistillabilityCallback(final int tabId) {
587 if (tabId == Tab.INVALID_TAB_ID || mTabStatusMap.get(tabId).isCallbackSe t()) { 456 if (tabId == Tab.INVALID_TAB_ID || mTabStatusMap.get(tabId).isCallbackSe t()) {
588 return; 457 return;
589 } 458 }
590 459
591 if (mTabModelSelector == null) return; 460 if (mTabModelSelector == null) return;
(...skipping 18 matching lines...) Expand all
610 // destroyed so that this never happens. 479 // destroyed so that this never happens.
611 if (readerTab == null || tabInfo == null) return; 480 if (readerTab == null || tabInfo == null) return;
612 481
613 // Make sure the page didn't navigate while waiting for a response. 482 // Make sure the page didn't navigate while waiting for a response.
614 if (!readerTab.getUrl().equals(tabInfo.getUrl())) return ; 483 if (!readerTab.getUrl().equals(tabInfo.getUrl())) return ;
615 484
616 if (isDistillable) { 485 if (isDistillable) {
617 tabInfo.setStatus(POSSIBLE); 486 tabInfo.setStatus(POSSIBLE);
618 // The user may have changed tabs. 487 // The user may have changed tabs.
619 if (tabId == mTabModelSelector.getCurrentTabId()) { 488 if (tabId == mTabModelSelector.getCurrentTabId()) {
620 // TODO(mdjones): Add reason DISTILLER_STATE_CHA NGE. 489 tryShowingInfoBar();
621 requestReaderPanelShow(StateChangeReason.UNKNOWN );
622 } 490 }
623 } else { 491 } else {
624 tabInfo.setStatus(NOT_POSSIBLE); 492 tabInfo.setStatus(NOT_POSSIBLE);
625 } 493 }
626 if (!mIsUmaRecorded && (tabInfo.getStatus() == POSSIBLE || isLast)) { 494 if (!mIsUmaRecorded && (tabInfo.getStatus() == POSSIBLE || isLast)) {
627 mIsUmaRecorded = true; 495 mIsUmaRecorded = true;
628 RecordHistogram.recordBooleanHistogram( 496 RecordHistogram.recordBooleanHistogram(
629 "DomDistiller.PageDistillable", 497 "DomDistiller.PageDistillable",
630 tabInfo.getStatus() == POSSIBLE); 498 tabInfo.getStatus() == POSSIBLE);
631 } 499 }
632 } 500 }
633 }); 501 });
634 mTabStatusMap.get(tabId).setIsCallbackSet(true); 502 mTabStatusMap.get(tabId).setIsCallbackSet(true);
635 } 503 }
636 504
637 /** 505 /**
638 * @return Whether Reader mode and its new UI are enabled. 506 * @return Whether Reader mode and its new UI are enabled.
639 * @param context A context 507 * @param context A context
640 */ 508 */
641 public static boolean isEnabled(Context context) { 509 public static boolean isEnabled(Context context) {
642 if (context == null) return false; 510 if (context == null) return false;
643 511
644 boolean enabled = CommandLine.getInstance().hasSwitch(ChromeSwitches.ENA BLE_DOM_DISTILLER) 512 boolean enabled = CommandLine.getInstance().hasSwitch(ChromeSwitches.ENA BLE_DOM_DISTILLER)
645 && !CommandLine.getInstance().hasSwitch( 513 && !CommandLine.getInstance().hasSwitch(
646 ChromeSwitches.DISABLE_READER_MODE_BOTTOM_BAR) 514 ChromeSwitches.DISABLE_READER_MODE_BOTTOM_BAR)
647 && !DeviceFormFactor.isTablet(context) 515 && DomDistillerTabUtils.isDistillerHeuristicsEnabled();
648 && DomDistillerTabUtils.isDistillerHeuristicsEnabled()
649 && !SysUtils.isLowEndDevice();
650 return enabled; 516 return enabled;
651 } 517 }
652 } 518 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698