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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java

Issue 2623993007: 🏠 Extract the ContentSuggestionManager interface from NTP (Closed)
Patch Set: fix destruction of snippets bridge Created 3 years, 11 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.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;
13 import android.os.Build; 12 import android.os.Build;
14 import android.os.SystemClock;
15 import android.support.v4.view.ViewCompat; 13 import android.support.v4.view.ViewCompat;
16 import android.support.v7.widget.RecyclerView; 14 import android.support.v7.widget.RecyclerView;
17 import android.text.TextUtils; 15 import android.text.TextUtils;
18 import android.view.LayoutInflater; 16 import android.view.LayoutInflater;
19 import android.view.View; 17 import android.view.View;
20 18
21 import org.chromium.base.ApiCompatibilityUtils; 19 import org.chromium.base.ApiCompatibilityUtils;
22 import org.chromium.base.Callback;
23 import org.chromium.base.CommandLine; 20 import org.chromium.base.CommandLine;
24 import org.chromium.base.ContextUtils; 21 import org.chromium.base.ContextUtils;
25 import org.chromium.base.Log; 22 import org.chromium.base.Log;
26 import org.chromium.base.ObserverList;
27 import org.chromium.base.ThreadUtils;
28 import org.chromium.base.VisibleForTesting; 23 import org.chromium.base.VisibleForTesting;
29 import org.chromium.base.metrics.RecordHistogram; 24 import org.chromium.base.metrics.RecordHistogram;
30 import org.chromium.base.metrics.RecordUserAction; 25 import org.chromium.base.metrics.RecordUserAction;
31 import org.chromium.chrome.R; 26 import org.chromium.chrome.R;
32 import org.chromium.chrome.browser.ChromeActivity; 27 import org.chromium.chrome.browser.ChromeActivity;
33 import org.chromium.chrome.browser.ChromeFeatureList; 28 import org.chromium.chrome.browser.ChromeFeatureList;
34 import org.chromium.chrome.browser.ChromeSwitches; 29 import org.chromium.chrome.browser.ChromeSwitches;
35 import org.chromium.chrome.browser.NativePage; 30 import org.chromium.chrome.browser.NativePage;
36 import org.chromium.chrome.browser.UrlConstants; 31 import org.chromium.chrome.browser.UrlConstants;
37 import org.chromium.chrome.browser.bookmarks.BookmarkUtils;
38 import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareT humbnailProvider; 32 import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareT humbnailProvider;
39 import org.chromium.chrome.browser.download.DownloadManagerService; 33 import org.chromium.chrome.browser.download.DownloadManagerService;
40 import org.chromium.chrome.browser.download.DownloadUtils;
41 import org.chromium.chrome.browser.favicon.FaviconHelper; 34 import org.chromium.chrome.browser.favicon.FaviconHelper;
42 import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback;
43 import org.chromium.chrome.browser.favicon.FaviconHelper.IconAvailabilityCallbac k;
44 import org.chromium.chrome.browser.favicon.LargeIconBridge; 35 import org.chromium.chrome.browser.favicon.LargeIconBridge;
45 import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback;
46 import org.chromium.chrome.browser.metrics.StartupMetrics; 36 import org.chromium.chrome.browser.metrics.StartupMetrics;
47 import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
48 import org.chromium.chrome.browser.ntp.LogoBridge.Logo; 37 import org.chromium.chrome.browser.ntp.LogoBridge.Logo;
49 import org.chromium.chrome.browser.ntp.LogoBridge.LogoObserver; 38 import org.chromium.chrome.browser.ntp.LogoBridge.LogoObserver;
50 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager; 39 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager;
51 import org.chromium.chrome.browser.ntp.snippets.KnownCategories;
52 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
53 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; 40 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge;
54 import org.chromium.chrome.browser.ntp.snippets.SnippetsConfig; 41 import org.chromium.chrome.browser.ntp.snippets.SnippetsConfig;
55 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; 42 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource;
56 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
57 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
58 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
59 import org.chromium.chrome.browser.profiles.MostVisitedSites; 43 import org.chromium.chrome.browser.profiles.MostVisitedSites;
60 import org.chromium.chrome.browser.profiles.MostVisitedSites.MostVisitedURLsObse rver; 44 import org.chromium.chrome.browser.profiles.MostVisitedSites.MostVisitedURLsObse rver;
61 import org.chromium.chrome.browser.profiles.Profile; 45 import org.chromium.chrome.browser.profiles.Profile;
62 import org.chromium.chrome.browser.search_engines.TemplateUrlService; 46 import org.chromium.chrome.browser.search_engines.TemplateUrlService;
63 import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl ServiceObserver; 47 import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl ServiceObserver;
64 import org.chromium.chrome.browser.snackbar.Snackbar; 48 import org.chromium.chrome.browser.snackbar.Snackbar;
65 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController; 49 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController;
66 import org.chromium.chrome.browser.suggestions.SuggestionsMetricsReporter; 50 import org.chromium.chrome.browser.suggestions.SuggestionsMetricsReporter;
51 import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegate;
52 import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegateImpl ;
53 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegateImpl;
67 import org.chromium.chrome.browser.sync.SyncSessionsMetrics; 54 import org.chromium.chrome.browser.sync.SyncSessionsMetrics;
68 import org.chromium.chrome.browser.tab.EmptyTabObserver; 55 import org.chromium.chrome.browser.tab.EmptyTabObserver;
69 import org.chromium.chrome.browser.tab.Tab; 56 import org.chromium.chrome.browser.tab.Tab;
70 import org.chromium.chrome.browser.tab.TabObserver; 57 import org.chromium.chrome.browser.tab.TabObserver;
71 import org.chromium.chrome.browser.tabmodel.TabModel; 58 import org.chromium.chrome.browser.tabmodel.TabModel;
72 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
73 import org.chromium.chrome.browser.tabmodel.TabModelSelector; 59 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
74 import org.chromium.chrome.browser.tabmodel.TabModelUtils; 60 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
75 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
76 import org.chromium.chrome.browser.util.UrlUtilities; 61 import org.chromium.chrome.browser.util.UrlUtilities;
77 import org.chromium.content_public.browser.LoadUrlParams; 62 import org.chromium.content_public.browser.LoadUrlParams;
78 import org.chromium.content_public.browser.NavigationController; 63 import org.chromium.content_public.browser.NavigationController;
79 import org.chromium.content_public.browser.NavigationEntry; 64 import org.chromium.content_public.browser.NavigationEntry;
80 import org.chromium.content_public.common.Referrer;
81 import org.chromium.net.NetworkChangeNotifier; 65 import org.chromium.net.NetworkChangeNotifier;
82 import org.chromium.ui.base.DeviceFormFactor; 66 import org.chromium.ui.base.DeviceFormFactor;
83 import org.chromium.ui.base.PageTransition; 67 import org.chromium.ui.base.PageTransition;
84 import org.chromium.ui.mojom.WindowOpenDisposition; 68 import org.chromium.ui.mojom.WindowOpenDisposition;
85 69
86 import java.util.HashSet;
87 import java.util.Set;
88 import java.util.concurrent.TimeUnit; 70 import java.util.concurrent.TimeUnit;
89 71
90 import jp.tomorrowkey.android.gifplayer.BaseGifImage; 72 import jp.tomorrowkey.android.gifplayer.BaseGifImage;
91 73
92 /** 74 /**
93 * Provides functionality when the user interacts with the NTP. 75 * Provides functionality when the user interacts with the NTP.
94 */ 76 */
95 public class NewTabPage 77 public class NewTabPage
96 implements NativePage, InvalidationAwareThumbnailProvider, TemplateUrlSe rviceObserver { 78 implements NativePage, InvalidationAwareThumbnailProvider, TemplateUrlSe rviceObserver {
97 private static final String TAG = "NewTabPage"; 79 private static final String TAG = "NewTabPage";
98 80
99 // UMA enum constants. CTA means the "click-to-action" icon. 81 // UMA enum constants. CTA means the "click-to-action" icon.
100 private static final String LOGO_SHOWN_UMA_NAME = "NewTabPage.LogoShown"; 82 private static final String LOGO_SHOWN_UMA_NAME = "NewTabPage.LogoShown";
101 private static final int STATIC_LOGO_SHOWN = 0; 83 private static final int STATIC_LOGO_SHOWN = 0;
102 private static final int CTA_IMAGE_SHOWN = 1; 84 private static final int CTA_IMAGE_SHOWN = 1;
103 85
104 private static final String LOGO_CLICK_UMA_NAME = "NewTabPage.LogoClick"; 86 private static final String LOGO_CLICK_UMA_NAME = "NewTabPage.LogoClick";
105 private static final int STATIC_LOGO_CLICKED = 0; 87 private static final int STATIC_LOGO_CLICKED = 0;
106 private static final int CTA_IMAGE_CLICKED = 1; 88 private static final int CTA_IMAGE_CLICKED = 1;
107 private static final int ANIMATED_LOGO_CLICKED = 2; 89 private static final int ANIMATED_LOGO_CLICKED = 2;
108 90
109 // Key for the scroll position data that may be stored in a navigation entry . 91 // Key for the scroll position data that may be stored in a navigation entry .
110 private static final String NAVIGATION_ENTRY_SCROLL_POSITION_KEY = "NewTabPa geScrollPosition"; 92 private static final String NAVIGATION_ENTRY_SCROLL_POSITION_KEY = "NewTabPa geScrollPosition";
111 93
112 private static final String CHROME_CONTENT_SUGGESTIONS_REFERRER =
113 "https://www.googleapis.com/auth/chrome-content-suggestions";
114
115 private static MostVisitedSites sMostVisitedSitesForTests; 94 private static MostVisitedSites sMostVisitedSitesForTests;
116 private static SuggestionsSource sSuggestionsSourceForTests; 95 private static SuggestionsSource sSuggestionsSourceForTests;
117 96
118 private final Tab mTab; 97 private final Tab mTab;
119 private final TabModelSelector mTabModelSelector; 98 private final TabModelSelector mTabModelSelector;
120 private final ChromeActivity mActivity; 99 private final ChromeActivity mActivity;
121 100
122 private final Profile mProfile;
123 private final String mTitle; 101 private final String mTitle;
124 private final int mBackgroundColor; 102 private final int mBackgroundColor;
125 private final int mThemeColor; 103 private final int mThemeColor;
126 private final NewTabPageView mNewTabPageView; 104 private final NewTabPageView mNewTabPageView;
105 private final NewTabPageManagerImpl mNewTabPageManager;
127 106
128 private TabObserver mTabObserver; 107 private TabObserver mTabObserver;
129 private MostVisitedSites mMostVisitedSites; 108 private MostVisitedSites mMostVisitedSites;
130 private SnackbarController mMostVisitedItemRemovedController; 109 private SnackbarController mMostVisitedItemRemovedController;
131 private FaviconHelper mFaviconHelper; 110 private FaviconHelper mFaviconHelper;
132 private LargeIconBridge mLargeIconBridge; 111 private LargeIconBridge mLargeIconBridge;
Michael van Ouwerkerk 2017/01/18 14:02:44 This is now unused, it should be deleted from NewT
dgn 2017/01/18 16:22:27 Done.
133 private LogoBridge mLogoBridge; 112 private LogoBridge mLogoBridge;
134 private boolean mSearchProviderHasLogo; 113 private boolean mSearchProviderHasLogo;
135 private String mOnLogoClickUrl; 114 private String mOnLogoClickUrl;
136 private String mAnimatedLogoUrl; 115 private String mAnimatedLogoUrl;
137 private FakeboxDelegate mFakeboxDelegate; 116 private FakeboxDelegate mFakeboxDelegate;
138 private SnippetsBridge mSnippetsBridge; 117 private SnippetsBridge mSnippetsBridge;
139 118
140 // The timestamp at which the constructor was called. 119 // The timestamp at which the constructor was called.
141 private final long mConstructedTimeNs; 120 private final long mConstructedTimeNs;
142 121
143 // The timestamp at which this NTP was last shown to the user. 122 // The timestamp at which this NTP was last shown to the user.
144 private long mLastShownTimeNs; 123 private long mLastShownTimeNs;
145 124
146 private boolean mIsLoaded; 125 private boolean mIsLoaded;
147 126
148 // Whether destroy() has been called. 127 // Whether destroy() has been called.
149 private boolean mIsDestroyed; 128 private boolean mIsDestroyed;
150 129
151 private final ObserverList<DestructionObserver> mDestructionObservers = new ObserverList<>();
152
153 /** 130 /**
154 * Allows clients to listen for updates to the scroll changes of the search box on the 131 * Allows clients to listen for updates to the scroll changes of the search box on the
155 * NTP. 132 * NTP.
156 */ 133 */
157 public interface OnSearchBoxScrollListener { 134 public interface OnSearchBoxScrollListener {
158 /** 135 /**
159 * Callback to be notified when the scroll position of the search box on the NTP has 136 * Callback to be notified when the scroll position of the search box on the NTP has
160 * changed. A scroll percentage of 0, means the search box has no scrol l applied and 137 * changed. A scroll percentage of 0, means the search box has no scrol l applied and
161 * is in it's natural resting position. A value of 1 means the search b ox is scrolled 138 * is in it's natural resting position. A value of 1 means the search b ox is scrolled
162 * entirely to the top of the screen viewport. 139 * entirely to the top of the screen viewport.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 @VisibleForTesting 198 @VisibleForTesting
222 public static void setMostVisitedSitesForTests(MostVisitedSites mostVisitedS itesForTests) { 199 public static void setMostVisitedSitesForTests(MostVisitedSites mostVisitedS itesForTests) {
223 sMostVisitedSitesForTests = mostVisitedSitesForTests; 200 sMostVisitedSitesForTests = mostVisitedSitesForTests;
224 } 201 }
225 202
226 @VisibleForTesting 203 @VisibleForTesting
227 public static void setSuggestionsSourceForTests(SuggestionsSource suggestion sSource) { 204 public static void setSuggestionsSourceForTests(SuggestionsSource suggestion sSource) {
228 sSuggestionsSourceForTests = suggestionsSource; 205 sSuggestionsSourceForTests = suggestionsSource;
229 } 206 }
230 207
231 private final NewTabPageManager mNewTabPageManager = new NewTabPageManager() { 208 private class NewTabPageManagerImpl
232 private static final String NTP_OFFLINE_PAGES_FEATURE_NAME = "NTPOffline Pages"; 209 extends SuggestionsUiDelegateImpl implements NewTabPageManager {
210 public NewTabPageManagerImpl(SuggestionsSource suggestionsSource,
211 SuggestionsMetricsReporter metricsReporter,
212 SuggestionsNavigationDelegate navigationDelegate, Profile profil e, Tab currentTab) {
213 super(suggestionsSource, metricsReporter, navigationDelegate, profil e, currentTab);
214 }
233 215
234 private boolean isNtpOfflinePagesEnabled() { 216 private boolean isNtpOfflinePagesEnabled() {
235 return ChromeFeatureList.isEnabled(NTP_OFFLINE_PAGES_FEATURE_NAME); 217 return ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_OFFLINE_PAG ES_FEATURE_NAME);
236 } 218 }
237 219
238 @Override 220 @Override
239 public boolean isLocationBarShownInNTP() { 221 public boolean isLocationBarShownInNTP() {
240 if (mIsDestroyed) return false; 222 if (mIsDestroyed) return false;
241 Context context = mNewTabPageView.getContext(); 223 Context context = mNewTabPageView.getContext();
242 return isInSingleUrlBarMode(context) 224 return isInSingleUrlBarMode(context)
243 && !mNewTabPageView.urlFocusAnimationsDisabled(); 225 && !mNewTabPageView.urlFocusAnimationsDisabled();
244 } 226 }
245 227
(...skipping 28 matching lines...) Expand all
274 // TODO(treib): Should we call recordOpenedMostVisitedItem here? 256 // TODO(treib): Should we call recordOpenedMostVisitedItem here?
275 if (windowDisposition != WindowOpenDisposition.NEW_WINDOW) { 257 if (windowDisposition != WindowOpenDisposition.NEW_WINDOW) {
276 recordOpenedMostVisitedItem(item); 258 recordOpenedMostVisitedItem(item);
277 } 259 }
278 260
279 if (windowDisposition == WindowOpenDisposition.CURRENT_TAB 261 if (windowDisposition == WindowOpenDisposition.CURRENT_TAB
280 && switchToExistingTab(url)) { 262 && switchToExistingTab(url)) {
281 return; 263 return;
282 } 264 }
283 265
284 openUrl(windowDisposition, new LoadUrlParams(url, PageTransition.AUT O_BOOKMARK)); 266 getNavigationDelegate().openUrl(
267 windowDisposition, new LoadUrlParams(url, PageTransition.AUT O_BOOKMARK));
285 } 268 }
286 269
287 @Override 270 @Override
288 public void removeMostVisitedItem(MostVisitedItem item) { 271 public void removeMostVisitedItem(MostVisitedItem item) {
289 mMostVisitedSites.addBlacklistedUrl(item.getUrl()); 272 mMostVisitedSites.addBlacklistedUrl(item.getUrl());
290 showMostVisitedItemRemovedSnackbar(item.getUrl()); 273 showMostVisitedItemRemovedSnackbar(item.getUrl());
291 } 274 }
292 275
293 @Override
294 public void onLearnMoreClicked() {
295 if (mIsDestroyed) return;
296 NewTabPageUma.recordAction(NewTabPageUma.ACTION_CLICKED_LEARN_MORE);
297 String url = "https://support.google.com/chrome/?p=new_tab";
298 // TODO(mastiz): Change this to LINK?
299 openUrl(WindowOpenDisposition.CURRENT_TAB,
300 new LoadUrlParams(url, PageTransition.AUTO_BOOKMARK));
301 }
302
303 @TargetApi(Build.VERSION_CODES.LOLLIPOP) 276 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
304 private boolean switchToExistingTab(String url) { 277 private boolean switchToExistingTab(String url) {
305 String matchPattern = CommandLine.getInstance().getSwitchValue( 278 String matchPattern = CommandLine.getInstance().getSwitchValue(
306 ChromeSwitches.NTP_SWITCH_TO_EXISTING_TAB); 279 ChromeSwitches.NTP_SWITCH_TO_EXISTING_TAB);
307 boolean matchByHost; 280 boolean matchByHost;
308 if ("url".equals(matchPattern)) { 281 if ("url".equals(matchPattern)) {
309 matchByHost = false; 282 matchByHost = false;
310 } else if ("host".equals(matchPattern)) { 283 } else if ("host".equals(matchPattern)) {
311 matchByHost = true; 284 matchByHost = true;
312 } else { 285 } else {
313 return false; 286 return false;
314 } 287 }
315 288
316 TabModel tabModel = mTabModelSelector.getModel(false); 289 TabModel tabModel = mTabModelSelector.getModel(false);
317 for (int i = tabModel.getCount() - 1; i >= 0; --i) { 290 for (int i = tabModel.getCount() - 1; i >= 0; --i) {
318 if (matchURLs(tabModel.getTabAt(i).getUrl(), url, matchByHost)) { 291 if (matchURLs(tabModel.getTabAt(i).getUrl(), url, matchByHost)) {
319 TabModelUtils.setIndex(tabModel, i); 292 TabModelUtils.setIndex(tabModel, i);
320 return true; 293 return true;
321 } 294 }
322 } 295 }
323 return false; 296 return false;
324 } 297 }
325 298
326 private boolean matchURLs(String url1, String url2, boolean matchByHost) { 299 private boolean matchURLs(String url1, String url2, boolean matchByHost) {
327 if (url1 == null || url2 == null) return false; 300 if (url1 == null || url2 == null) return false;
328 return matchByHost ? UrlUtilities.sameHost(url1, url2) : url1.equals (url2); 301 return matchByHost ? UrlUtilities.sameHost(url1, url2) : url1.equals (url2);
329 } 302 }
330 303
331 public SuggestionsMetricsReporter getSuggestionsMetricsReporter() {
332 return mSnippetsBridge;
333 }
334
335 @Override
336 public void openSnippet(int windowOpenDisposition, SnippetArticle articl e) {
337 mSnippetsBridge.onSuggestionOpened(article, windowOpenDisposition);
338 NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_SNIPPET);
339
340 if (article.mIsAssetDownload) {
341 assert windowOpenDisposition == WindowOpenDisposition.CURRENT_TA B
342 || windowOpenDisposition == WindowOpenDisposition.NEW_WI NDOW
343 || windowOpenDisposition == WindowOpenDisposition.NEW_FO REGROUND_TAB;
344 DownloadUtils.openFile(
345 article.getAssetDownloadFile(), article.getAssetDownload MimeType(), false);
346 return;
347 }
348
349 if (article.isRecentTab()) {
350 assert windowOpenDisposition == WindowOpenDisposition.CURRENT_TA B;
351 // TODO(vitaliii): Add a debug check that the result is true aft er crbug.com/662924
352 // is resolved.
353 openRecentTabSnippet(article);
354 return;
355 }
356
357 // TODO(treib): Also track other dispositions. crbug.com/665915
358 if (windowOpenDisposition == WindowOpenDisposition.CURRENT_TAB) {
359 NewTabPageUma.monitorContentSuggestionVisit(mTab, article.mCateg ory);
360 }
361
362 LoadUrlParams loadUrlParams;
363 // We explicitly open an offline page only for offline page download s. For all other
364 // sections the URL is opened and it is up to Offline Pages whether to open its offline
365 // page (e.g. when offline).
366 if (article.isDownload() && !article.mIsAssetDownload) {
367 assert article.getOfflinePageOfflineId() != null;
368 assert windowOpenDisposition == WindowOpenDisposition.CURRENT_TA B
369 || windowOpenDisposition == WindowOpenDisposition.NEW_WI NDOW
370 || windowOpenDisposition == WindowOpenDisposition.NEW_FO REGROUND_TAB;
371 loadUrlParams = OfflinePageUtils.getLoadUrlParamsForOpeningOffli neVersion(
372 article.mUrl, article.getOfflinePageOfflineId());
373 // Extra headers are not read in loadUrl, but verbatim headers a re.
374 loadUrlParams.setVerbatimHeaders(loadUrlParams.getExtraHeadersSt ring());
375 } else {
376 loadUrlParams = new LoadUrlParams(article.mUrl, PageTransition.A UTO_BOOKMARK);
377 }
378
379 // For article suggestions, we set the referrer. This is exploited
380 // to filter out these history entries for NTP tiles.
381 // TODO(mastiz): Extend this with support for other categories.
382 if (article.mCategory == KnownCategories.ARTICLES) {
383 loadUrlParams.setReferrer(new Referrer(
384 CHROME_CONTENT_SUGGESTIONS_REFERRER, Referrer.REFERRER_P OLICY_ALWAYS));
385 }
386
387 openUrl(windowOpenDisposition, loadUrlParams);
388 }
389
390 private boolean openRecentTabSnippet(SnippetArticle recentTabArticle) {
391 TabModel tabModel = mTabModelSelector.getModel(false);
392 int tabId = Integer.parseInt(recentTabArticle.getRecentTabId());
393 int tabIndex = TabModelUtils.getTabIndexById(tabModel, tabId);
394 if (tabIndex == TabModel.INVALID_TAB_INDEX) return false;
395 TabModelUtils.setIndex(tabModel, tabIndex);
396 return true;
397 }
398
399 private void openUrl(int windowOpenDisposition, LoadUrlParams loadUrlPar ams) {
400 assert !mIsDestroyed;
401 switch (windowOpenDisposition) {
402 case WindowOpenDisposition.CURRENT_TAB:
403 mTab.loadUrl(loadUrlParams);
404 break;
405 case WindowOpenDisposition.NEW_FOREGROUND_TAB:
406 openUrlInNewTab(loadUrlParams, false);
407 break;
408 case WindowOpenDisposition.OFF_THE_RECORD:
409 openUrlInNewTab(loadUrlParams, true);
410 break;
411 case WindowOpenDisposition.NEW_WINDOW:
412 openUrlInNewWindow(loadUrlParams);
413 break;
414 case WindowOpenDisposition.SAVE_TO_DISK:
415 saveUrlForOffline(loadUrlParams.getUrl());
416 break;
417 default:
418 assert false;
419 }
420 }
421
422 @Override
423 public boolean isOpenInNewWindowEnabled() {
424 return MultiWindowUtils.getInstance().isOpenInOtherWindowSupported(m Activity);
425 }
426
427 @Override
428 public boolean isOpenInIncognitoEnabled() {
429 return PrefServiceBridge.getInstance().isIncognitoModeEnabled();
430 }
431
432 private void openUrlInNewWindow(LoadUrlParams loadUrlParams) {
433 TabDelegate tabDelegate = new TabDelegate(false);
434 tabDelegate.createTabInOtherWindow(loadUrlParams, mActivity, mTab.ge tParentId());
435 }
436
437 private void openUrlInNewTab(LoadUrlParams loadUrlParams, boolean incogn ito) {
438 mTabModelSelector.openNewTab(
439 loadUrlParams, TabLaunchType.FROM_LONGPRESS_BACKGROUND, mTab , incognito);
440 }
441
442 private void saveUrlForOffline(String url) {
443 OfflinePageBridge.getForProfile(mProfile)
444 .savePageLater(url, "ntp_suggestions", true /* userRequested */);
445 }
446
447 @Override
448 public void navigateToBookmarks() {
449 if (mIsDestroyed) return;
450 RecordUserAction.record("MobileNTPSwitchToBookmarks");
451 BookmarkUtils.showBookmarkManager(mActivity);
452 }
453
454 @Override
455 public void navigateToRecentTabs() {
456 if (mIsDestroyed) return;
457 RecordUserAction.record("MobileNTPSwitchToOpenTabs");
458 mTab.loadUrl(new LoadUrlParams(UrlConstants.RECENT_TABS_URL));
459 }
460
461 @Override
462 public void navigateToDownloadManager() {
463 if (mIsDestroyed) return;
464 assert DownloadUtils.isDownloadHomeEnabled();
465 RecordUserAction.record("MobileNTPSwitchToDownloadManager");
466 DownloadUtils.showDownloadManager(mActivity, mTab);
467 }
468
469 @Override 304 @Override
470 public void focusSearchBox(boolean beginVoiceSearch, String pastedText) { 305 public void focusSearchBox(boolean beginVoiceSearch, String pastedText) {
471 if (mIsDestroyed) return; 306 if (mIsDestroyed) return;
472 if (mFakeboxDelegate != null) { 307 if (mFakeboxDelegate != null) {
473 if (beginVoiceSearch) { 308 if (beginVoiceSearch) {
474 mFakeboxDelegate.startVoiceRecognition(); 309 mFakeboxDelegate.startVoiceRecognition();
475 } else { 310 } else {
476 mFakeboxDelegate.requestUrlFocusFromFakebox(pastedText); 311 mFakeboxDelegate.requestUrlFocusFromFakebox(pastedText);
477 } 312 }
478 } 313 }
479 } 314 }
480 315
481 @Override 316 @Override
482 public void setMostVisitedURLsObserver(MostVisitedURLsObserver observer, int numResults) { 317 public void setMostVisitedURLsObserver(MostVisitedURLsObserver observer, int numResults) {
483 if (mIsDestroyed) return; 318 if (mIsDestroyed) return;
484 mMostVisitedSites.setMostVisitedURLsObserver(observer, numResults); 319 mMostVisitedSites.setMostVisitedURLsObserver(observer, numResults);
485 } 320 }
486 321
487 @Override 322 @Override
488 public void getLocalFaviconImageForURL(
489 String url, int size, FaviconImageCallback faviconCallback) {
490 if (mIsDestroyed) return;
491 if (mFaviconHelper == null) mFaviconHelper = new FaviconHelper();
492 mFaviconHelper.getLocalFaviconImageForURL(mProfile, url, size, favic onCallback);
493 }
494
495 @Override
496 public void getLargeIconForUrl(String url, int size, LargeIconCallback c allback) {
497 if (mIsDestroyed) return;
498 if (mLargeIconBridge == null) mLargeIconBridge = new LargeIconBridge (mProfile);
499 mLargeIconBridge.getLargeIconForUrl(url, size, callback);
500 }
501
502 @Override
503 public void ensureIconIsAvailable(String pageUrl, String iconUrl, boolea n isLargeIcon,
504 boolean isTemporary, IconAvailabilityCallback callback) {
505 if (mIsDestroyed) return;
506 if (mFaviconHelper == null) mFaviconHelper = new FaviconHelper();
507 mFaviconHelper.ensureIconIsAvailable(mProfile, mTab.getWebContents() , pageUrl, iconUrl,
508 isLargeIcon, isTemporary, callback);
509 }
510
511 private boolean isLocalUrl(String url) {
512 return "file".equals(Uri.parse(url).getScheme());
513 }
514
515 @Override
516 public void getUrlsAvailableOffline(
517 Set<String> pageUrls, final Callback<Set<String>> callback) {
518 final Set<String> urlsAvailableOffline = new HashSet<>();
519 if (mIsDestroyed || !isNtpOfflinePagesEnabled()) {
520 callback.onResult(urlsAvailableOffline);
521 return;
522 }
523
524 HashSet<String> urlsToCheckForOfflinePage = new HashSet<>();
525
526 for (String pageUrl : pageUrls) {
527 if (isLocalUrl(pageUrl)) {
528 urlsAvailableOffline.add(pageUrl);
529 } else {
530 urlsToCheckForOfflinePage.add(pageUrl);
531 }
532 }
533
534 final long offlineQueryStartTime = SystemClock.elapsedRealtime();
535
536 OfflinePageBridge offlinePageBridge = OfflinePageBridge.getForProfil e(mProfile);
537
538 // TODO(dewittj): Remove this code by making the NTP badging availab le after the NTP is
539 // fully loaded.
540 if (offlinePageBridge == null || !offlinePageBridge.isOfflinePageMod elLoaded()) {
541 // Posting a task to avoid potential re-entrancy issues.
542 ThreadUtils.postOnUiThread(new Runnable() {
543 @Override
544 public void run() {
545 callback.onResult(urlsAvailableOffline);
546 }
547 });
548 return;
549 }
550
551 offlinePageBridge.checkPagesExistOffline(
552 urlsToCheckForOfflinePage, new Callback<Set<String>>() {
553 @Override
554 public void onResult(Set<String> urlsWithOfflinePages) {
555 urlsAvailableOffline.addAll(urlsWithOfflinePages);
556 callback.onResult(urlsAvailableOffline);
557 RecordHistogram.recordTimesHistogram("NewTabPage.Off lineUrlsLoadTime",
558 SystemClock.elapsedRealtime() - offlineQuery StartTime,
559 TimeUnit.MILLISECONDS);
560 }
561 });
562 }
563
564 @Override
565 public void onLogoClicked(boolean isAnimatedLogoShowing) { 323 public void onLogoClicked(boolean isAnimatedLogoShowing) {
566 if (mIsDestroyed) return; 324 if (mIsDestroyed) return;
567 325
568 if (!isAnimatedLogoShowing && mAnimatedLogoUrl != null) { 326 if (!isAnimatedLogoShowing && mAnimatedLogoUrl != null) {
569 RecordHistogram.recordSparseSlowlyHistogram(LOGO_CLICK_UMA_NAME, CTA_IMAGE_CLICKED); 327 RecordHistogram.recordSparseSlowlyHistogram(LOGO_CLICK_UMA_NAME, CTA_IMAGE_CLICKED);
570 mNewTabPageView.showLogoLoadingView(); 328 mNewTabPageView.showLogoLoadingView();
571 mLogoBridge.getAnimatedLogo(new LogoBridge.AnimatedLogoCallback( ) { 329 mLogoBridge.getAnimatedLogo(new LogoBridge.AnimatedLogoCallback( ) {
572 @Override 330 @Override
573 public void onAnimatedLogoAvailable(BaseGifImage animatedLog oImage) { 331 public void onAnimatedLogoAvailable(BaseGifImage animatedLog oImage) {
574 if (mIsDestroyed) return; 332 if (mIsDestroyed) return;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 SyncSessionsMetrics.recordYoungestForeignTabAgeOnNTP(); 396 SyncSessionsMetrics.recordYoungestForeignTabAgeOnNTP();
639 } 397 }
640 398
641 @Override 399 @Override
642 public SuggestionsSource getSuggestionsSource() { 400 public SuggestionsSource getSuggestionsSource() {
643 if (sSuggestionsSourceForTests != null) return sSuggestionsSourceFor Tests; 401 if (sSuggestionsSourceForTests != null) return sSuggestionsSourceFor Tests;
644 return mSnippetsBridge; 402 return mSnippetsBridge;
645 } 403 }
646 404
647 @Override 405 @Override
648 public void addDestructionObserver(DestructionObserver destructionObserv er) {
649 if (mIsDestroyed) return;
650 mDestructionObservers.addObserver(destructionObserver);
651 }
652
653 @Override
654 public boolean isCurrentPage() { 406 public boolean isCurrentPage() {
655 if (mIsDestroyed) return false; 407 if (mIsDestroyed) return false;
656 if (mFakeboxDelegate == null) return false; 408 if (mFakeboxDelegate == null) return false;
657 return mFakeboxDelegate.isCurrentPage(NewTabPage.this); 409 return mFakeboxDelegate.isCurrentPage(NewTabPage.this);
658 } 410 }
659 411
660 @Override 412 @Override
661 public ContextMenuManager getContextMenuManager() { 413 public ContextMenuManager getContextMenuManager() {
662 assert !mIsDestroyed; 414 assert !mIsDestroyed;
663 return mNewTabPageView.getContextMenuManager(); 415 return mNewTabPageView.getContextMenuManager();
664 } 416 }
665 }; 417 };
666 418
667 /** 419 /**
668 * Constructs a NewTabPage. 420 * Constructs a NewTabPage.
669 * @param activity The activity used for context to create the new tab page' s View. 421 * @param activity The activity used for context to create the new tab page' s View.
670 * @param tab The Tab that is showing this new tab page. 422 * @param tab The Tab that is showing this new tab page.
671 * @param tabModelSelector The TabModelSelector used to open tabs. 423 * @param tabModelSelector The TabModelSelector used to open tabs.
672 */ 424 */
673 public NewTabPage(ChromeActivity activity, Tab tab, TabModelSelector tabMode lSelector) { 425 public NewTabPage(ChromeActivity activity, Tab tab, TabModelSelector tabMode lSelector) {
674 mConstructedTimeNs = System.nanoTime(); 426 mConstructedTimeNs = System.nanoTime();
675 427
676 mTab = tab; 428 mTab = tab;
677 mActivity = activity; 429 mActivity = activity;
678 mTabModelSelector = tabModelSelector; 430 mTabModelSelector = tabModelSelector;
679 mProfile = tab.getProfile(); 431 Profile profile = tab.getProfile();
432
433 if (SnippetsConfig.isEnabled()) {
434 mSnippetsBridge = new SnippetsBridge(profile);
435 }
436
437 SuggestionsNavigationDelegateImpl navigationDelegate =
Michael van Ouwerkerk 2017/01/16 15:31:15 Can this be of type SuggestionsNavigationDelegate?
438 new SuggestionsNavigationDelegateImpl(mActivity, profile, tab, t abModelSelector);
439 mNewTabPageManager = new NewTabPageManagerImpl(
440 mSnippetsBridge, mSnippetsBridge, navigationDelegate, profile, t ab);
441 mNewTabPageManager.addDestructionObserver(navigationDelegate);
680 442
681 mTitle = activity.getResources().getString(R.string.button_new_tab); 443 mTitle = activity.getResources().getString(R.string.button_new_tab);
682 mBackgroundColor = ApiCompatibilityUtils.getColor(activity.getResources( ), R.color.ntp_bg); 444 mBackgroundColor = ApiCompatibilityUtils.getColor(activity.getResources( ), R.color.ntp_bg);
683 mThemeColor = ApiCompatibilityUtils.getColor( 445 mThemeColor = ApiCompatibilityUtils.getColor(
684 activity.getResources(), R.color.default_primary_color); 446 activity.getResources(), R.color.default_primary_color);
685 TemplateUrlService.getInstance().addObserver(this); 447 TemplateUrlService.getInstance().addObserver(this);
686 448
687 mTabObserver = new EmptyTabObserver() { 449 mTabObserver = new EmptyTabObserver() {
688 @Override 450 @Override
689 public void onShown(Tab tab) { 451 public void onShown(Tab tab) {
(...skipping 23 matching lines...) Expand all
713 // yet. This method will then be called a second time when the u ser navigates away, 475 // yet. This method will then be called a second time when the u ser navigates away,
714 // at which point the last committed entry is for the NTP. The e xtra data must only 476 // at which point the last committed entry is for the NTP. The e xtra data must only
715 // be set in the latter case. 477 // be set in the latter case.
716 if (!isNTPUrl(entry.getUrl())) return; 478 if (!isNTPUrl(entry.getUrl())) return;
717 479
718 controller.setEntryExtraData(index, NAVIGATION_ENTRY_SCROLL_POSI TION_KEY, 480 controller.setEntryExtraData(index, NAVIGATION_ENTRY_SCROLL_POSI TION_KEY,
719 Integer.toString(scrollPosition)); 481 Integer.toString(scrollPosition));
720 } 482 }
721 }; 483 };
722 mTab.addObserver(mTabObserver); 484 mTab.addObserver(mTabObserver);
723 mMostVisitedSites = buildMostVisitedSites(mProfile); 485 mMostVisitedSites = buildMostVisitedSites(profile);
724 mLogoBridge = new LogoBridge(mProfile); 486 mLogoBridge = new LogoBridge(profile);
725 updateSearchProviderHasLogo(); 487 updateSearchProviderHasLogo();
726 488
727 if (SnippetsConfig.isEnabled()) {
728 mSnippetsBridge = new SnippetsBridge(mProfile);
729 }
730
731 LayoutInflater inflater = LayoutInflater.from(activity); 489 LayoutInflater inflater = LayoutInflater.from(activity);
732 mNewTabPageView = (NewTabPageView) inflater.inflate(R.layout.new_tab_pag e_view, null); 490 mNewTabPageView = (NewTabPageView) inflater.inflate(R.layout.new_tab_pag e_view, null);
733 mNewTabPageView.initialize(mNewTabPageManager, mTab, mSearchProviderHasL ogo, 491 mNewTabPageView.initialize(mNewTabPageManager, mTab, mSearchProviderHasL ogo,
734 getScrollPositionFromNavigationEntry()); 492 getScrollPositionFromNavigationEntry());
735 493
736 if (mSnippetsBridge != null) { 494 if (mSnippetsBridge != null) {
737 mSnippetsBridge.onNtpInitialized(); 495 mSnippetsBridge.onNtpInitialized();
738 } 496 }
739 497
740 DownloadManagerService.getDownloadManagerService(ContextUtils.getApplica tionContext()) 498 DownloadManagerService.getDownloadManagerService(ContextUtils.getApplica tionContext())
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
960 mLogoBridge.destroy(); 718 mLogoBridge.destroy();
961 mLogoBridge = null; 719 mLogoBridge = null;
962 } 720 }
963 if (mSnippetsBridge != null) { 721 if (mSnippetsBridge != null) {
964 mSnippetsBridge.destroy(); 722 mSnippetsBridge.destroy();
965 mSnippetsBridge = null; 723 mSnippetsBridge = null;
966 } 724 }
967 if (mMostVisitedItemRemovedController != null) { 725 if (mMostVisitedItemRemovedController != null) {
968 mTab.getSnackbarManager().dismissSnackbars(mMostVisitedItemRemovedCo ntroller); 726 mTab.getSnackbarManager().dismissSnackbars(mMostVisitedItemRemovedCo ntroller);
969 } 727 }
970 for (DestructionObserver observer : mDestructionObservers) { 728 mNewTabPageManager.onDestroy();
971 observer.onDestroy();
972 }
973 mDestructionObservers.clear();
974 TemplateUrlService.getInstance().removeObserver(this); 729 TemplateUrlService.getInstance().removeObserver(this);
975 mTab.removeObserver(mTabObserver); 730 mTab.removeObserver(mTabObserver);
976 mTabObserver = null; 731 mTabObserver = null;
977 mIsDestroyed = true; 732 mIsDestroyed = true;
978 } 733 }
979 734
980 @Override 735 @Override
981 public String getUrl() { 736 public String getUrl() {
982 return UrlConstants.NTP_URL; 737 return UrlConstants.NTP_URL;
983 } 738 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 @Override 776 @Override
1022 public boolean shouldCaptureThumbnail() { 777 public boolean shouldCaptureThumbnail() {
1023 return mNewTabPageView.shouldCaptureThumbnail(); 778 return mNewTabPageView.shouldCaptureThumbnail();
1024 } 779 }
1025 780
1026 @Override 781 @Override
1027 public void captureThumbnail(Canvas canvas) { 782 public void captureThumbnail(Canvas canvas) {
1028 mNewTabPageView.captureThumbnail(canvas); 783 mNewTabPageView.captureThumbnail(canvas);
1029 } 784 }
1030 } 785 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698