bug 700354 - Use of AsyncTask needs some cleanup r=mfinkle
authorBrad Lassey <blassey@mozilla.com>
Thu, 10 Nov 2011 21:34:38 -0500
changeset 83436 13f5d3d70ecbbf00224341af29517eed89dd3f3d
parent 83435 c5a4c774f474774935d59eaa955ce44a391bf600
child 83437 dce9246b76d7cde6aeb9c1c3918e9f7a5f19a53f
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs700354
milestone10.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 700354 - Use of AsyncTask needs some cleanup r=mfinkle
embedding/android/Favicons.java
embedding/android/GeckoApp.java
embedding/android/GeckoAsyncTask.java
embedding/android/GeckoThread.java
embedding/android/Makefile.in
embedding/android/Tab.java
--- a/embedding/android/Favicons.java
+++ b/embedding/android/Favicons.java
@@ -165,17 +165,17 @@ public class Favicons {
         new LoadFaviconTask(pageUrl, faviconUrl, listener).execute();
     }
 
     public void close() {
         Log.d(LOG_NAME, "Closing Favicons database");
         mDbHelper.close();
     }
 
-    private class LoadFaviconTask extends AsyncTask<Void, Void, BitmapDrawable> {
+    private class LoadFaviconTask extends GeckoAsyncTask<Void, Void, BitmapDrawable> {
         private String mPageUrl;
         private String mFaviconUrl;
         private OnFaviconLoadedListener mListener;
 
         public LoadFaviconTask(String pageUrl, String faviconUrl, OnFaviconLoadedListener listener) {
             mPageUrl = pageUrl;
             mFaviconUrl = faviconUrl;
             mListener = listener;
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -336,91 +336,24 @@ abstract public class GeckoApp
     // Returns true when the intent is going to be handled by gecko launch
     boolean launch(Intent intent)
     {
         Log.w(LOGTAG, "zerdatime " + new Date().getTime() + " - launch");
         
         if (!checkAndSetLaunchState(LaunchState.Launching, LaunchState.Launched))
             return false;
 
-        class GeckoTask extends AsyncTask<Intent, Void, Void> {
-            protected Void doInBackground(Intent... intents) {
-                Intent intent = intents[0];
-                File cacheFile = GeckoAppShell.getCacheDir();
-                File libxulFile = new File(cacheFile, "libxul.so");
-
-                if ((!libxulFile.exists() ||
-                     new File(getApplication().getPackageResourcePath()).lastModified() >= libxulFile.lastModified())) {
-                    File[] libs = cacheFile.listFiles(new FilenameFilter() {
-                            public boolean accept(File dir, String name) {
-                                return name.endsWith(".so");
-                            }
-                        });
-                    if (libs != null) {
-                        for (int i = 0; i < libs.length; i++) {
-                            libs[i].delete();
-                        }
-                    }
-                 }
- 
-                // At some point while loading the gecko libs our default locale gets set
-                // so just save it to locale here and reset it as default after the join
-                Locale locale = Locale.getDefault();
-                GeckoAppShell.loadGeckoLibs(
-                    getApplication().getPackageResourcePath());
-                Locale.setDefault(locale);
-                Resources res = getBaseContext().getResources();
-                Configuration config = res.getConfiguration();
-                config.locale = locale;
-                res.updateConfiguration(config, res.getDisplayMetrics());
-
-                Log.w(LOGTAG, "zerdatime " + new Date().getTime() + " - runGecko");
                 String args = intent.getStringExtra("args");
                 if (args != null && args.contains("-profile"))
                     mUserDefinedProfile = true;
 
-                // and then fire us up
-                try {
-                    String uri = intent.getDataString();
-                    String title = uri;
-                    if (!mUserDefinedProfile &&
-                        (uri == null || uri.length() == 0)) {
-                        SharedPreferences prefs = getSharedPreferences("GeckoApp", MODE_PRIVATE);
-                        uri = prefs.getString("last-uri", "");
-                        title = prefs.getString("last-title", uri);
-                    }
-
-                    final String awesomeTitle = title; 
-                    mMainHandler.post(new Runnable() {
-                        public void run() {
-                            mBrowserToolbar.setTitle(awesomeTitle);
-                        }
-                    });
-
-                    Log.w(LOGTAG, "RunGecko - URI = " + uri);
-
-                    GeckoAppShell.runGecko(getApplication().getPackageResourcePath(),
-                                           args,
-                                           uri);
-                } catch (Exception e) {
-                    Log.e(LOG_NAME, "top level exception", e);
-                    StringWriter sw = new StringWriter();
-                    PrintWriter pw = new PrintWriter(sw);
-                    e.printStackTrace(pw);
-                    pw.flush();
-                    GeckoAppShell.reportJavaCrash(sw.toString());
-                }
-                return null;
-            }
-        }
-
         if (intent == null)
             intent = getIntent();
 
-        new GeckoTask().execute(intent);
+        new GeckoThread(intent).start();
 
         return true;
     }
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu)
     {
         sMenu = menu;
@@ -1721,55 +1654,58 @@ abstract public class GeckoApp
     }
 
     public void onSensorChanged(SensorEvent event)
     {
         Log.w(LOGTAG, "onSensorChanged "+event);
         GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
     }
 
-    private class GeocoderTask extends AsyncTask<Location, Void, Void> {
-        protected Void doInBackground(Location... location) {
+    private class GeocoderRunnable implements Runnable {
+        Location mLocation;
+        GeocoderRunnable (Location location) {
+            mLocation = location;
+        }
+        public void run() {
             try {
-                List<Address> addresses = mGeocoder.getFromLocation(location[0].getLatitude(),
-                                                                    location[0].getLongitude(), 1);
+                List<Address> addresses = mGeocoder.getFromLocation(mLocation.getLatitude(),
+                                                                    mLocation.getLongitude(), 1);
                 // grab the first address.  in the future,
                 // may want to expose multiple, or filter
                 // for best.
                 mLastGeoAddress = addresses.get(0);
-                GeckoAppShell.sendEventToGecko(new GeckoEvent(location[0], mLastGeoAddress));
+                GeckoAppShell.sendEventToGecko(new GeckoEvent(mLocation, mLastGeoAddress));
             } catch (Exception e) {
                 Log.w(LOGTAG, "GeocoderTask "+e);
             }
-            return null;
         }
     }
 
     // geolocation
     public void onLocationChanged(Location location)
     {
         Log.w(LOGTAG, "onLocationChanged "+location);
         if (mGeocoder == null)
             mGeocoder = new Geocoder(mLayerController.getView().getContext(), Locale.getDefault());
 
         if (mLastGeoAddress == null) {
-            new GeocoderTask().execute(location);
+            GeckoAppShell.getHandler().post(new GeocoderRunnable(location));
         }
         else {
             float[] results = new float[1];
             Location.distanceBetween(location.getLatitude(),
                                      location.getLongitude(),
                                      mLastGeoAddress.getLatitude(),
                                      mLastGeoAddress.getLongitude(),
                                      results);
             // pfm value.  don't want to slam the
             // geocoder with very similar values, so
             // only call after about 100m
             if (results[0] > 100)
-                new GeocoderTask().execute(location);
+                GeckoAppShell.getHandler().post(new GeocoderRunnable(location));
         }
 
         GeckoAppShell.sendEventToGecko(new GeckoEvent(location, mLastGeoAddress));
     }
 
     public void onProviderDisabled(String provider)
     {
     }
new file mode 100644
--- /dev/null
+++ b/embedding/android/GeckoAsyncTask.java
@@ -0,0 +1,57 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Brad Lassey <blassey@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.gecko;
+
+// 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 void execute(final Params... params) {
+        GeckoAppShell.getHandler().post(new Runnable() {
+            public void run() {
+                final Result result = doInBackground(params);
+                GeckoApp.mAppContext.runOnUiThread(new Runnable() {
+                    public void run() {
+                        onPostExecute(result);
+                    }});
+            }});
+    }
+
+    protected abstract Result doInBackground(Params... params);
+    protected abstract void  onPostExecute(Result result);
+}
new file mode 100644
--- /dev/null
+++ b/embedding/android/GeckoThread.java
@@ -0,0 +1,128 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Brad Lassey <blassey@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.gecko;
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.content.res.Configuration;
+import android.util.Log;
+import android.widget.AbsoluteLayout;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Date;
+import java.util.Locale;
+
+public class GeckoThread extends Thread {
+
+    private static final String LOGTAG = "GeckoThread";
+
+    Intent mIntent;
+
+    GeckoThread (Intent intent) {
+        mIntent = intent;
+    }
+
+    public void run() {
+        final GeckoApp app = GeckoApp.mAppContext;
+        Intent intent = mIntent;
+        File cacheFile = GeckoAppShell.getCacheDir();
+        File libxulFile = new File(cacheFile, "libxul.so");
+
+        if ((!libxulFile.exists() ||
+             new File(app.getApplication().getPackageResourcePath()).lastModified() >= libxulFile.lastModified())) {
+            File[] libs = cacheFile.listFiles(new FilenameFilter() {
+                public boolean accept(File dir, String name) {
+                    return name.endsWith(".so");
+                }
+            });
+            if (libs != null) {
+                for (int i = 0; i < libs.length; i++) {
+                    libs[i].delete();
+                }
+            }
+        }
+
+        // At some point while loading the gecko libs our default locale gets set
+        // so just save it to locale here and reset it as default after the join
+        Locale locale = Locale.getDefault();
+        GeckoAppShell.loadGeckoLibs(
+            app.getApplication().getPackageResourcePath());
+        Locale.setDefault(locale);
+        Resources res = app.getBaseContext().getResources();
+        Configuration config = res.getConfiguration();
+        config.locale = locale;
+        res.updateConfiguration(config, res.getDisplayMetrics());
+
+        Log.w(LOGTAG, "zerdatime " + new Date().getTime() + " - runGecko");
+
+        // and then fire us up
+        try {
+            String uri = intent.getDataString();
+            String title = uri;
+            if (!app.mUserDefinedProfile &&
+                (uri == null || uri.length() == 0)) {
+                SharedPreferences prefs = app.getSharedPreferences("GeckoApp", app.MODE_PRIVATE);
+                uri = prefs.getString("last-uri", "");
+                title = prefs.getString("last-title", uri);
+            }
+
+            final String awesomeTitle = title;
+            app.mMainHandler.post(new Runnable() {
+                public void run() {
+                    app.mBrowserToolbar.setTitle(awesomeTitle);
+                }
+            });
+
+            Log.w(LOGTAG, "RunGecko - URI = " + uri);
+
+            GeckoAppShell.runGecko(app.getApplication().getPackageResourcePath(),
+                                   intent.getStringExtra("args"),
+                                   uri);
+        } catch (Exception e) {
+            Log.e(LOGTAG, "top level exception", e);
+            StringWriter sw = new StringWriter();
+            PrintWriter pw = new PrintWriter(sw);
+            e.printStackTrace(pw);
+            pw.flush();
+            GeckoAppShell.reportJavaCrash(sw.toString());
+        }
+    }
+}
--- a/embedding/android/Makefile.in
+++ b/embedding/android/Makefile.in
@@ -63,16 +63,18 @@ JAVAFILES = \
   GeckoPreferences.java \
   GlobalHistory.java \
   PromptService.java \
   SurfaceInfo.java \
   Tab.java \
   Tabs.java \
   TabsTray.java \
   GeckoBatteryManager.java \
+  GeckoThread.java \
+  GeckoAsyncTask.java \
   gfx/BufferedCairoImage.java \
   gfx/CairoImage.java \
   gfx/CairoUtils.java \
   gfx/FloatPoint.java \
   gfx/FloatRect.java \
   gfx/GeckoSoftwareLayerClient.java \
   gfx/InputConnectionHandler.java \
   gfx/IntPoint.java \
--- a/embedding/android/Tab.java
+++ b/embedding/android/Tab.java
@@ -37,17 +37,16 @@
 
 package org.mozilla.gecko;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
 import android.provider.Browser;
 import android.util.Log;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import java.io.InputStream;
 import java.io.IOException;
@@ -157,20 +156,20 @@ public class Tab {
         }
 
         Log.i(LOG_NAME, "Updated title: " + mTitle + " for tab with id: " + mId);
 
         final HistoryEntry he = getLastHistoryEntry();
         if (he != null) {
             he.mTitle = mTitle;
             GeckoAppShell.getHandler().post(new Runnable() {
-                    public void run() {
-                        GlobalHistory.getInstance().update(he.mUri, he.mTitle);
-                    }
-                });
+                public void run() {
+                    GlobalHistory.getInstance().update(he.mUri, he.mTitle);
+                }
+            });
         } else {
             Log.e(LOG_NAME, "Requested title update on empty history stack");
         }
     }
 
     public void setLoading(boolean loading) {
         mLoading = loading;
     }
@@ -184,17 +183,17 @@ public class Tab {
             return null;
         return mHistory.get(mHistoryIndex);
     }
 
     public void updateFavicon(Drawable favicon) {
         mFavicon = favicon;
         Log.i(LOG_NAME, "Updated favicon for tab with id: " + mId);
     }
- 
+
     public void updateFaviconURL(String faviconUrl) {
         mFaviconUrl = mFaviconUrl;
         Log.i(LOG_NAME, "Updated favicon URL for tab with id: " + mId);
     }
 
     public void updateSecurityMode(String mode) {
         mSecurityMode = mode;
     }
@@ -275,20 +274,20 @@ public class Tab {
             final String uri = message.getString("uri");
             mHistoryIndex++;
             while (mHistory.size() > mHistoryIndex) {
                 mHistory.remove(mHistoryIndex);
             }
             HistoryEntry he = new HistoryEntry(uri, null);
             mHistory.add(he);
             GeckoAppShell.getHandler().post(new Runnable() {
-                    public void run() {
-                        GlobalHistory.getInstance().add(uri);
-                    }
-                });
+                public void run() {
+                    GlobalHistory.getInstance().add(uri);
+                }
+            });
         } else if (event.equals("Back")) {
             if (mHistoryIndex - 1 < 0) {
                 Log.e(LOG_NAME, "Received unexpected back notification");
                 return;
             }
             mHistoryIndex--;
         } else if (event.equals("Forward")) {
             if (mHistoryIndex + 1 >= mHistory.size()) {
@@ -304,17 +303,17 @@ public class Tab {
             }
             mHistoryIndex = index;
         } else if (event.equals("Purge")) {
             mHistory.clear();
             mHistoryIndex = -1;
         }
     }
 
-    private class CheckBookmarkTask extends AsyncTask<Void, Void, Boolean> {
+    private class CheckBookmarkTask extends GeckoAsyncTask<Void, Void, Boolean> {
         @Override
         protected Boolean doInBackground(Void... unused) {
             ContentResolver resolver = Tabs.getInstance().getContentResolver();
             Cursor cursor = resolver.query(Browser.BOOKMARKS_URI,
                                            null,
                                            Browser.BookmarkColumns.URL + " = ? and " + Browser.BookmarkColumns.BOOKMARK + " = ?",
                                            new String[] { getURL(), "1" },
                                            Browser.BookmarkColumns.URL);
@@ -327,17 +326,17 @@ public class Tab {
         }
 
         @Override
         protected void onPostExecute(Boolean isBookmark) {
             setBookmark(isBookmark.booleanValue());
         }
     }
 
-    private class AddBookmarkTask extends AsyncTask<Void, Void, Void> {
+    private class AddBookmarkTask extends GeckoAsyncTask<Void, Void, Void> {
         @Override
         protected Void doInBackground(Void... unused) {
             ContentResolver resolver = Tabs.getInstance().getContentResolver();
             Cursor cursor = resolver.query(Browser.BOOKMARKS_URI,
                                            null,
                                            Browser.BookmarkColumns.URL + " = ?",
                                            new String[] { getURL() },
                                            Browser.BookmarkColumns.URL);
@@ -365,17 +364,17 @@ public class Tab {
         }
 
         @Override
         protected void onPostExecute(Void unused) {
             setBookmark(true);
         }
     }
 
-    private class RemoveBookmarkTask extends AsyncTask<Void, Void, Void> {
+    private class RemoveBookmarkTask extends GeckoAsyncTask<Void, Void, Void> {
         @Override
         protected Void doInBackground(Void... unused) {
             ContentResolver resolver = Tabs.getInstance().getContentResolver();
             ContentValues values = new ContentValues();
             values.put(Browser.BookmarkColumns.BOOKMARK, "0");
             resolver.update(Browser.BOOKMARKS_URI,
                             values,
                             Browser.BookmarkColumns.URL + " = ?",
@@ -383,9 +382,9 @@ public class Tab {
             return null;
         }
 
         @Override
         protected void onPostExecute(Void unused) {
             setBookmark(false);
         }
     }
-} 
+}