mobile/android/base/favicons/cache/FaviconsForURL.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 package org.mozilla.gecko.favicons.cache;
     7 import android.graphics.Bitmap;
     8 import android.util.Log;
     9 import org.mozilla.gecko.gfx.BitmapUtils;
    11 import java.util.ArrayList;
    12 import java.util.Collections;
    14 public class FaviconsForURL {
    15     private static final String LOGTAG = "FaviconForURL";
    17     private volatile int dominantColor = -1;
    19     final long downloadTimestamp;
    20     final ArrayList<FaviconCacheElement> favicons;
    22     public final boolean hasFailed;
    24     public FaviconsForURL(int size) {
    25         this(size, false);
    26     }
    28     public FaviconsForURL(int size, boolean failed) {
    29         hasFailed = failed;
    30         downloadTimestamp = System.currentTimeMillis();
    31         favicons = new ArrayList<FaviconCacheElement>(size);
    32     }
    34     public FaviconCacheElement addSecondary(Bitmap favicon, int imageSize) {
    35         return addInternal(favicon, false, imageSize);
    36     }
    38     public FaviconCacheElement addPrimary(Bitmap favicon) {
    39         return addInternal(favicon, true, favicon.getWidth());
    40     }
    42     private FaviconCacheElement addInternal(Bitmap favicon, boolean isPrimary, int imageSize) {
    43         FaviconCacheElement c = new FaviconCacheElement(favicon, isPrimary, imageSize, this);
    45         int index = Collections.binarySearch(favicons, c);
    47         // We've already got an equivalent one. We don't care about this new one. This only occurs in certain obscure
    48         // case conditions.
    49         if (index >= 0) {
    50             return favicons.get(index);
    51         }
    53         // binarySearch returns -x - 1 where x is the insertion point of the element. Convert
    54         // this to the actual insertion point..
    55         index++;
    56         index = -index;
    57         favicons.add(index, c);
    59         return c;
    60     }
    62     /**
    63      * Get the index of the smallest image in this collection larger than or equal to
    64      * the given target size.
    65      *
    66      * @param targetSize Minimum size for the desired result.
    67      * @return The index of the smallest image larger than the target size, or -1 if none exists.
    68      */
    69     public int getNextHighestIndex(int targetSize) {
    70         // Create a dummy object to hold the target value for comparable.
    71         FaviconCacheElement dummy = new FaviconCacheElement(null, false, targetSize, null);
    73         int index = Collections.binarySearch(favicons, dummy);
    75         // The search routine returns the index of an element equal to dummy, if present.
    76         // Otherwise, it returns -x - 1, where x is the index in the ArrayList where dummy would be
    77         // inserted if the list were to remain sorted.
    78         if (index < 0) {
    79             index++;
    80             index = -index;
    81         }
    83         // index is now 'x', as described above.
    85         // The routine will return favicons.size() as the index iff dummy is larger than all elements
    86         // present (So the "index at which it should be inserted" is the index after the end.
    87         // In this case, we set the sentinel value -1 to indicate that we just requested something
    88         // larger than all primaries.
    89         if (index == favicons.size()) {
    90             index = -1;
    91         }
    93         return index;
    94     }
    96     /**
    97      * Get the next valid primary icon from this collection, starting at the given index.
    98      * If the appropriate icon is found, but is invalid, we return null - the proper response is to
    99      * reacquire the primary from the database.
   100      * If no icon is found, the search is repeated going backwards from the start index to find any
   101      * primary at all (The input index may be a secondary which is larger than the actual available
   102      * primary.)
   103      *
   104      * @param fromIndex The index into favicons from which to start the search.
   105      * @return The FaviconCacheElement of the next valid primary from the given index. If none exists,
   106      *         then returns the previous valid primary. If none exists, returns null (Insanity.).
   107      */
   108     public FaviconCacheElement getNextPrimary(final int fromIndex) {
   109         final int numIcons = favicons.size();
   111         int searchIndex = fromIndex;
   112         while (searchIndex < numIcons) {
   113             FaviconCacheElement element = favicons.get(searchIndex);
   115             if (element.isPrimary) {
   116                 if (element.invalidated) {
   117                     // We return null here, despite the possible existence of other primaries,
   118                     // because we know the most suitable primary for this request exists, but is
   119                     // no longer in the cache. By returning null, we cause the caller to load the
   120                     // missing primary from the database and call again.
   121                     return null;
   122                 }
   123                 return element;
   124             }
   125             searchIndex++;
   126         }
   128         // No larger primary available. Let's look for smaller ones...
   129         searchIndex = fromIndex - 1;
   130         while (searchIndex >= 0) {
   131             FaviconCacheElement element = favicons.get(searchIndex);
   133             if (element.isPrimary) {
   134                 if (element.invalidated) {
   135                     return null;
   136                 }
   137                 return element;
   138             }
   139             searchIndex--;
   140         }
   142         Log.e(LOGTAG, "No primaries found in Favicon cache structure. This is madness!");
   144         return null;
   145     }
   147     /**
   148      * Ensure the dominant colour field is populated for this favicon.
   149      */
   150     public int ensureDominantColor() {
   151         if (dominantColor == -1) {
   152             // Find a payload, any payload, that is not invalidated.
   153             for (FaviconCacheElement element : favicons) {
   154                 if (!element.invalidated) {
   155                     dominantColor = BitmapUtils.getDominantColor(element.faviconPayload);
   156                     return dominantColor;
   157                 }
   158             }
   159             dominantColor = 0xFFFFFF;
   160         }
   162         return dominantColor;
   163     }
   164 }

mercurial