diff -r 000000000000 -r 6474c204b198 mobile/android/base/favicons/cache/FaviconCacheElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobile/android/base/favicons/cache/FaviconCacheElement.java Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,115 @@ +/* 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.favicons.cache; + +import android.graphics.Bitmap; + +/** + * Objects stored in the Favicon cache - allow for the bitmap to be tagged to indicate if it has + * been scaled. Unscaled bitmaps are not included in the scaled-bitmap cache's size calculation. + */ +public class FaviconCacheElement implements Comparable { + // Was this Favicon computed via scaling another primary Favicon, or is this a primary Favicon? + final boolean isPrimary; + + // The Favicon bitmap. + Bitmap faviconPayload; + + // If set, faviconPayload is absent. Since the underlying ICO may contain multiple primary + // payloads, primary payloads are never truly deleted from the cache, but instead have their + // payload deleted and this flag set on their FaviconCacheElement. That way, the cache always + // has a record of the existence of a primary payload, even if it is no longer in the cache. + // This means that when a request comes in that will be best served using a primary that is in + // the database but no longer cached, we know that it exists and can go get it (Useful when ICO + // support is added). + volatile boolean invalidated; + + final int imageSize; + + // Used for LRU pruning. + final FaviconsForURL backpointer; + + public FaviconCacheElement(Bitmap payload, boolean primary, int size, FaviconsForURL backpointer) { + this.faviconPayload = payload; + this.isPrimary = primary; + this.imageSize = size; + this.backpointer = backpointer; + } + + public FaviconCacheElement(Bitmap faviconPayload, boolean isPrimary, FaviconsForURL backpointer) { + this.faviconPayload = faviconPayload; + this.isPrimary = isPrimary; + this.backpointer = backpointer; + + if (faviconPayload != null) { + imageSize = faviconPayload.getWidth(); + } else { + imageSize = 0; + } + } + + public int sizeOf() { + if (invalidated) { + return 0; + } + return faviconPayload.getRowBytes() * faviconPayload.getHeight(); + } + + /** + * Establish an ordering on FaviconCacheElements based on size and validity. An element is + * considered "greater than" another if it is valid and the other is not, or if it contains a + * larger payload. + * + * @param another The FaviconCacheElement to compare to this one. + * @return -1 if this element is less than the given one, 1 if the other one is larger than this + * and 0 if both are of equal value. + */ + @Override + public int compareTo(FaviconCacheElement another) { + if (invalidated && !another.invalidated) { + return -1; + } + + if (!invalidated && another.invalidated) { + return 1; + } + + if (invalidated) { + return 0; + } + + final int w1 = imageSize; + final int w2 = another.imageSize; + if (w1 > w2) { + return 1; + } else if (w2 > w1) { + return -1; + } + return 0; + } + + /** + * Called when this element is evicted from the cache. + * + * If primary, drop the payload and set invalid. If secondary, just unlink from parent node. + */ + public void onEvictedFromCache() { + if (isPrimary) { + // So we keep a record of which primaries exist in the database for this URL, we + // don't actually delete the entry for primaries. Instead, we delete their payload + // and flag them as invalid. This way, we can later figure out that what a request + // really want is one of the primaries that have been dropped from the cache, and we + // can go get it. + invalidated = true; + faviconPayload = null; + } else { + // Secondaries don't matter - just delete them. + if (backpointer == null) { + return; + } + backpointer.favicons.remove(this); + } + } +}