mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 888326 - Part 3: Factor the inner classes of Favicon into their own files. r=mleibovic
This commit is contained in:
parent
752da87dd8
commit
1968180312
@ -9,6 +9,8 @@ import org.mozilla.gecko.animation.PropertyAnimator;
|
||||
import org.mozilla.gecko.db.BrowserContract.Combined;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.favicons.Favicons;
|
||||
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
|
||||
import org.mozilla.gecko.favicons.LoadFaviconTask;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||
@ -706,7 +708,7 @@ abstract public class BrowserApp extends GeckoApp
|
||||
}
|
||||
|
||||
Favicons.loadFavicon(url, tab.getFaviconURL(), 0,
|
||||
new Favicons.OnFaviconLoadedListener() {
|
||||
new OnFaviconLoadedListener() {
|
||||
@Override
|
||||
public void onFaviconLoaded(String url, Bitmap favicon) {
|
||||
GeckoAppShell.createShortcut(title, url, url, favicon == null ? null : favicon, "");
|
||||
@ -1332,9 +1334,9 @@ abstract public class BrowserApp extends GeckoApp
|
||||
private void loadFavicon(final Tab tab) {
|
||||
maybeCancelFaviconLoad(tab);
|
||||
|
||||
int flags = Favicons.FLAG_SCALE | ( (tab.isPrivate() || tab.getErrorType() != Tab.ErrorType.NONE) ? 0 : Favicons.FLAG_PERSIST);
|
||||
int flags = LoadFaviconTask.FLAG_SCALE | ( (tab.isPrivate() || tab.getErrorType() != Tab.ErrorType.NONE) ? 0 : LoadFaviconTask.FLAG_PERSIST);
|
||||
long id = Favicons.loadFavicon(tab.getURL(), tab.getFaviconURL(), flags,
|
||||
new Favicons.OnFaviconLoadedListener() {
|
||||
new OnFaviconLoadedListener() {
|
||||
|
||||
@Override
|
||||
public void onFaviconLoaded(String pageUrl, Bitmap favicon) {
|
||||
|
@ -77,6 +77,8 @@ FENNEC_JAVA_FILES = \
|
||||
DoorHangerPopup.java \
|
||||
EditBookmarkDialog.java \
|
||||
favicons/Favicons.java \
|
||||
favicons/LoadFaviconTask.java \
|
||||
favicons/OnFaviconLoadedListener.java \
|
||||
FilePickerResultHandler.java \
|
||||
FilePickerResultHandlerSync.java \
|
||||
FindInPageBar.java \
|
||||
|
@ -5,33 +5,16 @@
|
||||
|
||||
package org.mozilla.gecko.favicons;
|
||||
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.util.GeckoJarReader;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.UiAsyncTask;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.entity.BufferedHttpEntity;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.http.AndroidHttpClient;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.util.LruCache;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@ -49,10 +32,9 @@ public class Favicons {
|
||||
private static int sFaviconSmallSize = -1;
|
||||
private static int sFaviconLargeSize = -1;
|
||||
|
||||
private static Context sContext;
|
||||
protected static Context sContext;
|
||||
|
||||
private static final Map<Long,LoadFaviconTask> sLoadTasks = Collections.synchronizedMap(new HashMap<Long, LoadFaviconTask>());
|
||||
private static long sNextFaviconLoadId;
|
||||
private static final LruCache<String, Bitmap> sFaviconCache = new LruCache<String, Bitmap>(1024 * 1024) {
|
||||
@Override
|
||||
protected int sizeOf(String url, Bitmap image) {
|
||||
@ -67,22 +49,7 @@ public class Favicons {
|
||||
// A cache holding the dominant colours of favicons - used by FaviconView to fill the extra space
|
||||
// around a Favicon when it is asked to render a Favicon small than the view.
|
||||
private static final LruCache<String, Integer> sColorCache = new LruCache<String, Integer>(256);
|
||||
private static final String USER_AGENT = GeckoAppShell.getGeckoInterface().getDefaultUAString();
|
||||
private static AndroidHttpClient sHttpClient;
|
||||
|
||||
public interface OnFaviconLoadedListener {
|
||||
public void onFaviconLoaded(String url, Bitmap favicon);
|
||||
}
|
||||
|
||||
private static synchronized AndroidHttpClient getHttpClient() {
|
||||
if (sHttpClient != null)
|
||||
return sHttpClient;
|
||||
|
||||
sHttpClient = AndroidHttpClient.newInstance(USER_AGENT);
|
||||
return sHttpClient;
|
||||
}
|
||||
|
||||
private static void dispatchResult(final String pageUrl, final Bitmap image,
|
||||
static void dispatchResult(final String pageUrl, final Bitmap image,
|
||||
final OnFaviconLoadedListener listener) {
|
||||
if (pageUrl != null && image != null)
|
||||
putFaviconInMemCache(pageUrl, image);
|
||||
@ -125,7 +92,7 @@ public class Favicons {
|
||||
|
||||
LoadFaviconTask task = new LoadFaviconTask(ThreadUtils.getBackgroundHandler(), pageUrl, faviconUrl, flags, listener);
|
||||
|
||||
long taskId = task.getId();
|
||||
long taskId = task.getmId();
|
||||
sLoadTasks.put(taskId, task);
|
||||
|
||||
task.execute();
|
||||
@ -195,8 +162,8 @@ public class Favicons {
|
||||
cancelFaviconLoad(taskId);
|
||||
}
|
||||
}
|
||||
if (sHttpClient != null)
|
||||
sHttpClient.close();
|
||||
|
||||
LoadFaviconTask.closeHTTPClient();
|
||||
}
|
||||
|
||||
public static boolean isLargeFavicon(Bitmap image) {
|
||||
@ -234,172 +201,7 @@ public class Favicons {
|
||||
sFaviconLargeSize = Math.round(sContext.getResources().getDimension(R.dimen.favicon_size_large));
|
||||
}
|
||||
}
|
||||
|
||||
private static class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
|
||||
private long mId;
|
||||
private String mPageUrl;
|
||||
private String mFaviconUrl;
|
||||
private OnFaviconLoadedListener mListener;
|
||||
private int mFlags;
|
||||
|
||||
public LoadFaviconTask(Handler backgroundThreadHandler,
|
||||
String pageUrl, String faviconUrl, int flags,
|
||||
OnFaviconLoadedListener listener) {
|
||||
super(backgroundThreadHandler);
|
||||
|
||||
synchronized(this) {
|
||||
mId = ++sNextFaviconLoadId;
|
||||
}
|
||||
|
||||
mPageUrl = pageUrl;
|
||||
mFaviconUrl = faviconUrl;
|
||||
mListener = listener;
|
||||
mFlags = flags;
|
||||
}
|
||||
|
||||
// Runs in background thread
|
||||
private Bitmap loadFaviconFromDb() {
|
||||
ContentResolver resolver = sContext.getContentResolver();
|
||||
return BrowserDB.getFaviconForUrl(resolver, mPageUrl);
|
||||
}
|
||||
|
||||
// Runs in background thread
|
||||
private void saveFaviconToDb(final Bitmap favicon) {
|
||||
if ((mFlags & FLAG_PERSIST) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ContentResolver resolver = sContext.getContentResolver();
|
||||
BrowserDB.updateFaviconForUrl(resolver, mPageUrl, favicon, mFaviconUrl);
|
||||
}
|
||||
|
||||
// Runs in background thread
|
||||
private Bitmap downloadFavicon(URL faviconUrl) {
|
||||
if (mFaviconUrl.startsWith("jar:jar:")) {
|
||||
return GeckoJarReader.getBitmap(sContext.getResources(), mFaviconUrl);
|
||||
}
|
||||
|
||||
URI uri;
|
||||
try {
|
||||
uri = faviconUrl.toURI();
|
||||
} catch (URISyntaxException e) {
|
||||
Log.e(LOGTAG, "URISyntaxException getting URI for favicon", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
// only get favicons for HTTP/HTTPS
|
||||
String scheme = uri.getScheme();
|
||||
if (!"http".equals(scheme) && !"https".equals(scheme))
|
||||
return null;
|
||||
|
||||
// skia decoder sometimes returns null; workaround is to use BufferedHttpEntity
|
||||
// http://groups.google.com/group/android-developers/browse_thread/thread/171b8bf35dbbed96/c3ec5f45436ceec8?lnk=raot
|
||||
Bitmap image = null;
|
||||
try {
|
||||
HttpGet request = new HttpGet(faviconUrl.toURI());
|
||||
HttpResponse response = getHttpClient().execute(request);
|
||||
if (response == null)
|
||||
return null;
|
||||
if (response.getStatusLine() != null) {
|
||||
// Was the response a failure?
|
||||
int status = response.getStatusLine().getStatusCode();
|
||||
if (status >= 400) {
|
||||
putFaviconInFailedCache(mPageUrl, FAILED_EXPIRY_NEVER);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity == null)
|
||||
return null;
|
||||
if (entity.getContentType() != null) {
|
||||
// Is the content type valid? Might be a captive portal.
|
||||
String contentType = entity.getContentType().getValue();
|
||||
if (!contentType.contains("image"))
|
||||
return null;
|
||||
}
|
||||
|
||||
BufferedHttpEntity bufferedEntity = new BufferedHttpEntity(entity);
|
||||
InputStream contentStream = bufferedEntity.getContent();
|
||||
image = BitmapUtils.decodeStream(contentStream);
|
||||
contentStream.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(LOGTAG, "IOException reading favicon:", e);
|
||||
} catch (URISyntaxException e) {
|
||||
Log.e(LOGTAG, "URISyntaxException reading favicon:", e);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bitmap doInBackground(Void... unused) {
|
||||
Bitmap image = null;
|
||||
|
||||
if (isCancelled())
|
||||
return null;
|
||||
|
||||
URL faviconUrl = null;
|
||||
|
||||
// Handle the case of malformed favicon URL
|
||||
try {
|
||||
// If favicon is empty, fallback to default favicon URI
|
||||
if (mFaviconUrl == null || mFaviconUrl.isEmpty()) {
|
||||
// Handle the case of malformed URL
|
||||
URL pageUrl = null;
|
||||
pageUrl = new URL(mPageUrl);
|
||||
|
||||
faviconUrl = new URL(pageUrl.getProtocol(), pageUrl.getAuthority(), "/favicon.ico");
|
||||
mFaviconUrl = faviconUrl.toString();
|
||||
} else {
|
||||
faviconUrl = new URL(mFaviconUrl);
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
Log.d(LOGTAG, "The provided favicon URL is not valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isCancelled())
|
||||
return null;
|
||||
|
||||
String storedFaviconUrl = getFaviconUrlForPageUrl(mPageUrl);
|
||||
if (storedFaviconUrl != null && storedFaviconUrl.equals(mFaviconUrl)) {
|
||||
image = loadFaviconFromDb();
|
||||
if (image != null && image.getWidth() > 0 && image.getHeight() > 0)
|
||||
return ((mFlags & FLAG_SCALE) != 0) ? scaleImage(image) : image;
|
||||
}
|
||||
|
||||
if (isCancelled())
|
||||
return null;
|
||||
|
||||
image = downloadFavicon(faviconUrl);
|
||||
|
||||
if (image != null && image.getWidth() > 0 && image.getHeight() > 0) {
|
||||
saveFaviconToDb(image);
|
||||
image = ((mFlags & FLAG_SCALE) != 0) ? scaleImage(image) : image;
|
||||
} else {
|
||||
image = null;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Bitmap image) {
|
||||
sLoadTasks.remove(mId);
|
||||
dispatchResult(mPageUrl, image, mListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
sLoadTasks.remove(mId);
|
||||
|
||||
// Note that we don't call the listener callback if the
|
||||
// favicon load is cancelled.
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return mId;
|
||||
}
|
||||
public static void removeLoadTask(long taskId) {
|
||||
sLoadTasks.remove(taskId);
|
||||
}
|
||||
}
|
||||
|
213
mobile/android/base/favicons/LoadFaviconTask.java
Normal file
213
mobile/android/base/favicons/LoadFaviconTask.java
Normal file
@ -0,0 +1,213 @@
|
||||
/* 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;
|
||||
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.http.AndroidHttpClient;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.entity.BufferedHttpEntity;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.util.GeckoJarReader;
|
||||
import org.mozilla.gecko.util.UiAsyncTask;
|
||||
import static org.mozilla.gecko.favicons.Favicons.sContext;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Class representing the asynchronous task to load a Favicon which is not currently in the in-memory
|
||||
* cache.
|
||||
* The implementation initially tries to get the Favicon from the database. Upon failure, the icon
|
||||
* is loaded from the internet.
|
||||
*/
|
||||
public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
|
||||
private static final String LOGTAG = "LoadFaviconTask";
|
||||
|
||||
public static final int FLAG_PERSIST = 1;
|
||||
public static final int FLAG_SCALE = 2;
|
||||
|
||||
private long mNextFaviconLoadId;
|
||||
private long mId;
|
||||
private String mPageUrl;
|
||||
private String mFaviconUrl;
|
||||
private OnFaviconLoadedListener mListener;
|
||||
private int mFlags;
|
||||
|
||||
static AndroidHttpClient sHttpClient = AndroidHttpClient.newInstance(GeckoAppShell.getGeckoInterface().getDefaultUAString());
|
||||
|
||||
public LoadFaviconTask(Handler backgroundThreadHandler,
|
||||
String aPageUrl, String aFaviconUrl, int aFlags,
|
||||
OnFaviconLoadedListener aListener) {
|
||||
super(backgroundThreadHandler);
|
||||
|
||||
synchronized(this) {
|
||||
mId = ++mNextFaviconLoadId;
|
||||
}
|
||||
|
||||
mPageUrl = aPageUrl;
|
||||
mFaviconUrl = aFaviconUrl;
|
||||
mListener = aListener;
|
||||
mFlags = aFlags;
|
||||
}
|
||||
|
||||
// Runs in background thread
|
||||
private Bitmap loadFaviconFromDb() {
|
||||
ContentResolver resolver = sContext.getContentResolver();
|
||||
return BrowserDB.getFaviconForUrl(resolver, mPageUrl);
|
||||
}
|
||||
|
||||
// Runs in background thread
|
||||
private void saveFaviconToDb(final Bitmap favicon) {
|
||||
if ((mFlags & FLAG_PERSIST) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ContentResolver resolver = sContext.getContentResolver();
|
||||
BrowserDB.updateFaviconForUrl(resolver, mPageUrl, favicon, mFaviconUrl);
|
||||
}
|
||||
|
||||
// Runs in background thread
|
||||
private Bitmap downloadFavicon(URL targetFaviconURL) {
|
||||
if (mFaviconUrl.startsWith("jar:jar:")) {
|
||||
return GeckoJarReader.getBitmap(sContext.getResources(), mFaviconUrl);
|
||||
}
|
||||
|
||||
URI uri;
|
||||
try {
|
||||
uri = targetFaviconURL.toURI();
|
||||
} catch (URISyntaxException e) {
|
||||
Log.d(LOGTAG, "Could not get URI for favicon");
|
||||
return null;
|
||||
}
|
||||
|
||||
// only get favicons for HTTP/HTTPS
|
||||
String scheme = uri.getScheme();
|
||||
if (!"http".equals(scheme) && !"https".equals(scheme))
|
||||
return null;
|
||||
|
||||
// skia decoder sometimes returns null; workaround is to use BufferedHttpEntity
|
||||
// http://groups.google.com/group/android-developers/browse_thread/thread/171b8bf35dbbed96/c3ec5f45436ceec8?lnk=raot
|
||||
Bitmap image = null;
|
||||
try {
|
||||
HttpGet request = new HttpGet(targetFaviconURL.toURI());
|
||||
HttpResponse response = sHttpClient.execute(request);
|
||||
if (response == null)
|
||||
return null;
|
||||
if (response.getStatusLine() != null) {
|
||||
// Was the response a failure?
|
||||
int status = response.getStatusLine().getStatusCode();
|
||||
if (status >= 400) {
|
||||
Favicons.putFaviconInFailedCache(mPageUrl, Favicons.FAILED_EXPIRY_NEVER);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity == null)
|
||||
return null;
|
||||
if (entity.getContentType() != null) {
|
||||
// Is the content type valid? Might be a captive portal.
|
||||
String contentType = entity.getContentType().getValue();
|
||||
if (contentType.indexOf("image") == -1)
|
||||
return null;
|
||||
}
|
||||
|
||||
BufferedHttpEntity bufferedEntity = new BufferedHttpEntity(entity);
|
||||
InputStream contentStream = bufferedEntity.getContent();
|
||||
image = BitmapUtils.decodeStream(contentStream);
|
||||
contentStream.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Error reading favicon", e);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bitmap doInBackground(Void... unused) {
|
||||
Bitmap image;
|
||||
|
||||
if (isCancelled())
|
||||
return null;
|
||||
|
||||
URL faviconURLToDownload;
|
||||
|
||||
// Handle the case of malformed favicon URL
|
||||
try {
|
||||
// If favicon is empty, fallback to default favicon URI
|
||||
if (mFaviconUrl == null || mFaviconUrl.length() == 0) {
|
||||
// Handle the case of malformed URL
|
||||
URL targetPageURL = new URL(mPageUrl);
|
||||
|
||||
faviconURLToDownload = new URL(targetPageURL.getProtocol(), targetPageURL.getAuthority(), "/favicon.ico");
|
||||
mFaviconUrl = faviconURLToDownload.toString();
|
||||
} else {
|
||||
faviconURLToDownload = new URL(mFaviconUrl);
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
Log.d(LOGTAG, "The provided favicon URL is not valid");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isCancelled())
|
||||
return null;
|
||||
|
||||
String storedFaviconUrl = Favicons.getFaviconUrlForPageUrl(mPageUrl);
|
||||
if (storedFaviconUrl != null && storedFaviconUrl.equals(mFaviconUrl)) {
|
||||
image = loadFaviconFromDb();
|
||||
if (image != null && image.getWidth() > 0 && image.getHeight() > 0)
|
||||
return ((mFlags & FLAG_SCALE) != 0) ? Favicons.scaleImage(image) : image;
|
||||
}
|
||||
|
||||
if (isCancelled())
|
||||
return null;
|
||||
|
||||
image = downloadFavicon(faviconURLToDownload);
|
||||
|
||||
if (image != null && image.getWidth() > 0 && image.getHeight() > 0) {
|
||||
saveFaviconToDb(image);
|
||||
image = ((mFlags & FLAG_SCALE) != 0) ? Favicons.scaleImage(image) : image;
|
||||
} else {
|
||||
image = null;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Bitmap image) {
|
||||
Favicons.removeLoadTask(mId);
|
||||
Favicons.dispatchResult(mPageUrl, image, mListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
Favicons.removeLoadTask(mId);
|
||||
|
||||
// Note that we don't call the listener callback if the
|
||||
// favicon load is cancelled.
|
||||
}
|
||||
|
||||
long getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
static void closeHTTPClient() {
|
||||
if (sHttpClient != null) {
|
||||
sHttpClient.close();
|
||||
}
|
||||
}
|
||||
}
|
14
mobile/android/base/favicons/OnFaviconLoadedListener.java
Normal file
14
mobile/android/base/favicons/OnFaviconLoadedListener.java
Normal file
@ -0,0 +1,14 @@
|
||||
/* 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;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by objects wishing to listen for favicon load completion events.
|
||||
*/
|
||||
public interface OnFaviconLoadedListener {
|
||||
void onFaviconLoaded(String url, Bitmap favicon);
|
||||
}
|
@ -7,6 +7,7 @@ package org.mozilla.gecko.home;
|
||||
|
||||
import org.mozilla.gecko.EditBookmarkDialog;
|
||||
import org.mozilla.gecko.favicons.Favicons;
|
||||
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
@ -236,7 +237,7 @@ abstract class HomeFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onPostExecute(String faviconUrl) {
|
||||
Favicons.OnFaviconLoadedListener listener = new Favicons.OnFaviconLoadedListener() {
|
||||
OnFaviconLoadedListener listener = new OnFaviconLoadedListener() {
|
||||
@Override
|
||||
public void onFaviconLoaded(String url, Bitmap favicon) {
|
||||
GeckoAppShell.createShortcut(mTitle, mUrl, favicon, "");
|
||||
|
Loading…
Reference in New Issue
Block a user