Bug 1325586 - Prevent creating IconDescriptor with null url, r?sebastian draft
authorjwu <topwu.tw@gmail.com>
Mon, 16 Jan 2017 15:56:43 +0800
changeset 461247 eddebed3dfbe890ad15fefd002acbe31c6c54607
parent 461121 8eaf154b385bbe0ff06155294ccf7962aa2d3324
child 542261 c379a03e3bd54d70f4756b9a172d773be22e2d1a
push id41613
push userbmo:topwu.tw@gmail.com
push dateMon, 16 Jan 2017 08:42:01 +0000
reviewerssebastian
bugs1325586
milestone53.0a1
Bug 1325586 - Prevent creating IconDescriptor with null url, r?sebastian MozReview-Commit-ID: 4y6fKR49DGG
mobile/android/base/java/org/mozilla/gecko/Tab.java
mobile/android/base/java/org/mozilla/gecko/icons/IconDescriptor.java
mobile/android/base/java/org/mozilla/gecko/icons/storage/FailureCache.java
mobile/android/base/java/org/mozilla/gecko/preferences/SearchEnginePreference.java
--- a/mobile/android/base/java/org/mozilla/gecko/Tab.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tab.java
@@ -32,16 +32,17 @@ import org.mozilla.gecko.widget.SiteLogi
 
 import android.content.ContentResolver;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 
 public class Tab {
     private static final String LOGTAG = "GeckoTab";
 
     private static Pattern sColorPattern;
@@ -423,23 +424,23 @@ public class Tab {
     public void setHasTouchListeners(boolean aValue) {
         mHasTouchListeners = aValue;
     }
 
     public boolean getHasTouchListeners() {
         return mHasTouchListeners;
     }
 
-    public synchronized void addFavicon(String faviconURL, int faviconSize, String mimeType) {
+    public synchronized void addFavicon(@NonNull String faviconURL, int faviconSize, String mimeType) {
         mIconRequestBuilder
                 .icon(IconDescriptor.createFavicon(faviconURL, faviconSize, mimeType))
                 .deferBuild();
     }
 
-    public synchronized void addTouchicon(String iconUrl, int faviconSize, String mimeType) {
+    public synchronized void addTouchicon(@NonNull String iconUrl, int faviconSize, String mimeType) {
         mIconRequestBuilder
                 .icon(IconDescriptor.createTouchicon(iconUrl, faviconSize, mimeType))
                 .deferBuild();
     }
 
     public void loadFavicon() {
         // Static Favicons never change
         if (AboutPages.isBuiltinIconPage(mUrl) && mFavicon != null) {
--- a/mobile/android/base/java/org/mozilla/gecko/icons/IconDescriptor.java
+++ b/mobile/android/base/java/org/mozilla/gecko/icons/IconDescriptor.java
@@ -1,16 +1,17 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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.icons;
 
 import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
 
 /**
  * A class describing the location and properties of an icon that can be loaded.
  */
 public class IconDescriptor {
     @IntDef({ TYPE_GENERIC, TYPE_FAVICON, TYPE_TOUCHICON, TYPE_LOOKUP })
@@ -25,44 +26,44 @@ public class IconDescriptor {
     private final String url;
     private final int size;
     private final String mimeType;
     private final int type;
 
     /**
      * Create a generic icon located at the given URL. No MIME type or size is known.
      */
-    public static IconDescriptor createGenericIcon(String url) {
+    public static IconDescriptor createGenericIcon(@NonNull String url) {
         return new IconDescriptor(TYPE_GENERIC, url, 0, null);
     }
 
     /**
      * Create a favicon located at the given URL and with a known size and MIME type.
      */
-    public static IconDescriptor createFavicon(String url, int size, String mimeType) {
+    public static IconDescriptor createFavicon(@NonNull String url, int size, String mimeType) {
         return new IconDescriptor(TYPE_FAVICON, url, size, mimeType);
     }
 
     /**
      * Create a touch icon located at the given URL and with a known MIME type and size.
      */
-    public static IconDescriptor createTouchicon(String url, int size, String mimeType) {
+    public static IconDescriptor createTouchicon(@NonNull String url, int size, String mimeType) {
         return new IconDescriptor(TYPE_TOUCHICON, url, size, mimeType);
     }
 
     /**
      * Create an icon located at an URL that has been returned from a disk or memory storage. This
      * is an icon with an URL we loaded an icon from previously. Therefore we give it a little higher
      * ranking than a generic icon - even though we do not know the MIME type or size of the icon.
      */
-    public static IconDescriptor createLookupIcon(String url) {
+    public static IconDescriptor createLookupIcon(@NonNull String url) {
         return new IconDescriptor(TYPE_LOOKUP, url, 0, null);
     }
 
-    private IconDescriptor(@IconType int type, String url, int size, String mimeType) {
+    private IconDescriptor(@IconType int type, @NonNull String url, int size, String mimeType) {
         this.type = type;
         this.url = url;
         this.size = size;
         this.mimeType = mimeType;
     }
 
     /**
      * Get the URL of the icon.
--- a/mobile/android/base/java/org/mozilla/gecko/icons/storage/FailureCache.java
+++ b/mobile/android/base/java/org/mozilla/gecko/icons/storage/FailureCache.java
@@ -1,16 +1,17 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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.icons.storage;
 
 import android.os.SystemClock;
+import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
 import android.util.LruCache;
 
 /**
  * In-memory cache to remember URLs from which loading icons has failed recently.
  */
 public class FailureCache {
     /**
@@ -34,24 +35,24 @@ public class FailureCache {
 
     private FailureCache() {
         cache = new LruCache<>(MAX_ENTRIES);
     }
 
     /**
      * Remember this icon URL after loading from it (over the network) has failed.
      */
-    public void rememberFailure(String iconUrl) {
+    public void rememberFailure(@NonNull String iconUrl) {
         cache.put(iconUrl, SystemClock.elapsedRealtime());
     }
 
     /**
      * Has loading from this URL failed previously and recently?
      */
-    public boolean isKnownFailure(String iconUrl) {
+    public boolean isKnownFailure(@NonNull String iconUrl) {
         synchronized (cache) {
             final Long failedAt = cache.get(iconUrl);
             if (failedAt == null) {
                 return false;
             }
 
             if (failedAt + FAILURE_RETRY_MILLISECONDS < SystemClock.elapsedRealtime()) {
                 // The wait time has passed and we can retry loading from this URL.
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/SearchEnginePreference.java
+++ b/mobile/android/base/java/org/mozilla/gecko/preferences/SearchEnginePreference.java
@@ -15,16 +15,17 @@ import org.mozilla.gecko.widget.FaviconV
 
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.support.design.widget.Snackbar;
 import android.text.SpannableString;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 
 /**
  * Represents an element in the list of search engines on the preferences menu.
  */
 public class SearchEnginePreference extends CustomListPreference {
     protected String LOGTAG = "SearchEnginePreference";
@@ -150,16 +151,20 @@ public class SearchEnginePreference exte
         }
 
         final String engineName = geckoEngine.getString("name");
         final SpannableString titleSpannable = new SpannableString(engineName);
 
         setTitle(titleSpannable);
 
         final String iconURI = geckoEngine.getString("iconURI");
+        if (TextUtils.isEmpty(iconURI)) {
+            return;
+        }
+
         // Keep a reference to the bitmap - we'll need it later in onBindView.
         try {
             Icons.with(getContext())
                     .pageUrl(mIdentifier)
                     .icon(IconDescriptor.createGenericIcon(iconURI))
                     .privileged(true)
                     .build()
                     .execute(new IconCallback() {