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

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

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 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
(Empty)
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
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.ntp;
6
7 import android.app.Activity;
8 import android.content.Context;
9 import android.graphics.Canvas;
10 import android.graphics.Rect;
11 import android.view.ContextMenu;
12 import android.view.LayoutInflater;
13 import android.view.Menu;
14 import android.view.MenuItem.OnMenuItemClickListener;
15 import android.view.View;
16
17 import com.google.android.apps.chrome.R;
18
19 import org.chromium.base.VisibleForTesting;
20 import org.chromium.base.metrics.RecordHistogram;
21 import org.chromium.base.metrics.RecordUserAction;
22 import org.chromium.chrome.browser.LogoBridge;
23 import org.chromium.chrome.browser.LogoBridge.Logo;
24 import org.chromium.chrome.browser.LogoBridge.LogoObserver;
25 import org.chromium.chrome.browser.NativePage;
26 import org.chromium.chrome.browser.Tab;
27 import org.chromium.chrome.browser.UrlConstants;
28 import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareT humbnailProvider;
29 import org.chromium.chrome.browser.enhancedbookmarks.EnhancedBookmarkUtils;
30 import org.chromium.chrome.browser.favicon.FaviconHelper;
31 import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback;
32 import org.chromium.chrome.browser.favicon.LargeIconBridge;
33 import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback;
34 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager;
35 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
36 import org.chromium.chrome.browser.profiles.MostVisitedSites;
37 import org.chromium.chrome.browser.profiles.MostVisitedSites.MostVisitedURLsObse rver;
38 import org.chromium.chrome.browser.profiles.MostVisitedSites.ThumbnailCallback;
39 import org.chromium.chrome.browser.profiles.Profile;
40 import org.chromium.chrome.browser.search_engines.TemplateUrlService;
41 import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl ServiceObserver;
42 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
43 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
44 import org.chromium.content_public.browser.LoadUrlParams;
45 import org.chromium.ui.base.DeviceFormFactor;
46 import org.chromium.ui.base.PageTransition;
47
48 import java.util.concurrent.TimeUnit;
49
50 /**
51 * Provides functionality when the user interacts with the NTP.
52 */
53 public class NewTabPage
54 implements NativePage, InvalidationAwareThumbnailProvider, TemplateUrlSe rviceObserver {
55
56 // MostVisitedItem Context menu item IDs.
57 static final int ID_OPEN_IN_NEW_TAB = 0;
58 static final int ID_OPEN_IN_INCOGNITO_TAB = 1;
59 static final int ID_REMOVE = 2;
60
61 private static MostVisitedSites sMostVisitedSitesForTests;
62
63 private final Tab mTab;
64 private final TabModelSelector mTabModelSelector;
65 private final Activity mActivity;
66
67 private final Profile mProfile;
68 private final String mTitle;
69 private final int mBackgroundColor;
70 private final NewTabPageView mNewTabPageView;
71
72 private MostVisitedSites mMostVisitedSites;
73 private FaviconHelper mFaviconHelper;
74 private LargeIconBridge mLargeIconBridge;
75 private LogoBridge mLogoBridge;
76 private boolean mSearchProviderHasLogo;
77 private String mOnLogoClickUrl;
78 private FakeboxDelegate mFakeboxDelegate;
79
80 // The timestamp at which the constructor was called.
81 private final long mConstructedTimeNs;
82
83 private boolean mIsLoaded;
84
85 // Whether destroy() has been called.
86 private boolean mIsDestroyed;
87
88 /**
89 * Allows clients to listen for updates to the scroll changes of the search box on the
90 * NTP.
91 */
92 public interface OnSearchBoxScrollListener {
93 /**
94 * Callback to be notified when the scroll position of the search box on the NTP has
95 * changed. A scroll percentage of 0, means the search box has no scrol l applied and
96 * is in it's natural resting position. A value of 1 means the search b ox is scrolled
97 * entirely to the top of the screen viewport.
98 *
99 * @param scrollPercentage The percentage the search box has been scroll ed off the page.
100 */
101 void onScrollChanged(float scrollPercentage);
102 }
103
104 /**
105 * Handles user interaction with the fakebox (the URL bar in the NTP).
106 */
107 public interface FakeboxDelegate {
108 /**
109 * Shows the voice recognition dialog. Called when the user taps the mic rophone icon.
110 */
111 void startVoiceRecognition();
112
113 /**
114 * Focuses the URL bar when the user taps the fakebox, types in the fake box, or pastes text
115 * into the fakebox.
116 *
117 * @param pastedText The text that was pasted or typed into the fakebox, or null if the user
118 * just tapped the fakebox.
119 */
120 void requestUrlFocusFromFakebox(String pastedText);
121 }
122
123 /**
124 * @param url The URL to check whether it is for the NTP.
125 * @return Whether the passed in URL is used to render the NTP.
126 */
127 public static boolean isNTPUrl(String url) {
128 return url != null && url.startsWith(UrlConstants.NTP_URL);
129 }
130
131 @VisibleForTesting
132 static void setMostVisitedSitesForTests(MostVisitedSites mostVisitedSitesFor Tests) {
133 sMostVisitedSitesForTests = mostVisitedSitesForTests;
134 }
135
136 private final NewTabPageManager mNewTabPageManager = new NewTabPageManager() {
137 @Override
138 public boolean isLocationBarShownInNTP() {
139 if (mIsDestroyed) return false;
140 Context context = mNewTabPageView.getContext();
141 return isInSingleUrlBarMode(context)
142 && !mNewTabPageView.urlFocusAnimationsDisabled();
143 }
144
145 private void recordOpenedMostVisitedItem(MostVisitedItem item) {
146 if (mIsDestroyed) return;
147 NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_MOST_VISITED_ ENTRY);
148 RecordHistogram.recordEnumeratedHistogram("NewTabPage.MostVisited", item.getIndex(),
149 NewTabPageView.MAX_MOST_VISITED_SITES);
150 mMostVisitedSites.recordOpenedMostVisitedItem(item.getIndex());
151 }
152
153 @Override
154 public boolean shouldShowOptOutPromo() {
155 return false;
156 }
157
158 @Override
159 public void optOutPromoShown() {}
160
161 @Override
162 public void optOutPromoClicked(boolean settingsClicked) {
163 assert false : "Should never be called for this page";
164 }
165
166 @Override
167 public void open(MostVisitedItem item) {
168 if (mIsDestroyed) return;
169 recordOpenedMostVisitedItem(item);
170 mTab.loadUrl(new LoadUrlParams(item.getUrl()));
171 }
172
173 @Override
174 public void onCreateContextMenu(ContextMenu menu, OnMenuItemClickListene r listener) {
175 if (mIsDestroyed) return;
176 menu.add(Menu.NONE, ID_OPEN_IN_NEW_TAB, Menu.NONE, R.string.contextm enu_open_in_new_tab)
177 .setOnMenuItemClickListener(listener);
178 if (PrefServiceBridge.getInstance().isIncognitoModeEnabled()) {
179 menu.add(Menu.NONE, ID_OPEN_IN_INCOGNITO_TAB, Menu.NONE,
180 R.string.contextmenu_open_in_incognito_tab).setOnMenuIte mClickListener(
181 listener);
182 }
183 menu.add(Menu.NONE, ID_REMOVE, Menu.NONE, R.string.remove)
184 .setOnMenuItemClickListener(listener);
185 }
186
187 @Override
188 public boolean onMenuItemClick(int menuId, MostVisitedItem item) {
189 if (mIsDestroyed) return false;
190 switch (menuId) {
191 case ID_OPEN_IN_NEW_TAB:
192 recordOpenedMostVisitedItem(item);
193 mTabModelSelector.openNewTab(new LoadUrlParams(item.getUrl() ),
194 TabLaunchType.FROM_LONGPRESS_BACKGROUND, mTab, false );
195 return true;
196 case ID_OPEN_IN_INCOGNITO_TAB:
197 recordOpenedMostVisitedItem(item);
198 mTabModelSelector.openNewTab(new LoadUrlParams(item.getUrl() ),
199 TabLaunchType.FROM_LONGPRESS_FOREGROUND, mTab, true) ;
200 return true;
201 case ID_REMOVE:
202 mMostVisitedSites.blacklistUrl(item.getUrl());
203 return true;
204 default:
205 return false;
206 }
207 }
208
209 @Override
210 public void navigateToBookmarks() {
211 if (mIsDestroyed) return;
212 RecordUserAction.record("MobileNTPSwitchToBookmarks");
213 if (!EnhancedBookmarkUtils.showEnhancedBookmarkIfEnabled(mActivity)) {
214 mTab.loadUrl(new LoadUrlParams(UrlConstants.BOOKMARKS_URL));
215 }
216 }
217
218 @Override
219 public void navigateToRecentTabs() {
220 if (mIsDestroyed) return;
221 RecordUserAction.record("MobileNTPSwitchToOpenTabs");
222 mTab.loadUrl(new LoadUrlParams(UrlConstants.RECENT_TABS_URL));
223 }
224
225 @Override
226 public void focusSearchBox(boolean beginVoiceSearch, String pastedText) {
227 if (mIsDestroyed) return;
228 if (mFakeboxDelegate != null) {
229 if (beginVoiceSearch) {
230 mFakeboxDelegate.startVoiceRecognition();
231 } else {
232 mFakeboxDelegate.requestUrlFocusFromFakebox(pastedText);
233 }
234 }
235 }
236
237 @Override
238 public void setMostVisitedURLsObserver(MostVisitedURLsObserver observer, int numResults) {
239 if (mIsDestroyed) return;
240 mMostVisitedSites.setMostVisitedURLsObserver(observer, numResults);
241 }
242
243 @Override
244 public void getURLThumbnail(String url, ThumbnailCallback thumbnailCallb ack) {
245 if (mIsDestroyed) return;
246 mMostVisitedSites.getURLThumbnail(url, thumbnailCallback);
247 }
248
249 @Override
250 public void getLocalFaviconImageForURL(
251 String url, int size, FaviconImageCallback faviconCallback) {
252 if (mIsDestroyed) return;
253 if (mFaviconHelper == null) mFaviconHelper = new FaviconHelper();
254 mFaviconHelper.getLocalFaviconImageForURL(mProfile, url, FaviconHelp er.FAVICON
255 | FaviconHelper.TOUCH_ICON | FaviconHelper.TOUCH_PRECOMPOSED _ICON, size,
256 faviconCallback);
257 }
258
259 @Override
260 public void getLargeIconForUrl(String url, int size, LargeIconCallback c allback) {
261 if (mIsDestroyed) return;
262 if (mLargeIconBridge == null) mLargeIconBridge = new LargeIconBridge ();
263 mLargeIconBridge.getLargeIconForUrl(mProfile, url, size, callback);
264 }
265
266 @Override
267 public void openLogoLink() {
268 if (mIsDestroyed) return;
269 if (mOnLogoClickUrl == null) return;
270 mTab.loadUrl(
271 new LoadUrlParams(mOnLogoClickUrl, PageTransition.LINK));
272 }
273
274 @Override
275 public void getSearchProviderLogo(final LogoObserver logoObserver) {
276 if (mIsDestroyed) return;
277 LogoObserver wrapperCallback = new LogoObserver() {
278 @Override
279 public void onLogoAvailable(Logo logo, boolean fromCache) {
280 if (mIsDestroyed) return;
281 mOnLogoClickUrl = logo != null ? logo.onClickUrl : null;
282 logoObserver.onLogoAvailable(logo, fromCache);
283 }
284 };
285 mLogoBridge.getCurrentLogo(wrapperCallback);
286 }
287
288 @Override
289 public void onLoadingComplete() {
290 long loadTimeMs = (System.nanoTime() - mConstructedTimeNs) / 1000000 ;
291 RecordHistogram.recordTimesHistogram(
292 "Tab.NewTabOnload", loadTimeMs, TimeUnit.MILLISECONDS);
293 mIsLoaded = true;
294
295 if (mIsDestroyed) return;
296 mMostVisitedSites.onLoadingComplete();
297 }
298 };
299
300 /**
301 * Constructs a NewTabPage.
302 * @param activity The activity used for context to create the new tab page' s View.
303 * @param tab The Tab that is showing this new tab page.
304 * @param tabModelSelector The TabModelSelector used to open tabs.
305 */
306 public NewTabPage(Activity activity, Tab tab, TabModelSelector tabModelSelec tor) {
307 mConstructedTimeNs = System.nanoTime();
308
309 mTab = tab;
310 mActivity = activity;
311 mTabModelSelector = tabModelSelector;
312 mProfile = tab.getProfile();
313
314 mTitle = activity.getResources().getString(R.string.button_new_tab);
315 mBackgroundColor = activity.getResources().getColor(R.color.ntp_bg);
316 TemplateUrlService.getInstance().addObserver(this);
317
318 mMostVisitedSites = buildMostVisitedSites(mProfile);
319 mLogoBridge = new LogoBridge(mProfile);
320 mSearchProviderHasLogo = TemplateUrlService.getInstance().isDefaultSearc hEngineGoogle();
321
322 LayoutInflater inflater = LayoutInflater.from(activity);
323 mNewTabPageView = (NewTabPageView) inflater.inflate(R.layout.new_tab_pag e, null);
324 mNewTabPageView.initialize(mNewTabPageManager, isInSingleUrlBarMode(acti vity),
325 mSearchProviderHasLogo);
326 }
327
328 private static MostVisitedSites buildMostVisitedSites(Profile profile) {
329 if (sMostVisitedSitesForTests != null) {
330 return sMostVisitedSitesForTests;
331 } else {
332 return new MostVisitedSites(profile);
333 }
334 }
335
336 /** @return The view container for the new tab page. */
337 @VisibleForTesting
338 NewTabPageView getNewTabPageView() {
339 return mNewTabPageView;
340 }
341
342 /**
343 * Updates whether the NewTabPage should animate on URL focus changes.
344 * @param disable Whether to disable the animations.
345 */
346 public void setUrlFocusAnimationsDisabled(boolean disable) {
347 mNewTabPageView.setUrlFocusAnimationsDisabled(disable);
348 }
349
350 private boolean isInSingleUrlBarMode(Context context) {
351 return mSearchProviderHasLogo && !DeviceFormFactor.isTablet(context);
352 }
353
354 private void onSearchEngineUpdated() {
355 // TODO(newt): update this if other search providers provide logos.
356 mSearchProviderHasLogo = TemplateUrlService.getInstance().isDefaultSearc hEngineGoogle();
357 mNewTabPageView.setSearchProviderHasLogo(mSearchProviderHasLogo);
358 }
359
360 /**
361 * Specifies the percentage the URL is focused during an animation. 1.0 spe cifies that the URL
362 * bar has focus and has completed the focus animation. 0 is when the URL b ar is does not have
363 * any focus.
364 *
365 * @param percent The percentage of the URL bar focus animation.
366 */
367 public void setUrlFocusChangeAnimationPercent(float percent) {
368 mNewTabPageView.setUrlFocusChangeAnimationPercent(percent);
369 }
370
371 /**
372 * Get the bounds of the search box in relation to the top level NewTabPage view.
373 *
374 * @param originalBounds The bounding region of the search box without exter nal transforms
375 * applied. The delta between this and the transforme d bounds determines
376 * the amount of scroll applied to this view.
377 * @param transformedBounds The bounding region of the search box including any transforms
378 * applied by the parent view hierarchy up to the N ewTabPage view.
379 * This more accurately reflects the current drawin g location of the
380 * search box.
381 */
382 public void getSearchBoxBounds(Rect originalBounds, Rect transformedBounds) {
383 mNewTabPageView.getSearchBoxBounds(originalBounds, transformedBounds);
384 }
385
386 /**
387 * @return Whether the location bar is shown in the NTP.
388 */
389 public boolean isLocationBarShownInNTP() {
390 return mNewTabPageManager.isLocationBarShownInNTP();
391 }
392
393 /**
394 * Sets the listener for search box scroll changes.
395 * @param listener The listener to be notified on changes.
396 */
397 public void setSearchBoxScrollListener(OnSearchBoxScrollListener listener) {
398 mNewTabPageView.setSearchBoxScrollListener(listener);
399 }
400
401 /**
402 * Sets the FakeboxDelegate that this pages interacts with.
403 */
404 public void setFakeboxDelegate(FakeboxDelegate fakeboxDelegate) {
405 mFakeboxDelegate = fakeboxDelegate;
406 }
407
408 /**
409 * @return Whether the NTP has finished loaded.
410 */
411 @VisibleForTesting
412 public boolean isLoadedForTests() {
413 return mIsLoaded;
414 }
415
416 // TemplateUrlServiceObserver overrides
417
418 @Override
419 public void onTemplateURLServiceChanged() {
420 onSearchEngineUpdated();
421 }
422
423 // NativePage overrides
424
425 @Override
426 public void destroy() {
427 assert getView().getParent() == null : "Destroy called before removed fr om window";
428 if (mFaviconHelper != null) {
429 mFaviconHelper.destroy();
430 mFaviconHelper = null;
431 }
432 if (mLargeIconBridge != null) {
433 mLargeIconBridge.destroy();
434 mLargeIconBridge = null;
435 }
436 if (mMostVisitedSites != null) {
437 mMostVisitedSites.destroy();
438 mMostVisitedSites = null;
439 }
440 if (mLogoBridge != null) {
441 mLogoBridge.destroy();
442 mLogoBridge = null;
443 }
444 TemplateUrlService.getInstance().removeObserver(this);
445 mIsDestroyed = true;
446 }
447
448 @Override
449 public String getUrl() {
450 return UrlConstants.NTP_URL;
451 }
452
453 @Override
454 public String getTitle() {
455 return mTitle;
456 }
457
458 @Override
459 public int getBackgroundColor() {
460 return mBackgroundColor;
461 }
462
463 @Override
464 public View getView() {
465 return mNewTabPageView;
466 }
467
468 @Override
469 public String getHost() {
470 return UrlConstants.NTP_HOST;
471 }
472
473 @Override
474 public void updateForUrl(String url) {
475 }
476
477 // InvalidationAwareThumbnailProvider
478
479 @Override
480 public boolean shouldCaptureThumbnail() {
481 return mNewTabPageView.shouldCaptureThumbnail();
482 }
483
484 @Override
485 public void captureThumbnail(Canvas canvas) {
486 mNewTabPageView.captureThumbnail(canvas);
487 }
488 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698