Index: chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegateImpl.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegateImpl.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..74490ceb3ee6b474bb4b280d41f2c02b637c3f27 |
--- /dev/null |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsUiDelegateImpl.java |
@@ -0,0 +1,197 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.chrome.browser.suggestions; |
+ |
+import android.net.Uri; |
+import android.os.SystemClock; |
+import android.support.annotation.Nullable; |
+ |
+import org.chromium.base.Callback; |
+import org.chromium.base.ThreadUtils; |
+import org.chromium.base.metrics.RecordHistogram; |
+import org.chromium.chrome.browser.ChromeFeatureList; |
+import org.chromium.chrome.browser.favicon.FaviconHelper; |
+import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback; |
+import org.chromium.chrome.browser.favicon.FaviconHelper.IconAvailabilityCallback; |
+import org.chromium.chrome.browser.favicon.LargeIconBridge; |
+import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback; |
+import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; |
+import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; |
+import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; |
+import org.chromium.chrome.browser.profiles.Profile; |
+import org.chromium.chrome.browser.tab.Tab; |
+ |
+import java.util.ArrayList; |
+import java.util.HashSet; |
+import java.util.List; |
+import java.util.Set; |
+import java.util.concurrent.TimeUnit; |
+ |
+/** |
+ * {@link SuggestionsUiDelegate} implementation. |
+ */ |
+public class SuggestionsUiDelegateImpl implements SuggestionsUiDelegate { |
+ private final List<DestructionObserver> mDestructionObservers = new ArrayList<>(); |
+ private final SuggestionsSource mSuggestionsSource; |
+ private final SuggestionsMetricsReporter mSuggestionsMetricsReporter; |
+ private final SuggestionsNavigationDelegate mSuggestionsNavigationDelegate; |
+ |
+ private final Profile mProfile; |
+ |
+ private final Tab mTab; |
+ |
+ private FaviconHelper mFaviconHelper; |
+ private LargeIconBridge mLargeIconBridge; |
+ |
+ private boolean mIsDestroyed; |
+ |
+ public SuggestionsUiDelegateImpl(SuggestionsSource suggestionsSource, |
+ SuggestionsMetricsReporter metricsReporter, |
+ SuggestionsNavigationDelegate navigationDelegate, Profile profile, Tab currentTab) { |
+ mSuggestionsSource = suggestionsSource; |
+ mSuggestionsMetricsReporter = metricsReporter; |
+ mSuggestionsNavigationDelegate = navigationDelegate; |
+ |
+ mProfile = profile; |
+ mTab = currentTab; |
+ } |
+ |
+ @Override |
+ public void getLocalFaviconImageForURL( |
+ String url, int size, FaviconImageCallback faviconCallback) { |
+ if (mIsDestroyed) return; |
+ getFaviconHelper().getLocalFaviconImageForURL(mProfile, url, size, faviconCallback); |
+ } |
+ |
+ @Override |
+ public void getLargeIconForUrl(String url, int size, LargeIconCallback callback) { |
+ if (mIsDestroyed) return; |
+ getLargeIconBridge().getLargeIconForUrl(url, size, callback); |
+ } |
+ |
+ @Override |
+ public void ensureIconIsAvailable(String pageUrl, String iconUrl, boolean isLargeIcon, |
+ boolean isTemporary, IconAvailabilityCallback callback) { |
+ if (mIsDestroyed) return; |
+ getFaviconHelper().ensureIconIsAvailable(mProfile, mTab.getWebContents(), pageUrl, iconUrl, |
+ isLargeIcon, isTemporary, callback); |
+ } |
+ |
+ @Override |
+ public void getUrlsAvailableOffline( |
+ Set<String> pageUrls, final Callback<Set<String>> callback) { |
+ final Set<String> urlsAvailableOffline = new HashSet<>(); |
+ if (mIsDestroyed || !isNtpOfflinePagesEnabled()) { |
+ callback.onResult(urlsAvailableOffline); |
+ return; |
+ } |
+ |
+ HashSet<String> urlsToCheckForOfflinePage = new HashSet<>(); |
+ |
+ for (String pageUrl : pageUrls) { |
+ if (isLocalUrl(pageUrl)) { |
+ urlsAvailableOffline.add(pageUrl); |
+ } else { |
+ urlsToCheckForOfflinePage.add(pageUrl); |
+ } |
+ } |
+ |
+ final long offlineQueryStartTime = SystemClock.elapsedRealtime(); |
+ |
+ OfflinePageBridge offlinePageBridge = OfflinePageBridge.getForProfile(mProfile); |
+ |
+ // TODO(dewittj): Remove this code by making the NTP badging available after the NTP is |
+ // fully loaded. |
+ if (offlinePageBridge == null || !offlinePageBridge.isOfflinePageModelLoaded()) { |
+ // Posting a task to avoid potential re-entrancy issues. |
+ ThreadUtils.postOnUiThread(new Runnable() { |
+ @Override |
+ public void run() { |
+ callback.onResult(urlsAvailableOffline); |
+ } |
+ }); |
+ return; |
+ } |
+ |
+ offlinePageBridge.checkPagesExistOffline( |
+ urlsToCheckForOfflinePage, new Callback<Set<String>>() { |
+ @Override |
+ public void onResult(Set<String> urlsWithOfflinePages) { |
+ urlsAvailableOffline.addAll(urlsWithOfflinePages); |
+ callback.onResult(urlsAvailableOffline); |
+ RecordHistogram.recordTimesHistogram("NewTabPage.OfflineUrlsLoadTime", |
+ SystemClock.elapsedRealtime() - offlineQueryStartTime, |
+ TimeUnit.MILLISECONDS); |
+ } |
+ }); |
+ } |
+ |
+ @Override |
+ public SuggestionsSource getSuggestionsSource() { |
+ return mSuggestionsSource; |
+ } |
+ |
+ @Nullable |
+ @Override |
+ public SuggestionsMetricsReporter getMetricsReporter() { |
+ return mSuggestionsMetricsReporter; |
+ } |
+ |
+ @Nullable |
+ @Override |
+ public SuggestionsNavigationDelegate getNavigationDelegate() { |
+ return mSuggestionsNavigationDelegate; |
+ } |
+ |
+ @Override |
+ public void addDestructionObserver(DestructionObserver destructionObserver) { |
+ mDestructionObservers.add(destructionObserver); |
+ } |
+ |
+ /** Invalidates the delegate and calls the registered destruction observers. */ |
+ public void onDestroy() { |
+ assert !mIsDestroyed; |
+ |
+ for (DestructionObserver observer : mDestructionObservers) observer.onDestroy(); |
+ |
+ if (mFaviconHelper != null) { |
+ mFaviconHelper.destroy(); |
+ mFaviconHelper = null; |
+ } |
+ if (mLargeIconBridge != null) { |
+ mLargeIconBridge.destroy(); |
+ mLargeIconBridge = null; |
+ } |
+ mIsDestroyed = true; |
+ } |
+ |
+ /** |
+ * Utility method to lazily create the {@link FaviconHelper}, and avoid unnecessary native |
+ * calls in tests. |
+ */ |
+ private FaviconHelper getFaviconHelper() { |
+ assert !mIsDestroyed; |
+ if (mFaviconHelper == null) mFaviconHelper = new FaviconHelper(); |
+ return mFaviconHelper; |
+ } |
+ |
+ /** |
+ * Utility method to lazily create the {@link LargeIconBridge}, and avoid unnecessary native |
+ * calls in tests. |
+ */ |
+ private LargeIconBridge getLargeIconBridge() { |
+ assert !mIsDestroyed; |
+ if (mLargeIconBridge == null) mLargeIconBridge = new LargeIconBridge(mProfile); |
+ return mLargeIconBridge; |
+ } |
+ |
+ private boolean isNtpOfflinePagesEnabled() { |
+ return ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_OFFLINE_PAGES_FEATURE_NAME); |
+ } |
+ |
+ private boolean isLocalUrl(String url) { |
+ return "file".equals(Uri.parse(url).getScheme()); |
+ } |
+} |