OLD | NEW |
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.library_loader.LibraryLoader; | |
12 import org.chromium.base.metrics.RecordHistogram; | 11 import org.chromium.base.metrics.RecordHistogram; |
13 import org.chromium.chrome.browser.ChromeActivity; | 12 import org.chromium.chrome.browser.ChromeActivity; |
14 import org.chromium.chrome.browser.ChromeSwitches; | 13 import org.chromium.chrome.browser.ChromeSwitches; |
15 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChange
Reason; | 14 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChange
Reason; |
16 import org.chromium.chrome.browser.infobar.ReaderModeInfoBar; | 15 import org.chromium.chrome.browser.infobar.ReaderModeInfoBar; |
17 import org.chromium.chrome.browser.rappor.RapporServiceBridge; | |
18 import org.chromium.chrome.browser.tab.Tab; | 16 import org.chromium.chrome.browser.tab.Tab; |
19 import org.chromium.chrome.browser.tabmodel.TabCreatorManager; | |
20 import org.chromium.chrome.browser.tabmodel.TabModel; | |
21 import org.chromium.chrome.browser.tabmodel.TabModelSelector; | 17 import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
22 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; | 18 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; |
23 import org.chromium.chrome.browser.util.AccessibilityUtil; | 19 import org.chromium.chrome.browser.util.AccessibilityUtil; |
24 import org.chromium.components.dom_distiller.content.DistillablePageUtils; | 20 import org.chromium.components.dom_distiller.content.DistillablePageUtils; |
25 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; | 21 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; |
26 import org.chromium.content_public.browser.LoadUrlParams; | |
27 import org.chromium.content_public.browser.NavigationController; | 22 import org.chromium.content_public.browser.NavigationController; |
28 import org.chromium.content_public.browser.NavigationEntry; | 23 import org.chromium.content_public.browser.NavigationEntry; |
29 import org.chromium.content_public.browser.WebContents; | 24 import org.chromium.content_public.browser.WebContents; |
30 import org.chromium.content_public.browser.WebContentsObserver; | 25 import org.chromium.content_public.browser.WebContentsObserver; |
31 import org.chromium.ui.UiUtils; | 26 import org.chromium.ui.UiUtils; |
32 import org.chromium.ui.base.PageTransition; | |
33 | 27 |
34 import java.util.HashMap; | 28 import java.util.HashMap; |
35 import java.util.Map; | 29 import java.util.Map; |
36 import java.util.concurrent.TimeUnit; | 30 import java.util.concurrent.TimeUnit; |
37 | 31 |
38 /** | 32 /** |
39 * Manages UI effects for reader mode including hiding and showing the | 33 * Manages UI effects for reader mode including hiding and showing the |
40 * reader mode and reader mode preferences toolbar icon and hiding the | 34 * reader mode and reader mode preferences toolbar icon and hiding the |
41 * browser controls when a reader mode page has finished loading. | 35 * browser controls when a reader mode page has finished loading. |
42 */ | 36 */ |
43 public class ReaderModeManager | 37 public class ReaderModeManager extends TabModelSelectorTabObserver { |
44 extends TabModelSelectorTabObserver implements ReaderModeManagerDelegate
{ | |
45 /** POSSIBLE means reader mode can be entered. */ | 38 /** POSSIBLE means reader mode can be entered. */ |
46 public static final int POSSIBLE = 0; | 39 public static final int POSSIBLE = 0; |
47 | 40 |
48 /** NOT_POSSIBLE means reader mode cannot be entered. */ | 41 /** NOT_POSSIBLE means reader mode cannot be entered. */ |
49 public static final int NOT_POSSIBLE = 1; | 42 public static final int NOT_POSSIBLE = 1; |
50 | 43 |
51 /** STARTED means reader mode is currently in reader mode. */ | 44 /** STARTED means reader mode is currently in reader mode. */ |
52 public static final int STARTED = 2; | 45 public static final int STARTED = 2; |
53 | 46 |
54 /** The url of the last page visited if the last page was reader mode page.
Otherwise null. */ | 47 /** The url of the last page visited if the last page was reader mode page.
Otherwise null. */ |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 } | 134 } |
142 | 135 |
143 // Make sure there is a distillability delegate set on the WebContents. | 136 // Make sure there is a distillability delegate set on the WebContents. |
144 setDistillabilityCallback(shownTabId); | 137 setDistillabilityCallback(shownTabId); |
145 | 138 |
146 tryShowingInfoBar(); | 139 tryShowingInfoBar(); |
147 } | 140 } |
148 | 141 |
149 @Override | 142 @Override |
150 public void onHidden(Tab tab) { | 143 public void onHidden(Tab tab) { |
151 closeReaderPanel(StateChangeReason.UNKNOWN, false); | |
152 ReaderModeTabInfo info = mTabStatusMap.get(tab.getId()); | 144 ReaderModeTabInfo info = mTabStatusMap.get(tab.getId()); |
153 if (info != null && info.isViewingReaderModePage()) { | 145 if (info != null && info.isViewingReaderModePage()) { |
154 long timeMs = info.onExitReaderMode(); | 146 long timeMs = info.onExitReaderMode(); |
155 recordReaderModeViewDuration(timeMs); | 147 recordReaderModeViewDuration(timeMs); |
156 } | 148 } |
157 } | 149 } |
158 | 150 |
159 @Override | 151 @Override |
160 public void onDestroyed(Tab tab) { | 152 public void onDestroyed(Tab tab) { |
161 if (tab == null) return; | 153 if (tab == null) return; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 // need to be preserved. | 197 // need to be preserved. |
206 tabInfo.setStatus(NOT_POSSIBLE); | 198 tabInfo.setStatus(NOT_POSSIBLE); |
207 tabInfo.setUrl(tab.getUrl()); | 199 tabInfo.setUrl(tab.getUrl()); |
208 tabInfo.setIsCallbackSet(false); | 200 tabInfo.setIsCallbackSet(false); |
209 | 201 |
210 if (tab.getWebContents() != null) { | 202 if (tab.getWebContents() != null) { |
211 tabInfo.setWebContentsObserver(createWebContentsObserver(tab.getWebC
ontents())); | 203 tabInfo.setWebContentsObserver(createWebContentsObserver(tab.getWebC
ontents())); |
212 if (DomDistillerUrlUtils.isDistilledPage(tab.getUrl())) { | 204 if (DomDistillerUrlUtils.isDistilledPage(tab.getUrl())) { |
213 tabInfo.setStatus(STARTED); | 205 tabInfo.setStatus(STARTED); |
214 mReaderModePageUrl = tab.getUrl(); | 206 mReaderModePageUrl = tab.getUrl(); |
215 closeReaderPanel(StateChangeReason.CONTENT_CHANGED, true); | |
216 } | 207 } |
217 // Make sure there is a distillability delegate set on the WebConten
ts. | 208 // Make sure there is a distillability delegate set on the WebConten
ts. |
218 setDistillabilityCallback(tab.getId()); | 209 setDistillabilityCallback(tab.getId()); |
219 } | 210 } |
220 } | 211 } |
221 | 212 |
222 // ReaderModeManagerDelegate: | |
223 | |
224 @Override | |
225 public ChromeActivity getChromeActivity() { | |
226 return mChromeActivity; | |
227 } | |
228 | |
229 @Override | |
230 public void onPanelShown() { | |
231 if (mTabModelSelector == null) return; | |
232 int tabId = mTabModelSelector.getCurrentTabId(); | |
233 | |
234 ReaderModeTabInfo info = mTabStatusMap.get(tabId); | |
235 if (info != null && !info.isInfoBarShowRecorded()) { | |
236 info.setIsInfoBarShowRecorded(true); | |
237 recordInfoBarVisibilityForNavigation(true); | |
238 if (LibraryLoader.isInitialized()) { | |
239 RapporServiceBridge.sampleDomainAndRegistryFromURL( | |
240 "DomDistiller.PromptPanel", info.getUrl()); | |
241 } | |
242 } | |
243 } | |
244 | |
245 /** | 213 /** |
246 * Record if the infobar became visible on the current page. This can be ove
rridden for testing. | 214 * Record if the infobar became visible on the current page. This can be ove
rridden for testing. |
247 * @param visible If the infobar was visible at any time. | 215 * @param visible If the infobar was visible at any time. |
248 */ | 216 */ |
249 protected void recordInfoBarVisibilityForNavigation(boolean visible) { | 217 protected void recordInfoBarVisibilityForNavigation(boolean visible) { |
250 RecordHistogram.recordBooleanHistogram("DomDistiller.ReaderShownForPageL
oad", visible); | 218 RecordHistogram.recordBooleanHistogram("DomDistiller.ReaderShownForPageL
oad", visible); |
251 } | 219 } |
252 | 220 |
253 @Override | 221 /** |
| 222 * Notify the manager that the panel has completely closed. |
| 223 */ |
254 public void onClosed(StateChangeReason reason) { | 224 public void onClosed(StateChangeReason reason) { |
255 if (mTabModelSelector == null) return; | 225 if (mTabModelSelector == null) return; |
256 | 226 |
257 RecordHistogram.recordBooleanHistogram("DomDistiller.InfoBarUsage", fals
e); | 227 RecordHistogram.recordBooleanHistogram("DomDistiller.InfoBarUsage", fals
e); |
258 | 228 |
259 int currentTabId = mTabModelSelector.getCurrentTabId(); | 229 int currentTabId = mTabModelSelector.getCurrentTabId(); |
260 if (!mTabStatusMap.containsKey(currentTabId)) return; | 230 if (!mTabStatusMap.containsKey(currentTabId)) return; |
261 mTabStatusMap.get(currentTabId).setIsDismissed(true); | 231 mTabStatusMap.get(currentTabId).setIsDismissed(true); |
262 } | 232 } |
263 | 233 |
264 @Override | 234 /** |
| 235 * Get the WebContents of the page that is being distilled. |
| 236 * @return The WebContents for the currently visible tab. |
| 237 */ |
265 public WebContents getBasePageWebContents() { | 238 public WebContents getBasePageWebContents() { |
266 Tab tab = mTabModelSelector.getCurrentTab(); | 239 Tab tab = mTabModelSelector.getCurrentTab(); |
267 if (tab == null) return null; | 240 if (tab == null) return null; |
268 | 241 |
269 return tab.getWebContents(); | 242 return tab.getWebContents(); |
270 } | 243 } |
271 | 244 |
272 @Override | |
273 public void closeReaderPanel(StateChangeReason reason, boolean animate) { | |
274 // TODO(mdjones): Remove this method and dependencies. | |
275 } | |
276 | |
277 @Override | |
278 public void recordTimeSpentInReader(long timeMs) { | |
279 RecordHistogram.recordLongTimesHistogram("DomDistiller.Time.ViewingReade
rModePanel", | |
280 timeMs, TimeUnit.MILLISECONDS); | |
281 } | |
282 | |
283 /** | 245 /** |
284 * @return True if the keyboard might be showing. This is not 100% accurate;
see | 246 * @return True if the keyboard might be showing. This is not 100% accurate;
see |
285 * UiUtils.isKeyboardShowing(...). | 247 * UiUtils.isKeyboardShowing(...). |
286 */ | 248 */ |
287 protected boolean isKeyboardShowing() { | 249 protected boolean isKeyboardShowing() { |
288 return mChromeActivity != null && UiUtils.isKeyboardShowing(mChromeActiv
ity, | 250 return mChromeActivity != null && UiUtils.isKeyboardShowing(mChromeActiv
ity, |
289 mChromeActivity.findViewById(android.R.id.content)); | 251 mChromeActivity.findViewById(android.R.id.content)); |
290 } | 252 } |
291 | 253 |
292 protected WebContentsObserver createWebContentsObserver(final WebContents we
bContents) { | 254 protected WebContentsObserver createWebContentsObserver(final WebContents we
bContents) { |
(...skipping 16 matching lines...) Expand all Loading... |
309 // navigations and prepare to remove any that are "chrome-distil
ler" urls. | 271 // navigations and prepare to remove any that are "chrome-distil
ler" urls. |
310 NavigationController controller = webContents.getNavigationContr
oller(); | 272 NavigationController controller = webContents.getNavigationContr
oller(); |
311 int index = controller.getLastCommittedEntryIndex(); | 273 int index = controller.getLastCommittedEntryIndex(); |
312 NavigationEntry entry = controller.getEntryAtIndex(index); | 274 NavigationEntry entry = controller.getEntryAtIndex(index); |
313 | 275 |
314 if (entry != null && DomDistillerUrlUtils.isDistilledPage(entry.
getUrl())) { | 276 if (entry != null && DomDistillerUrlUtils.isDistilledPage(entry.
getUrl())) { |
315 mShouldRemovePreviousNavigation = true; | 277 mShouldRemovePreviousNavigation = true; |
316 mLastDistillerPageIndex = index; | 278 mLastDistillerPageIndex = index; |
317 } | 279 } |
318 | 280 |
319 // If there is a navigation in the current tab, hide the bar. It
will show again | |
320 // once the distillability test is successful. | |
321 if (readerTabId == mTabModelSelector.getCurrentTabId()) { | |
322 closeReaderPanel(StateChangeReason.TAB_NAVIGATION, false); | |
323 } | |
324 | |
325 // Make sure the tab was not destroyed. | 281 // Make sure the tab was not destroyed. |
326 ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId); | 282 ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId); |
327 if (tabInfo == null) return; | 283 if (tabInfo == null) return; |
328 | 284 |
329 tabInfo.setUrl(url); | 285 tabInfo.setUrl(url); |
330 if (DomDistillerUrlUtils.isDistilledPage(url)) { | 286 if (DomDistillerUrlUtils.isDistilledPage(url)) { |
331 tabInfo.setStatus(STARTED); | 287 tabInfo.setStatus(STARTED); |
332 mReaderModePageUrl = url; | 288 mReaderModePageUrl = url; |
333 } | 289 } |
334 } | 290 } |
(...skipping 19 matching lines...) Expand all Loading... |
354 | 310 |
355 tabInfo.setStatus(POSSIBLE); | 311 tabInfo.setStatus(POSSIBLE); |
356 if (!TextUtils.equals(url, | 312 if (!TextUtils.equals(url, |
357 DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl( | 313 DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl( |
358 mReaderModePageUrl))) { | 314 mReaderModePageUrl))) { |
359 tabInfo.setStatus(NOT_POSSIBLE); | 315 tabInfo.setStatus(NOT_POSSIBLE); |
360 mIsUmaRecorded = false; | 316 mIsUmaRecorded = false; |
361 } | 317 } |
362 mReaderModePageUrl = null; | 318 mReaderModePageUrl = null; |
363 | 319 |
364 if (tabInfo.getStatus() != POSSIBLE) { | 320 if (tabInfo.getStatus() == POSSIBLE) tryShowingInfoBar(); |
365 closeReaderPanel(StateChangeReason.UNKNOWN, false); | |
366 } else { | |
367 tryShowingInfoBar(); | |
368 } | |
369 } | 321 } |
370 | 322 |
371 @Override | 323 @Override |
372 public void navigationEntryCommitted() { | 324 public void navigationEntryCommitted() { |
373 // Make sure the tab was not destroyed. | 325 // Make sure the tab was not destroyed. |
374 ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId); | 326 ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId); |
375 if (tabInfo == null) return; | 327 if (tabInfo == null) return; |
376 // Reset closed state of reader mode in this tab once we know a
navigation is | 328 // Reset closed state of reader mode in this tab once we know a
navigation is |
377 // happening. | 329 // happening. |
378 tabInfo.setIsDismissed(false); | 330 tabInfo.setIsDismissed(false); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 String url = baseWebContents.getUrl(); | 391 String url = baseWebContents.getUrl(); |
440 if (url == null) return; | 392 if (url == null) return; |
441 | 393 |
442 ReaderModeTabInfo info = mTabStatusMap.get(mTabModelSelector.getCurrentT
abId()); | 394 ReaderModeTabInfo info = mTabStatusMap.get(mTabModelSelector.getCurrentT
abId()); |
443 if (info != null) info.onStartedReaderMode(); | 395 if (info != null) info.onStartedReaderMode(); |
444 | 396 |
445 DomDistillerTabUtils.distillCurrentPageAndView(getBasePageWebContents())
; | 397 DomDistillerTabUtils.distillCurrentPageAndView(getBasePageWebContents())
; |
446 } | 398 } |
447 | 399 |
448 /** | 400 /** |
449 * Open a link from the infobar in a new tab. | |
450 * @param url The URL to load. | |
451 */ | |
452 @Override | |
453 public void createNewTab(String url) { | |
454 if (mChromeActivity == null) return; | |
455 | |
456 Tab currentTab = mTabModelSelector.getCurrentTab(); | |
457 if (currentTab == null) return; | |
458 | |
459 TabCreatorManager.TabCreator tabCreator = | |
460 mChromeActivity.getTabCreator(currentTab.isIncognito()); | |
461 if (tabCreator == null) return; | |
462 | |
463 tabCreator.createNewTab(new LoadUrlParams(url, PageTransition.LINK), | |
464 TabModel.TabLaunchType.FROM_LINK, mChromeActivity.getActivityTab
()); | |
465 } | |
466 | |
467 /** | |
468 * Set the callback for updating reader mode status based on whether or not
the page should | 401 * Set the callback for updating reader mode status based on whether or not
the page should |
469 * be viewed in reader mode. | 402 * be viewed in reader mode. |
470 * @param tabId The ID of the tab having its callback set. | 403 * @param tabId The ID of the tab having its callback set. |
471 */ | 404 */ |
472 private void setDistillabilityCallback(final int tabId) { | 405 private void setDistillabilityCallback(final int tabId) { |
473 if (tabId == Tab.INVALID_TAB_ID || mTabStatusMap.get(tabId).isCallbackSe
t()) { | 406 if (tabId == Tab.INVALID_TAB_ID || mTabStatusMap.get(tabId).isCallbackSe
t()) { |
474 return; | 407 return; |
475 } | 408 } |
476 | 409 |
477 if (mTabModelSelector == null) return; | 410 if (mTabModelSelector == null) return; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 public static boolean isEnabled(Context context) { | 459 public static boolean isEnabled(Context context) { |
527 if (context == null) return false; | 460 if (context == null) return false; |
528 | 461 |
529 boolean enabled = CommandLine.getInstance().hasSwitch(ChromeSwitches.ENA
BLE_DOM_DISTILLER) | 462 boolean enabled = CommandLine.getInstance().hasSwitch(ChromeSwitches.ENA
BLE_DOM_DISTILLER) |
530 && !CommandLine.getInstance().hasSwitch( | 463 && !CommandLine.getInstance().hasSwitch( |
531 ChromeSwitches.DISABLE_READER_MODE_BOTTOM_BAR) | 464 ChromeSwitches.DISABLE_READER_MODE_BOTTOM_BAR) |
532 && DomDistillerTabUtils.isDistillerHeuristicsEnabled(); | 465 && DomDistillerTabUtils.isDistillerHeuristicsEnabled(); |
533 return enabled; | 466 return enabled; |
534 } | 467 } |
535 } | 468 } |
OLD | NEW |