mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1048626 - Provide a minimal background thread pool for long-running tasks, r=rnewman
This commit is contained in:
parent
9619f8a3b1
commit
15a17d0b15
@ -31,6 +31,8 @@ import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class Favicons {
|
||||
private static final String LOGTAG = "GeckoFavicons";
|
||||
@ -60,6 +62,9 @@ public class Favicons {
|
||||
// The density-adjusted maximum Favicon dimensions.
|
||||
public static int largestFaviconSize;
|
||||
|
||||
// Executor for long-running Favicon Tasks.
|
||||
public static final ExecutorService longRunningExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
private static final SparseArray<LoadFaviconTask> loadTasks = new SparseArray<LoadFaviconTask>();
|
||||
|
||||
// Cache to hold mappings between page URLs and Favicon URLs. Used to avoid going to the DB when
|
||||
@ -194,10 +199,11 @@ public class Favicons {
|
||||
* @param callback Callback to fire with the result.
|
||||
* @return The job ID of the spawned async task, if any.
|
||||
*/
|
||||
public static int getSizedFaviconForPageFromLocal(final String pageURL, final int targetSize, final OnFaviconLoadedListener callback) {
|
||||
public static int getSizedFaviconForPageFromLocal(final String pageURL, final int targetSize,
|
||||
final OnFaviconLoadedListener callback) {
|
||||
// Firstly, try extremely hard to cheat.
|
||||
// Have we cached this favicon URL? If we did, we can consult the memcache right away.
|
||||
String targetURL = pageURLMappings.get(pageURL);
|
||||
final String targetURL = pageURLMappings.get(pageURL);
|
||||
if (targetURL != null) {
|
||||
// Check if favicon has failed.
|
||||
if (faviconsCache.isFailedFavicon(targetURL)) {
|
||||
@ -205,7 +211,7 @@ public class Favicons {
|
||||
}
|
||||
|
||||
// Do we have a Favicon in the cache for this favicon URL?
|
||||
Bitmap result = getSizedFaviconFromCache(targetURL, targetSize);
|
||||
final Bitmap result = getSizedFaviconFromCache(targetURL, targetSize);
|
||||
if (result != null) {
|
||||
// Victory - immediate response!
|
||||
return dispatchResult(pageURL, targetURL, result, callback);
|
||||
@ -213,12 +219,14 @@ public class Favicons {
|
||||
}
|
||||
|
||||
// No joy using in-memory resources. Go to background thread and ask the database.
|
||||
LoadFaviconTask task = new LoadFaviconTask(ThreadUtils.getBackgroundHandler(), pageURL, targetURL, 0, callback, targetSize, true);
|
||||
int taskId = task.getId();
|
||||
final LoadFaviconTask task =
|
||||
new LoadFaviconTask(pageURL, targetURL, 0, callback, targetSize, true);
|
||||
final int taskId = task.getId();
|
||||
synchronized(loadTasks) {
|
||||
loadTasks.put(taskId, task);
|
||||
}
|
||||
task.execute();
|
||||
|
||||
return taskId;
|
||||
}
|
||||
|
||||
@ -259,8 +267,8 @@ public class Favicons {
|
||||
* Contains logic to prevent the repeated loading of Favicons which have previously failed.
|
||||
* There is no support for recovery from transient failures.
|
||||
*
|
||||
* @param pageUrl URL of the page for which to load a Favicon. If null, no job is created.
|
||||
* @param faviconUrl The URL of the Favicon to load. If null, an attempt to infer the value from
|
||||
* @param pageURL URL of the page for which to load a Favicon. If null, no job is created.
|
||||
* @param faviconURL The URL of the Favicon to load. If null, an attempt to infer the value from
|
||||
* the history database will be made, and ultimately an attempt to guess will
|
||||
* be made.
|
||||
* @param flags Flags to be used by the LoadFaviconTask while loading. Currently only one flag
|
||||
@ -272,20 +280,20 @@ public class Favicons {
|
||||
* @param listener The OnFaviconLoadedListener to invoke with the result of this Favicon load.
|
||||
* @return The id of the LoadFaviconTask handling this job.
|
||||
*/
|
||||
private static int loadUncachedFavicon(String pageUrl, String faviconUrl, int flags, int targetSize, OnFaviconLoadedListener listener) {
|
||||
private static int loadUncachedFavicon(String pageURL, String faviconURL, int flags,
|
||||
int targetSize, OnFaviconLoadedListener listener) {
|
||||
// Handle the case where we have no page url.
|
||||
if (TextUtils.isEmpty(pageUrl)) {
|
||||
if (TextUtils.isEmpty(pageURL)) {
|
||||
dispatchResult(null, null, null, listener);
|
||||
return NOT_LOADING;
|
||||
}
|
||||
|
||||
LoadFaviconTask task = new LoadFaviconTask(ThreadUtils.getBackgroundHandler(), pageUrl, faviconUrl, flags, listener, targetSize, false);
|
||||
|
||||
int taskId = task.getId();
|
||||
final LoadFaviconTask task =
|
||||
new LoadFaviconTask(pageURL, faviconURL, flags, listener, targetSize, false);
|
||||
final int taskId = task.getId();
|
||||
synchronized(loadTasks) {
|
||||
loadTasks.put(taskId, task);
|
||||
}
|
||||
|
||||
task.execute();
|
||||
|
||||
return taskId;
|
||||
@ -325,23 +333,23 @@ public class Favicons {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean cancelled;
|
||||
synchronized (loadTasks) {
|
||||
if (loadTasks.indexOfKey(taskId) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.v(LOGTAG, "Cancelling favicon load " + taskId + ".");
|
||||
|
||||
LoadFaviconTask task = loadTasks.get(taskId);
|
||||
cancelled = task.cancel(false);
|
||||
return task.cancel();
|
||||
}
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
public static void close() {
|
||||
Log.d(LOGTAG, "Closing Favicons database");
|
||||
|
||||
// Close the Executor to new tasks.
|
||||
longRunningExecutor.shutdown();
|
||||
|
||||
// Cancel any pending tasks
|
||||
synchronized (loadTasks) {
|
||||
final int count = loadTasks.size();
|
||||
|
@ -8,7 +8,6 @@ package org.mozilla.gecko.favicons;
|
||||
import android.content.ContentResolver;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.http.AndroidHttpClient;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import org.apache.http.Header;
|
||||
@ -31,6 +30,7 @@ import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
@ -39,7 +39,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* 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> {
|
||||
public class LoadFaviconTask {
|
||||
private static final String LOGTAG = "LoadFaviconTask";
|
||||
|
||||
// Access to this map needs to be synchronized prevent multiple jobs loading the same favicon
|
||||
@ -61,6 +61,7 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
|
||||
private int flags;
|
||||
|
||||
private final boolean onlyFromLocal;
|
||||
/* inner-access */ volatile boolean mCancelled;
|
||||
|
||||
// Assuming square favicons, judging by width only is acceptable.
|
||||
protected int targetWidth;
|
||||
@ -69,20 +70,16 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
|
||||
|
||||
static AndroidHttpClient httpClient = AndroidHttpClient.newInstance(GeckoAppShell.getGeckoInterface().getDefaultUAString());
|
||||
|
||||
public LoadFaviconTask(Handler backgroundThreadHandler,
|
||||
String pageUrl, String faviconUrl, int flags,
|
||||
OnFaviconLoadedListener listener) {
|
||||
this(backgroundThreadHandler, pageUrl, faviconUrl, flags, listener, -1, false);
|
||||
public LoadFaviconTask(String pageURL, String faviconURL, int flags, OnFaviconLoadedListener listener) {
|
||||
this(pageURL, faviconURL, flags, listener, -1, false);
|
||||
}
|
||||
public LoadFaviconTask(Handler backgroundThreadHandler,
|
||||
String pageUrl, String faviconUrl, int flags,
|
||||
OnFaviconLoadedListener listener, int targetWidth, boolean onlyFromLocal) {
|
||||
super(backgroundThreadHandler);
|
||||
|
||||
public LoadFaviconTask(String pageURL, String faviconURL, int flags, OnFaviconLoadedListener listener,
|
||||
int targetWidth, boolean onlyFromLocal) {
|
||||
id = nextFaviconLoadId.incrementAndGet();
|
||||
|
||||
this.pageUrl = pageUrl;
|
||||
this.faviconURL = faviconUrl;
|
||||
this.pageUrl = pageURL;
|
||||
this.faviconURL = faviconURL;
|
||||
this.listener = listener;
|
||||
this.flags = flags;
|
||||
this.targetWidth = targetWidth;
|
||||
@ -297,8 +294,45 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
|
||||
return FaviconDecoder.decodeFavicon(buffer, 0, bPointer + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bitmap doInBackground(Void... unused) {
|
||||
// LoadFavicon tasks are performed on a unique background executor thread
|
||||
// to avoid network blocking.
|
||||
public final void execute() {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
|
||||
try {
|
||||
Favicons.longRunningExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Bitmap result = doInBackground();
|
||||
|
||||
ThreadUtils.getUiHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mCancelled) {
|
||||
onCancelled();
|
||||
} else {
|
||||
onPostExecute(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// If our executor is unavailable.
|
||||
onCancelled();
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean cancel() {
|
||||
mCancelled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public final boolean isCancelled() {
|
||||
return mCancelled;
|
||||
}
|
||||
|
||||
/* inner-access */ Bitmap doInBackground() {
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
@ -463,8 +497,7 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
|
||||
image.getHeight() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Bitmap image) {
|
||||
/* inner-access */ void onPostExecute(Bitmap image) {
|
||||
if (isChaining) {
|
||||
return;
|
||||
}
|
||||
@ -508,8 +541,7 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
|
||||
Favicons.dispatchResult(pageUrl, faviconURL, scaled, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
/* inner-access */ void onCancelled() {
|
||||
Favicons.removeLoadTask(id);
|
||||
|
||||
synchronized(loadsInFlight) {
|
||||
|
Loading…
Reference in New Issue
Block a user