Bug 1377287: Update highlights label algorithm to match FFiOS. r=sebastian
authorMichael Comella <michael.l.comella@gmail.com>
Tue, 18 Jul 2017 15:03:39 -0700
changeset 422310 cdc31f6fc0840fb5fa76a9fefed1801c3625ce96
parent 422309 e25baed29efd7119609ad7838f46e33ee5ecebf7
child 422311 e244d146570c181f2d3108aebb50d515d5b0ca87
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssebastian
bugs1377287
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1377287: Update highlights label algorithm to match FFiOS. r=sebastian MozReview-Commit-ID: KLRdP9wXh1N
mobile/android/base/java/org/mozilla/gecko/activitystream/homepanel/stream/HighlightItem.java
mobile/android/base/java/org/mozilla/gecko/util/URIUtils.java
--- a/mobile/android/base/java/org/mozilla/gecko/activitystream/homepanel/stream/HighlightItem.java
+++ b/mobile/android/base/java/org/mozilla/gecko/activitystream/homepanel/stream/HighlightItem.java
@@ -1,43 +1,42 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.activitystream.homepanel.stream;
 
+import android.content.Context;
 import android.graphics.Color;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
-
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.activitystream.ActivityStream;
 import org.mozilla.gecko.activitystream.ActivityStreamTelemetry;
 import org.mozilla.gecko.activitystream.Utils;
-import org.mozilla.gecko.home.HomePager;
 import org.mozilla.gecko.activitystream.homepanel.menu.ActivityStreamContextMenu;
 import org.mozilla.gecko.activitystream.homepanel.model.Highlight;
+import org.mozilla.gecko.home.HomePager;
 import org.mozilla.gecko.icons.IconCallback;
 import org.mozilla.gecko.icons.IconResponse;
 import org.mozilla.gecko.icons.Icons;
 import org.mozilla.gecko.util.DrawableUtil;
 import org.mozilla.gecko.util.TouchTargetUtil;
+import org.mozilla.gecko.util.URIUtils;
 import org.mozilla.gecko.util.ViewUtil;
 import org.mozilla.gecko.widget.FaviconView;
 
+import java.lang.ref.WeakReference;
 import java.util.concurrent.Future;
 
-import static org.mozilla.gecko.activitystream.ActivityStream.extractLabel;
-
 public class HighlightItem extends StreamItem implements IconCallback {
     private static final String LOGTAG = "GeckoHighlightItem";
 
     public static final int LAYOUT_ID = R.layout.activity_stream_card_history_item;
 
     private Highlight highlight;
     private int position;
 
@@ -98,26 +97,28 @@ public class HighlightItem extends Strea
 
         ViewUtil.enableTouchRipple(menuButton);
     }
 
     public void bind(Highlight highlight, int position, int tilesWidth, int tilesHeight) {
         this.highlight = highlight;
         this.position = position;
 
-        pageTitleView.setText(highlight.getTitle());
+        final String backendHightlightTitle = highlight.getTitle();
+        final String uiHighlightTitle = !TextUtils.isEmpty(backendHightlightTitle) ? backendHightlightTitle : highlight.getUrl();
+        pageTitleView.setText(uiHighlightTitle);
         vTimeSince.setText(highlight.getRelativeTimeSpan());
 
         ViewGroup.LayoutParams layoutParams = pageIconView.getLayoutParams();
         layoutParams.width = tilesWidth - tilesMargin;
         layoutParams.height = tilesHeight;
         pageIconView.setLayoutParams(layoutParams);
 
         updateUiForSource(highlight.getSource());
-        updatePage();
+        updatePageDomain();
 
         if (ongoingIconLoad != null) {
             ongoingIconLoad.cancel(true);
         }
 
         ongoingIconLoad = Icons.with(itemView.getContext())
                 .pageUrl(highlight.getUrl())
                 .skipNetwork()
@@ -139,29 +140,40 @@ public class HighlightItem extends Strea
                 break;
             default:
                 pageSourceView.setVisibility(View.INVISIBLE);
                 pageSourceIconView.setImageResource(0);
                 break;
         }
     }
 
-    private void updatePage() {
-        // First try to set the provider name from the page's metadata.
-        if (highlight.getMetadata().hasProvider()) {
-            pageDomainView.setText(highlight.getMetadata().getProvider());
-            return;
-        }
-
-        // If there's no provider name available then let's try to extract one from the URL.
-        extractLabel(itemView.getContext(), highlight.getUrl(), false, new ActivityStream.LabelCallback() {
-            @Override
-            public void onLabelExtracted(String label) {
-                pageDomainView.setText(TextUtils.isEmpty(label) ? highlight.getUrl() : label);
-            }
-        });
+    private void updatePageDomain() {
+        final UpdatePageDomainAsyncTask hostSLDTask = new UpdatePageDomainAsyncTask(itemView.getContext(),
+                highlight.getUrl(), pageDomainView);
+        hostSLDTask.execute();
     }
 
     @Override
     public void onIconResponse(IconResponse response) {
         pageIconView.updateImage(response);
     }
+
+    /** Updates the text of the given view to the host second level domain. */
+    private static class UpdatePageDomainAsyncTask extends URIUtils.GetHostSecondLevelDomainAsyncTask {
+        private final WeakReference<TextView> pageDomainViewWeakReference;
+
+        UpdatePageDomainAsyncTask(final Context contextReference, final String uriString, final TextView pageDomainView) {
+            super(contextReference, uriString);
+            this.pageDomainViewWeakReference = new WeakReference<>(pageDomainView);
+        }
+
+        @Override
+        protected void onPostExecute(final String hostSLD) {
+            super.onPostExecute(hostSLD);
+            final TextView viewToUpdate = pageDomainViewWeakReference.get();
+            if (viewToUpdate == null) {
+                return;
+            }
+
+            viewToUpdate.setText(hostSLD);
+        }
+    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/util/URIUtils.java
+++ b/mobile/android/base/java/org/mozilla/gecko/util/URIUtils.java
@@ -1,26 +1,31 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.util;
 
 import android.content.Context;
+import android.os.AsyncTask;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.WorkerThread;
+import android.util.Log;
 import ch.boye.httpclientandroidlib.util.TextUtils;
 import org.mozilla.gecko.util.publicsuffix.PublicSuffix;
 
+import java.lang.ref.WeakReference;
 import java.net.URI;
 import java.net.URISyntaxException;
 
 /** Utilities for operating on URLs. */
 public class URIUtils {
+    private static final String LOGTAG = "GeckoURIUtils";
+
     private URIUtils() {}
 
     /**
      * Returns the second level domain (SLD) of a url. It removes any subdomain/TLD.
      * e.g. https://m.foo.com/bar/baz?noo=abc#123  => foo
      *
      * This implementation is taken from Firefox for iOS:
      *   https://github.com/mozilla-mobile/firefox-ios/blob/deb9736c905cdf06822ecc4a20152df7b342925d/Shared/Extensions/NSURLExtensions.swift#L152
@@ -74,9 +79,39 @@ public class URIUtils {
         return !TextUtils.isEmpty(publicSuffixWithDomain) ? publicSuffixWithDomain : null;
     }
 
     // impl via FFiOS: https://github.com/mozilla-mobile/firefox-ios/blob/deb9736c905cdf06822ecc4a20152df7b342925d/Shared/Extensions/NSURLExtensions.swift#L292
     private static boolean isIPv6(final URI uri) {
         final String host = uri.getHost();
         return !TextUtils.isEmpty(host) && host.contains(":");
     }
+
+    /**
+     * An async task that will take a URI formatted as a String and will retrieve
+     * {@link #getHostSecondLevelDomain(Context, String)}. To use this, extend the class and override
+     * {@link #onPostExecute(Object)}, where the secondLevelDomain will be returned.
+     */
+    public static abstract class GetHostSecondLevelDomainAsyncTask extends AsyncTask<Void, Void, String> {
+        protected final WeakReference<Context> contextWeakReference;
+        protected final String uriString;
+
+        public GetHostSecondLevelDomainAsyncTask(final Context contextWeakReference, final String uriString) {
+            this.contextWeakReference = new WeakReference<>(contextWeakReference);
+            this.uriString = uriString;
+        }
+
+        @Override
+        protected String doInBackground(final Void... params) {
+            final Context context = contextWeakReference.get();
+            if (context == null) {
+                return null;
+            }
+
+            try {
+                return URIUtils.getHostSecondLevelDomain(context, uriString);
+            } catch (final URISyntaxException e) {
+                Log.w(LOGTAG, "Unable to fetch second level domain."); // Don't log exception to avoid logging pii/urls.
+                return null;
+            }
+        }
+    }
 }