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.ntp; | 5 package org.chromium.chrome.browser.ntp; |
6 | 6 |
7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
8 import android.content.Context; | 8 import android.content.Context; |
9 import android.graphics.Canvas; | 9 import android.graphics.Canvas; |
10 import android.graphics.Point; | 10 import android.graphics.Point; |
11 import android.graphics.Rect; | 11 import android.graphics.Rect; |
12 import android.net.Uri; | 12 import android.net.Uri; |
13 import android.os.Build; | 13 import android.os.Build; |
14 import android.os.SystemClock; | 14 import android.os.SystemClock; |
15 import android.support.v4.view.ViewCompat; | 15 import android.support.v4.view.ViewCompat; |
16 import android.support.v7.widget.RecyclerView; | |
16 import android.view.ContextMenu; | 17 import android.view.ContextMenu; |
17 import android.view.LayoutInflater; | 18 import android.view.LayoutInflater; |
18 import android.view.Menu; | 19 import android.view.Menu; |
19 import android.view.MenuItem.OnMenuItemClickListener; | 20 import android.view.MenuItem.OnMenuItemClickListener; |
20 import android.view.View; | 21 import android.view.View; |
21 | 22 |
22 import org.chromium.base.ApiCompatibilityUtils; | 23 import org.chromium.base.ApiCompatibilityUtils; |
23 import org.chromium.base.Callback; | 24 import org.chromium.base.Callback; |
24 import org.chromium.base.CommandLine; | 25 import org.chromium.base.CommandLine; |
26 import org.chromium.base.Log; | |
25 import org.chromium.base.ThreadUtils; | 27 import org.chromium.base.ThreadUtils; |
26 import org.chromium.base.VisibleForTesting; | 28 import org.chromium.base.VisibleForTesting; |
27 import org.chromium.base.metrics.RecordHistogram; | 29 import org.chromium.base.metrics.RecordHistogram; |
28 import org.chromium.base.metrics.RecordUserAction; | 30 import org.chromium.base.metrics.RecordUserAction; |
29 import org.chromium.chrome.R; | 31 import org.chromium.chrome.R; |
30 import org.chromium.chrome.browser.ChromeActivity; | 32 import org.chromium.chrome.browser.ChromeActivity; |
31 import org.chromium.chrome.browser.ChromeFeatureList; | 33 import org.chromium.chrome.browser.ChromeFeatureList; |
32 import org.chromium.chrome.browser.ChromeSwitches; | 34 import org.chromium.chrome.browser.ChromeSwitches; |
33 import org.chromium.chrome.browser.NativePage; | 35 import org.chromium.chrome.browser.NativePage; |
34 import org.chromium.chrome.browser.UrlConstants; | 36 import org.chromium.chrome.browser.UrlConstants; |
(...skipping 27 matching lines...) Expand all Loading... | |
62 import org.chromium.chrome.browser.tab.EmptyTabObserver; | 64 import org.chromium.chrome.browser.tab.EmptyTabObserver; |
63 import org.chromium.chrome.browser.tab.Tab; | 65 import org.chromium.chrome.browser.tab.Tab; |
64 import org.chromium.chrome.browser.tab.TabObserver; | 66 import org.chromium.chrome.browser.tab.TabObserver; |
65 import org.chromium.chrome.browser.tabmodel.TabModel; | 67 import org.chromium.chrome.browser.tabmodel.TabModel; |
66 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; | 68 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; |
67 import org.chromium.chrome.browser.tabmodel.TabModelSelector; | 69 import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
68 import org.chromium.chrome.browser.tabmodel.TabModelUtils; | 70 import org.chromium.chrome.browser.tabmodel.TabModelUtils; |
69 import org.chromium.chrome.browser.tabmodel.document.TabDelegate; | 71 import org.chromium.chrome.browser.tabmodel.document.TabDelegate; |
70 import org.chromium.chrome.browser.util.UrlUtilities; | 72 import org.chromium.chrome.browser.util.UrlUtilities; |
71 import org.chromium.content_public.browser.LoadUrlParams; | 73 import org.chromium.content_public.browser.LoadUrlParams; |
74 import org.chromium.content_public.browser.NavigationController; | |
75 import org.chromium.content_public.browser.NavigationEntry; | |
72 import org.chromium.content_public.common.Referrer; | 76 import org.chromium.content_public.common.Referrer; |
73 import org.chromium.net.NetworkChangeNotifier; | 77 import org.chromium.net.NetworkChangeNotifier; |
74 import org.chromium.ui.base.DeviceFormFactor; | 78 import org.chromium.ui.base.DeviceFormFactor; |
75 import org.chromium.ui.base.PageTransition; | 79 import org.chromium.ui.base.PageTransition; |
76 import org.chromium.ui.mojom.WindowOpenDisposition; | 80 import org.chromium.ui.mojom.WindowOpenDisposition; |
77 | 81 |
78 import java.util.HashSet; | 82 import java.util.HashSet; |
79 import java.util.Set; | 83 import java.util.Set; |
80 import java.util.concurrent.TimeUnit; | 84 import java.util.concurrent.TimeUnit; |
81 | 85 |
82 import jp.tomorrowkey.android.gifplayer.BaseGifImage; | 86 import jp.tomorrowkey.android.gifplayer.BaseGifImage; |
83 | 87 |
84 /** | 88 /** |
85 * Provides functionality when the user interacts with the NTP. | 89 * Provides functionality when the user interacts with the NTP. |
86 */ | 90 */ |
87 public class NewTabPage | 91 public class NewTabPage |
88 implements NativePage, InvalidationAwareThumbnailProvider, TemplateUrlSe rviceObserver { | 92 implements NativePage, InvalidationAwareThumbnailProvider, TemplateUrlSe rviceObserver { |
93 private static final String TAG = "NewTabPage"; | |
89 | 94 |
90 // MostVisitedItem Context menu item IDs. | 95 // MostVisitedItem Context menu item IDs. |
91 static final int ID_OPEN_IN_NEW_WINDOW = 0; | 96 static final int ID_OPEN_IN_NEW_WINDOW = 0; |
92 static final int ID_OPEN_IN_NEW_TAB = 1; | 97 static final int ID_OPEN_IN_NEW_TAB = 1; |
93 static final int ID_OPEN_IN_INCOGNITO_TAB = 2; | 98 static final int ID_OPEN_IN_INCOGNITO_TAB = 2; |
94 static final int ID_REMOVE = 3; | 99 static final int ID_REMOVE = 3; |
95 | 100 |
96 // UMA enum constants. CTA means the "click-to-action" icon. | 101 // UMA enum constants. CTA means the "click-to-action" icon. |
97 private static final String LOGO_SHOWN_UMA_NAME = "NewTabPage.LogoShown"; | 102 private static final String LOGO_SHOWN_UMA_NAME = "NewTabPage.LogoShown"; |
98 private static final int STATIC_LOGO_SHOWN = 0; | 103 private static final int STATIC_LOGO_SHOWN = 0; |
99 private static final int CTA_IMAGE_SHOWN = 1; | 104 private static final int CTA_IMAGE_SHOWN = 1; |
100 | 105 |
101 private static final String LOGO_CLICK_UMA_NAME = "NewTabPage.LogoClick"; | 106 private static final String LOGO_CLICK_UMA_NAME = "NewTabPage.LogoClick"; |
102 private static final int STATIC_LOGO_CLICKED = 0; | 107 private static final int STATIC_LOGO_CLICKED = 0; |
103 private static final int CTA_IMAGE_CLICKED = 1; | 108 private static final int CTA_IMAGE_CLICKED = 1; |
104 private static final int ANIMATED_LOGO_CLICKED = 2; | 109 private static final int ANIMATED_LOGO_CLICKED = 2; |
105 | 110 |
111 // Key for the scroll position data that may be stored in a navigation entry . | |
112 private static final String NAVIGATION_ENTRY_SCROLL_POSITION_KEY = "NewTabPa geScrollPosition"; | |
113 | |
106 private static final String CHROME_CONTENT_SUGGESTIONS_REFERRER = | 114 private static final String CHROME_CONTENT_SUGGESTIONS_REFERRER = |
107 "https://www.googleapis.com/auth/chrome-content-suggestions"; | 115 "https://www.googleapis.com/auth/chrome-content-suggestions"; |
108 | 116 |
109 private static MostVisitedSites sMostVisitedSitesForTests; | 117 private static MostVisitedSites sMostVisitedSitesForTests; |
110 | 118 |
111 private final Tab mTab; | 119 private final Tab mTab; |
112 private final TabModelSelector mTabModelSelector; | 120 private final TabModelSelector mTabModelSelector; |
113 private final ChromeActivity mActivity; | 121 private final ChromeActivity mActivity; |
114 | 122 |
115 private final Profile mProfile; | 123 private final Profile mProfile; |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
658 @Override | 666 @Override |
659 public void onShown(Tab tab) { | 667 public void onShown(Tab tab) { |
660 // Showing the NTP is only meaningful when the page has been loa ded already. | 668 // Showing the NTP is only meaningful when the page has been loa ded already. |
661 if (mIsLoaded) recordNTPShown(); | 669 if (mIsLoaded) recordNTPShown(); |
662 } | 670 } |
663 | 671 |
664 @Override | 672 @Override |
665 public void onHidden(Tab tab) { | 673 public void onHidden(Tab tab) { |
666 if (mIsLoaded) recordNTPInteractionTime(); | 674 if (mIsLoaded) recordNTPInteractionTime(); |
667 } | 675 } |
676 | |
677 @Override | |
678 public void onPageLoadStarted(Tab tab, String url) { | |
679 int scrollPosition = mNewTabPageView.getScrollPosition(); | |
680 if (scrollPosition == RecyclerView.NO_POSITION) return; | |
681 | |
682 if (mTab.getWebContents() == null) return; | |
683 | |
684 NavigationController controller = mTab.getWebContents().getNavig ationController(); | |
685 int index = controller.getLastCommittedEntryIndex(); | |
686 NavigationEntry entry = controller.getEntryAtIndex(index); | |
687 if (entry == null) return; | |
688 | |
689 assert isNTPUrl(entry.getUrl()); | |
690 controller.setEntryExtraData(index, NAVIGATION_ENTRY_SCROLL_POSI TION_KEY, | |
691 Integer.toString(scrollPosition)); | |
692 } | |
668 }; | 693 }; |
669 mTab.addObserver(mTabObserver); | 694 mTab.addObserver(mTabObserver); |
670 mMostVisitedSites = buildMostVisitedSites(mProfile); | 695 mMostVisitedSites = buildMostVisitedSites(mProfile); |
671 mLogoBridge = new LogoBridge(mProfile); | 696 mLogoBridge = new LogoBridge(mProfile); |
672 updateSearchProviderHasLogo(); | 697 updateSearchProviderHasLogo(); |
673 | 698 |
674 if (SnippetsConfig.isEnabled()) { | 699 if (SnippetsConfig.isEnabled()) { |
675 mSnippetsBridge = new SnippetsBridge(mProfile); | 700 mSnippetsBridge = new SnippetsBridge(mProfile); |
676 } | 701 } |
677 | 702 |
678 LayoutInflater inflater = LayoutInflater.from(activity); | 703 LayoutInflater inflater = LayoutInflater.from(activity); |
679 mNewTabPageView = (NewTabPageView) inflater.inflate(R.layout.new_tab_pag e_view, null); | 704 mNewTabPageView = (NewTabPageView) inflater.inflate(R.layout.new_tab_pag e_view, null); |
680 mNewTabPageView.initialize(mNewTabPageManager, mSearchProviderHasLogo, m SnippetsBridge); | 705 mNewTabPageView.initialize(mNewTabPageManager, mSearchProviderHasLogo, m SnippetsBridge, |
706 getScrollPositionFromNavigationEntry()); | |
681 | 707 |
682 RecordHistogram.recordBooleanHistogram( | 708 RecordHistogram.recordBooleanHistogram( |
683 "NewTabPage.MobileIsUserOnline", NetworkChangeNotifier.isOnline( )); | 709 "NewTabPage.MobileIsUserOnline", NetworkChangeNotifier.isOnline( )); |
684 } | 710 } |
685 | 711 |
686 private static MostVisitedSites buildMostVisitedSites(Profile profile) { | 712 private static MostVisitedSites buildMostVisitedSites(Profile profile) { |
687 if (sMostVisitedSitesForTests != null) { | 713 if (sMostVisitedSitesForTests != null) { |
688 return sMostVisitedSitesForTests; | 714 return sMostVisitedSitesForTests; |
689 } else { | 715 } else { |
690 return new MostVisitedSites(profile); | 716 return new MostVisitedSites(profile); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
830 mLastShownTimeNs = System.nanoTime(); | 856 mLastShownTimeNs = System.nanoTime(); |
831 RecordUserAction.record("MobileNTPShown"); | 857 RecordUserAction.record("MobileNTPShown"); |
832 } | 858 } |
833 | 859 |
834 private void recordNTPInteractionTime() { | 860 private void recordNTPInteractionTime() { |
835 RecordHistogram.recordMediumTimesHistogram( | 861 RecordHistogram.recordMediumTimesHistogram( |
836 "NewTabPage.TimeSpent", System.nanoTime() - mLastShownTimeNs, Ti meUnit.NANOSECONDS); | 862 "NewTabPage.TimeSpent", System.nanoTime() - mLastShownTimeNs, Ti meUnit.NANOSECONDS); |
837 } | 863 } |
838 | 864 |
839 /** | 865 /** |
866 * Returns the value of the adapter scroll position that was stored in the l ast committed | |
867 * navigation entry. Returns {@code RecyclerView.NO_POSITION} if there is no last committed | |
868 * navigation entry, or if no data is found. | |
869 * @return The adapter scroll position. | |
870 */ | |
871 private int getScrollPositionFromNavigationEntry() { | |
872 if (mTab.getWebContents() == null) return RecyclerView.NO_POSITION; | |
873 | |
874 NavigationController controller = mTab.getWebContents().getNavigationCon troller(); | |
875 int index = controller.getLastCommittedEntryIndex(); | |
876 String scrollPositionData = | |
877 controller.getEntryExtraData(index, NAVIGATION_ENTRY_SCROLL_POSI TION_KEY); | |
878 if (scrollPositionData == null) return RecyclerView.NO_POSITION; | |
Ted C
2016/09/26 18:40:26
I was testing locally and got this stack:
W/cr_New
Michael van Ouwerkerk
2016/09/27 14:36:58
Agreed, done.
| |
879 | |
880 try { | |
881 return Integer.parseInt(scrollPositionData); | |
882 } catch (NumberFormatException e) { | |
883 Log.w(TAG, "Bad data found for scroll position: %s", scrollPositionD ata, e); | |
884 return RecyclerView.NO_POSITION; | |
885 } | |
886 } | |
887 | |
888 /** | |
840 * @return Whether the NTP has finished loaded. | 889 * @return Whether the NTP has finished loaded. |
841 */ | 890 */ |
842 @VisibleForTesting | 891 @VisibleForTesting |
843 public boolean isLoadedForTests() { | 892 public boolean isLoadedForTests() { |
844 return mIsLoaded; | 893 return mIsLoaded; |
845 } | 894 } |
846 | 895 |
847 // TemplateUrlServiceObserver overrides | 896 // TemplateUrlServiceObserver overrides |
848 | 897 |
849 @Override | 898 @Override |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
935 @Override | 984 @Override |
936 public boolean shouldCaptureThumbnail() { | 985 public boolean shouldCaptureThumbnail() { |
937 return mNewTabPageView.shouldCaptureThumbnail(); | 986 return mNewTabPageView.shouldCaptureThumbnail(); |
938 } | 987 } |
939 | 988 |
940 @Override | 989 @Override |
941 public void captureThumbnail(Canvas canvas) { | 990 public void captureThumbnail(Canvas canvas) { |
942 mNewTabPageView.captureThumbnail(canvas); | 991 mNewTabPageView.captureThumbnail(canvas); |
943 } | 992 } |
944 } | 993 } |
OLD | NEW |