blob: 2df4c53abbb4ab889da929409de405847bc0a034 [file] [log] [blame]
// Copyright 2013 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.favicon;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import androidx.annotation.ColorInt;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ntp.NewTabPage;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.content_public.browser.WebContents;
/**
* This is a helper class to use favicon_service.cc's functionality.
*
* You can request a favicon image by web page URL. Note that an instance of
* this class should be created & used & destroyed (by destroy()) in the same
* thread due to the C++ base::CancelableTaskTracker class
* requirement.
*/
public class FaviconHelper {
private long mNativeFaviconHelper;
/**
* Callback interface for getting the result from getLocalFaviconImageForURL method.
*/
public interface FaviconImageCallback {
/**
* This method will be called when the result favicon is ready.
* @param image Favicon image.
* @param iconUrl Favicon image's icon url.
*/
@CalledByNative("FaviconImageCallback")
public void onFaviconAvailable(Bitmap image, String iconUrl);
}
/**
* Callback interface for the result of the ensureIconIsAvailable method.
*/
public interface IconAvailabilityCallback {
/**
* This method will be called when the availability of the icon has been checked.
* @param newlyAvailable true if the icon was downloaded and is now available, false if the
* favicon was already there or the download failed.
*/
@CalledByNative("IconAvailabilityCallback")
public void onIconAvailabilityChecked(boolean newlyAvailable);
}
/**
* Helper for generating default favicons and sharing the same icon between multiple views.
*/
public static class DefaultFaviconHelper {
private Bitmap mChromeDarkBitmap;
private Bitmap mChromeLightBitmap;
private Bitmap mDefaultDarkBitmap;
private Bitmap mDefaultLightBitmap;
private int getResourceId(String url) {
return NewTabPage.isNTPUrl(url) ? R.drawable.chromelogo16 : R.drawable.default_favicon;
}
private Bitmap createBitmap(Resources resources, String url, boolean useDarkIcon) {
Bitmap origBitmap = BitmapFactory.decodeResource(resources, getResourceId(url));
Bitmap tintedBitmap = Bitmap.createBitmap(
origBitmap.getWidth(), origBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(tintedBitmap);
@ColorInt
int tintColor = ApiCompatibilityUtils.getColor(resources,
useDarkIcon ? R.color.default_icon_color : R.color.default_icon_color_white);
Paint p = new Paint();
p.setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN));
c.drawBitmap(origBitmap, 0f, 0f, p);
return tintedBitmap;
}
/**
* Generate a default favicon bitmap for the given URL.
* @param resources The {@link Resources} to fetch the icons.
* @param url The URL of the page whose icon is being generated.
* @param useDarkIcon Whether a dark icon should be used.
* @return The favicon.
*/
public Bitmap getDefaultFaviconBitmap(
Resources resources, String url, boolean useDarkIcon) {
boolean isNtp = NewTabPage.isNTPUrl(url);
Bitmap bitmap = isNtp ? (useDarkIcon ? mChromeDarkBitmap : mChromeLightBitmap)
: (useDarkIcon ? mDefaultDarkBitmap : mDefaultLightBitmap);
if (bitmap != null) return bitmap;
bitmap = createBitmap(resources, url, useDarkIcon);
if (isNtp && useDarkIcon) {
mChromeDarkBitmap = bitmap;
} else if (isNtp) {
mChromeLightBitmap = bitmap;
} else if (useDarkIcon) {
mDefaultDarkBitmap = bitmap;
} else {
mDefaultLightBitmap = bitmap;
}
return bitmap;
}
/**
* Generate a default favicon drawable for the given URL.
* @param resources The {@link Resources} used to fetch the default icons.
* @param url The URL of the page whose icon is being generated.
* @param useDarkIcon Whether a dark icon should be used.
* @return The favicon.
*/
public Drawable getDefaultFaviconDrawable(
Resources resources, String url, boolean useDarkIcon) {
return new BitmapDrawable(
resources, getDefaultFaviconBitmap(resources, url, useDarkIcon));
}
/** Clears any of the cached default drawables. */
public void clearCache() {
mChromeDarkBitmap = null;
mChromeLightBitmap = null;
mDefaultDarkBitmap = null;
mDefaultLightBitmap = null;
}
}
/**
* Allocate and initialize the C++ side of this class.
*/
public FaviconHelper() {
mNativeFaviconHelper = FaviconHelperJni.get().init();
}
/**
* Clean up the C++ side of this class. After the call, this class instance shouldn't be used.
*/
public void destroy() {
assert mNativeFaviconHelper != 0;
FaviconHelperJni.get().destroy(mNativeFaviconHelper);
mNativeFaviconHelper = 0;
}
/**
* Get Favicon bitmap for the requested arguments. Retrieves favicons only for pages the user
* has visited on the current device.
* @param profile Profile used for the FaviconService construction.
* @param pageUrl The target Page URL to get the favicon.
* @param desiredSizeInPixel The size of the favicon in pixel we want to get.
* @param faviconImageCallback A method to be called back when the result is available. Note
* that this callback is not called if this method returns false.
* @return True if GetLocalFaviconImageForURL is successfully called.
*/
public boolean getLocalFaviconImageForURL(
Profile profile, String pageUrl, int desiredSizeInPixel,
FaviconImageCallback faviconImageCallback) {
assert mNativeFaviconHelper != 0;
return FaviconHelperJni.get().getLocalFaviconImageForURL(
mNativeFaviconHelper, profile, pageUrl, desiredSizeInPixel, faviconImageCallback);
}
/**
* Get foreign Favicon bitmap for the requested arguments.
* @param profile Profile used for the FaviconService construction.
* @param pageUrl The target Page URL to get the favicon.
* @param desiredSizeInPixel The size of the favicon in pixel we want to get.
* @param faviconImageCallback A method to be called back when the result is available. Note
* that this callback is not called if this method returns false.
* @return favicon Bitmap corresponding to the pageUrl.
*/
public boolean getForeignFaviconImageForURL(Profile profile, String pageUrl,
int desiredSizeInPixel, FaviconImageCallback faviconImageCallback) {
assert mNativeFaviconHelper != 0;
return FaviconHelperJni.get().getForeignFaviconImageForURL(
mNativeFaviconHelper, profile, pageUrl, desiredSizeInPixel, faviconImageCallback);
}
// TODO(jkrcal): Remove these two methods when FaviconHelper is not used any more by
// org.chromium.chrome.browser.suggestions.ImageFetcher. https://crbug.com/751628
/**
* Tries to make sure that the specified icon is available in the cache of the provided profile.
* The icon will we cached as an on-demand favicon.
* @param profile Profile used for the FaviconService construction.
* @param webContents The object used to download the icon.
* @param pageUrl The target Page URL to get the favicon for.
* @param iconUrl The URL of the icon to retrieve.
* @param isLargeIcon Specifies whether the type is kTouchIcon (true) or kFavicon (false).
* @param callback Called when completed (download not needed, finished or failed).
*/
public void ensureIconIsAvailable(Profile profile, WebContents webContents, String pageUrl,
String iconUrl, boolean isLargeIcon, IconAvailabilityCallback callback) {
FaviconHelperJni.get().ensureIconIsAvailable(mNativeFaviconHelper, profile, webContents,
pageUrl, iconUrl, isLargeIcon, callback);
}
/**
* Mark that the specified on-demand favicon was requested now. This postpones the automatic
* eviction of the favicon from the database.
* @param profile Profile used for the FaviconService construction.
* @param iconUrl The URL of the icon to touch.
*/
public void touchOnDemandFavicon(Profile profile, String iconUrl) {
FaviconHelperJni.get().touchOnDemandFavicon(mNativeFaviconHelper, profile, iconUrl);
}
@NativeMethods
interface Natives {
long init();
void destroy(long nativeFaviconHelper);
boolean getLocalFaviconImageForURL(long nativeFaviconHelper, Profile profile,
String pageUrl, int desiredSizeInDip, FaviconImageCallback faviconImageCallback);
boolean getForeignFaviconImageForURL(long nativeFaviconHelper, Profile profile,
String pageUrl, int desiredSizeInDip, FaviconImageCallback faviconImageCallback);
void ensureIconIsAvailable(long nativeFaviconHelper, Profile profile,
WebContents webContents, String pageUrl, String iconUrl, boolean isLargeIcon,
IconAvailabilityCallback callback);
void touchOnDemandFavicon(long nativeFaviconHelper, Profile profile, String iconUrl);
}
}