Bug 842421 - Make GeckoAsyncTask cancellable r=kats r=bnicholson
authorMark Finkle <mfinkle@mozilla.com>
Tue, 19 Feb 2013 16:14:37 -0500
changeset 122365 c36abb35fb9b39be560ae58eac5b4fd4408c7bec
parent 122364 208b826dc3d30a69023f6ff6888c44a13f4401e7
child 122366 5b56d8a519a57503d1f934da2ce30260dd2cae90
push id24336
push userryanvm@gmail.com
push dateWed, 20 Feb 2013 12:07:46 +0000
treeherdermozilla-central@1bcc3c56b011 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, bnicholson
bugs842421
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 842421 - Make GeckoAsyncTask cancellable r=kats r=bnicholson
mobile/android/base/Favicons.java
mobile/android/base/GeckoAsyncTask.java
--- a/mobile/android/base/Favicons.java
+++ b/mobile/android/base/Favicons.java
@@ -1,30 +1,31 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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;
 
 import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.util.GeckoBackgroundThread;
+import org.mozilla.gecko.util.GeckoAsyncTask;
 import org.mozilla.gecko.util.GeckoJarReader;
 
 import org.apache.http.HttpEntity;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.entity.BufferedHttpEntity;
 
+import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.net.http.AndroidHttpClient;
-import android.os.AsyncTask;
+import android.os.Handler;
 import android.support.v4.util.LruCache;
 import android.util.Log;
 
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
@@ -106,17 +107,17 @@ public class Favicons {
 
         // Check if favicon is mem cached
         Bitmap image = getFaviconFromMemCache(pageUrl);
         if (image != null) {
             dispatchResult(pageUrl, image, listener);
             return -1;
         }
 
-        LoadFaviconTask task = new LoadFaviconTask(pageUrl, faviconUrl, persist, listener);
+        LoadFaviconTask task = new LoadFaviconTask(GeckoApp.mAppContext, GeckoAppShell.getHandler(), pageUrl, faviconUrl, persist, listener);
 
         long taskId = task.getId();
         mLoadTasks.put(taskId, task);
 
         task.execute();
 
         return taskId;
     }
@@ -193,25 +194,28 @@ public class Favicons {
         if (sFaviconSmallSize < 0) {
             sFaviconSmallSize = Math.round(mContext.getResources().getDimension(R.dimen.awesomebar_row_favicon_size_small));
         }
         if (sFaviconLargeSize < 0) {
             sFaviconLargeSize = Math.round(mContext.getResources().getDimension(R.dimen.awesomebar_row_favicon_size_large));
         }
     }
 
-    private class LoadFaviconTask extends AsyncTask<Void, Void, Bitmap> {
+    private class LoadFaviconTask extends GeckoAsyncTask<Void, Void, Bitmap> {
         private long mId;
         private String mPageUrl;
         private String mFaviconUrl;
         private OnFaviconLoadedListener mListener;
         private boolean mPersist;
 
-        public LoadFaviconTask(String pageUrl, String faviconUrl, boolean persist,
-                OnFaviconLoadedListener listener) {
+        public LoadFaviconTask(Activity activity, Handler backgroundThreadHandler,
+                               String pageUrl, String faviconUrl, boolean persist,
+                               OnFaviconLoadedListener listener) {
+            super(activity, backgroundThreadHandler);
+
             synchronized(this) {
                 mId = ++mNextFaviconLoadId;
             }
 
             mPageUrl = pageUrl;
             mFaviconUrl = faviconUrl;
             mListener = listener;
             mPersist = persist;
@@ -224,25 +228,18 @@ public class Favicons {
         }
 
         // Runs in background thread
         private void saveFaviconToDb(final Bitmap favicon) {
             if (!mPersist) {
                 return;
             }
 
-            // Even though this code is in a background thread, all DB writes
-            // should happen in GeckoBackgroundThread or we could get locked
-            // databases.
-            GeckoBackgroundThread.post(new Runnable() {
-                public void run() {
-                    ContentResolver resolver = mContext.getContentResolver();
-                    BrowserDB.updateFaviconForUrl(resolver, mPageUrl, favicon, mFaviconUrl);
-                }
-            });
+            ContentResolver resolver = mContext.getContentResolver();
+            BrowserDB.updateFaviconForUrl(resolver, mPageUrl, favicon, mFaviconUrl);
         }
 
         // Runs in background thread
         private Bitmap downloadFavicon(URL faviconUrl) {
             if (mFaviconUrl.startsWith("jar:jar:")) {
                 BitmapDrawable d = GeckoJarReader.getBitmapDrawable(mContext.getResources(), mFaviconUrl);
                 return d.getBitmap();
             }
--- a/mobile/android/base/GeckoAsyncTask.java
+++ b/mobile/android/base/GeckoAsyncTask.java
@@ -10,16 +10,17 @@ import android.os.Handler;
 
 // AsyncTask runs onPostExecute on the thread it is constructed on
 // We construct these off of the main thread, and we want that to run
 // on the main UI thread, so this is a convenience class to do that
 public abstract class GeckoAsyncTask<Params, Progress, Result> {
     public enum Priority { NORMAL, HIGH };
 
     private final Activity mActivity;
+    private volatile boolean mCancelled = false;
     private final Handler mBackgroundThreadHandler;
     private Priority mPriority = Priority.NORMAL;
 
     public GeckoAsyncTask(Activity activity, Handler backgroundThreadHandler) {
         mActivity = activity;
         mBackgroundThreadHandler = backgroundThreadHandler;
     }
 
@@ -27,19 +28,23 @@ public abstract class GeckoAsyncTask<Par
         private Params[] mParams;
 
         public BackgroundTaskRunnable(Params... params) {
             mParams = params;
         }
 
         public void run() {
             final Result result = doInBackground(mParams);
+
             mActivity.runOnUiThread(new Runnable() {
                 public void run() {
-                    onPostExecute(result);
+                    if (mCancelled)
+                        onCancelled();
+                    else
+                        onPostExecute(result);
                 }
             });
         }
     }
 
     public final void execute(final Params... params) {
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -54,14 +59,23 @@ public abstract class GeckoAsyncTask<Par
         });
     }
 
     public final GeckoAsyncTask<Params, Progress, Result> setPriority(Priority priority) {
         mPriority = priority;
         return this;
     }
 
-    /* Empty stub method. Implementors can optionally override this if they need it */
+    @SuppressWarnings({"UnusedParameters"})
+    public final boolean cancel(boolean mayInterruptIfRunning) {
+        mCancelled = true;
+        return mCancelled;
+    }
+
+    public final boolean isCancelled() {
+        return mCancelled;
+    }
+
     protected void onPreExecute() { }
     protected void onPostExecute(Result result) { }
-
+    protected void onCancelled() { }
     protected abstract Result doInBackground(Params... params);
 }