backout a965cebe4462 32220d7085e0 3689bb4199d8 d0c82cb6eb28 b295c8825acd and 95ab5c738512
authorWes Johnston <wjohnston@mozilla.com>
Thu, 08 Mar 2012 12:32:01 -0800
changeset 91451 5940fe8d1af98b9c57e677cb92511a2f28391663
parent 91450 ada07a6d6264a439dba82eea21cc695a77aef880
child 91452 b53e140ae2969619647b27215a50f93db26618ee
push id783
push userlsblakk@mozilla.com
push dateTue, 24 Apr 2012 17:33:42 +0000
treeherdermozilla-beta@11faed19f136 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone13.0a1
backs outa965cebe44623ba09f4e3a938d677b7b85e7541a
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
backout a965cebe4462 32220d7085e0 3689bb4199d8 d0c82cb6eb28 b295c8825acd and 95ab5c738512
build/mobile/robocop/Actions.java.in
build/mobile/robocop/FennecMochitestAssert.java.in
build/mobile/robocop/FennecNativeActions.java.in
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/GeckoMessageReceiver.java
mobile/android/base/GeckoThread.java
mobile/android/base/Makefile.in
mobile/android/base/NSSBridge.java
mobile/android/base/ProfileMigrator.java
mobile/android/base/db/BrowserContract.java.in
mobile/android/base/db/DBUtils.java
mobile/android/base/db/FormHistoryProvider.java.in
mobile/android/base/db/GeckoProvider.java.in
mobile/android/base/db/PasswordsProvider.java.in
mobile/android/base/sqlite/MatrixBlobCursor.java
mobile/android/base/tests/BaseTest.java.in
mobile/android/base/tests/robocop.ini
mobile/android/base/tests/testFormHistory.java.in
mobile/android/base/tests/testPasswordProvider.java.in
mozglue/android/APKOpen.cpp
mozglue/android/APKOpen.h
mozglue/android/Makefile.in
mozglue/android/NSSBridge.cpp
mozglue/android/NSSBridge.h
mozglue/android/SQLiteBridge.cpp
other-licenses/android/dlfcn.c
--- a/build/mobile/robocop/Actions.java.in
+++ b/build/mobile/robocop/Actions.java.in
@@ -34,19 +34,16 @@
  * 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 @ANDROID_PACKAGE_NAME@;
 import java.util.List;
-import java.util.ArrayList;
-
-import android.database.Cursor;
 
 public interface Actions {
 
     /** Special keys supported by sendSpecialKey() */
     public enum SpecialKey {
         DOWN, UP, LEFT, RIGHT, ENTER, MENU, BACK
     }
 
@@ -90,14 +87,9 @@ public interface Actions {
     /**
      * Send a special keycode to the element
      *
      * @param key The special key to send
      */
     void sendSpecialKey(SpecialKey key);
 
     void drag(int startingX, int endingX, int startingY, int endingY);
-
-    /**
-     * Run a sql query on the specified database
-     */
-    public Cursor querySql(String dbPath, String sql);
 }
--- a/build/mobile/robocop/FennecMochitestAssert.java.in
+++ b/build/mobile/robocop/FennecMochitestAssert.java.in
@@ -161,23 +161,31 @@ public class FennecMochitestAssert imple
 
     public void ok(boolean condition, String name, String diag) {
         testInfo test = new testInfo(condition, name, diag, false);
         _logMochitestResult(test, "TEST-PASS", "TEST-UNEXPECTED-FAIL");
         mTestList.add(test);
     }
 
     public void is(Object a, Object b, String name) {
-        boolean pass = checkObjectsEqual(a,b);
-        ok(pass, name, getEqualString(a,b, pass));
+        boolean pass = a.equals(b);
+        String diag = "got " + a.toString() + ", expected " + b.toString();
+        if (pass) {
+            diag = a.toString() + " should equal " + b.toString();
+        }
+        ok(pass, name, diag);
     }
     
     public void isnot(Object a, Object b, String name) {
-        boolean pass = checkObjectsNotEqual(a,b);
-        ok(pass, name, getNotEqualString(a,b,pass));
+        boolean pass = !a.equals(b);
+        String diag = "didn't expect " + a.toString() + ", but got it";
+        if (pass) {
+            diag = a.toString() + " should not equal " + b.toString();
+        }
+        ok(pass, name, diag);
     }
 
     public void ispixel(int actual, int r, int g, int b, String name) {
         // When we read GL pixels the GPU has already processed them and they
         // are usually off by a little bit. For example a CSS-color pixel of color #64FFF5
         // was turned into #63FFF7 when it came out of glReadPixels. So in order to compare
         // against the expected value, we use a little fuzz factor. For the alpha we just
         // make sure it is always 0xFF.
@@ -194,59 +202,30 @@ public class FennecMochitestAssert imple
 
     public void todo(boolean condition, String name, String diag) {
         testInfo test = new testInfo(condition, name, diag, true);
         _logMochitestResult(test, "TEST-UNEXPECTED-PASS", "TEST-KNOWN-FAIL");
         mTestList.add(test);
     }
 
     public void todo_is(Object a, Object b, String name) {
-        boolean pass = checkObjectsEqual(a,b);
-        todo(pass, name, getEqualString(a,b,pass));
-    }
-
-    public void todo_isnot(Object a, Object b, String name) {
-        boolean pass = checkObjectsNotEqual(a,b);
-        todo(pass, name, getNotEqualString(a,b,pass));
-    }
-
-    private boolean checkObjectsEqual(Object a, Object b) {
-        if (a == null || b == null) {
-            if (a == null && b == null) {
-                return true;
-            }
-            return false;
-        } else {
-            return a.equals(b);
-        }
-    }
-
-    private String getEqualString(Object a, Object b, boolean pass) {
+        boolean pass = a.equals(b);
+        String diag = "got " + a.toString() + ", expected " + b.toString();
         if (pass) {
-            return a + " should equal " + b;
+            diag = a.toString() + " should equal " + b.toString();
         }
-        return "got " + a + ", expected " + b;
+        todo(pass, name, diag);
     }
-
-    private boolean checkObjectsNotEqual(Object a, Object b) {
-        if (a == null || b == null) {
-            if ((a == null && b != null) || (a != null && b == null)) {
-                return true;
-            } else {
-                return false;
-            }
-        } else {
-            return !a.equals(b);
+    
+    public void todo_isnot(Object a, Object b, String name) {
+        boolean pass = !a.equals(b);
+        String diag = "didn't expect " + a.toString() + ", but got it";
+        if (pass) {
+            diag = a.toString() + " should not equal " + b.toString();
         }
-    }
-
-    private String getNotEqualString(Object a, Object b, boolean pass) {
-        if(pass) {
-            return a + " should not equal " + b;
-        }
-        return "didn't expect " + a + ", but got it";
+        todo(pass, name, diag);
     }
 
     public void info(String name, String message) {
         testInfo test = new testInfo(true, name, message, false);
         _logMochitestResult(test, "TEST-INFO", "INFO FAILED?");
     }
 }
--- a/build/mobile/robocop/FennecNativeActions.java.in
+++ b/build/mobile/robocop/FennecNativeActions.java.in
@@ -35,34 +35,29 @@
  * 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 @ANDROID_PACKAGE_NAME@;
 
 import java.lang.Class;
-import java.lang.ClassLoader;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.lang.reflect.InvocationHandler;
 import java.lang.Long;
-import java.util.concurrent.SynchronousQueue;
-import java.util.ArrayList;
 
 import android.app.Activity;
-import android.content.Context;
 import android.app.Instrumentation;
-import android.database.Cursor;
 import android.os.SystemClock;
 import android.view.View;
 import android.view.KeyEvent;
-import android.util.Log;
+
+import java.util.concurrent.SynchronousQueue;
 
 import org.json.*;
 
 import com.jayway.android.robotium.solo.Solo;
 
 public class FennecNativeActions implements Actions {
     private Solo mSolo;
     private Instrumentation mInstr;
@@ -74,17 +69,16 @@ public class FennecNativeActions impleme
     private Class mGe;
     private Class mGas;
     private Class mDrawListener;
     private Method mRegisterGEL;
     private Method mUnregisterGEL;
     private Method mSendGE;
     private Method mGetLayerClient;
     private Method mSetDrawListener;
-    private static final String LOGTAG = "FennecNativeActions";
 
     public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation) {
         mSolo = robocop;
         mInstr = instrumentation;
         mGeckoApp = activity;
         // Set up reflexive access of java classes and methods.
         try {
             mClassLoader = activity.getClassLoader();
@@ -350,41 +344,9 @@ public class FennecNativeActions impleme
     @Override
     public void sendKeys(String input) {
         mInstr.sendStringSync(input);
     }
 
     public void drag(int startingX, int endingX, int startingY, int endingY) {
         mSolo.drag(startingX, endingX, startingY, endingY, 10);
     }
-
-    public Cursor querySql(String dbPath, String sql) {
-        try {
-            ClassLoader classLoader = mGeckoApp.getClassLoader();
-            Class sqlClass = classLoader.loadClass("org.mozilla.gecko.sqlite.SQLiteBridge");
-            Class stringClass = String.class;
-            Class stringArrayClass = String[].class;
-            Class appshell = classLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
-            Class contextClass = Context.class;
-    
-            Constructor bridgeConstructor = sqlClass.getConstructor(stringClass);
-            Method query = sqlClass.getMethod("rawQuery", stringClass, stringArrayClass);
-            Method loadSQLiteLibs = appshell.getMethod("loadSQLiteLibs", contextClass, stringClass);
-    
-            Object bridge = bridgeConstructor.newInstance(dbPath);
-    
-            String resourcePath = mGeckoApp.getApplication().getPackageResourcePath();
-            loadSQLiteLibs.invoke(null, mGeckoApp, resourcePath);
-            return (Cursor)query.invoke(bridge, sql, null);
-        } catch(ClassNotFoundException ex) {
-            Log.e(LOGTAG, "Error getting class", ex);
-        } catch(NoSuchMethodException ex) {
-            Log.e(LOGTAG, "Error getting method", ex);
-        } catch(InvocationTargetException ex) {
-            Log.e(LOGTAG, "Error invoking method", ex);
-        } catch(InstantiationException ex) {
-            Log.e(LOGTAG, "Error calling constructor", ex);
-        } catch(IllegalAccessException ex) {
-            Log.e(LOGTAG, "Error using field", ex);
-        }
-        return null;
-    }
 }
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -18,17 +18,16 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
     <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
 
     <uses-permission android:name="android.permission.WAKE_LOCK"/>
     <uses-permission android:name="android.permission.VIBRATE"/>
-    <uses-permission android:name="@ANDROID_PACKAGE_NAME@.permissions.PASSWORD_PROVIDER"/>
 
 #ifdef MOZ_WEBSMS_BACKEND
     <!-- WebSMS -->
     <uses-permission android:name="android.permission.SEND_SMS"/>
     <uses-permission android:name="android.permission.RECEIVE_SMS"/>
     <uses-permission android:name="android.permission.WRITE_SMS"/>
     <uses-permission android:name="android.permission.READ_SMS"/>
 #endif
@@ -112,23 +111,16 @@
 
         <receiver android:name="NotificationHandler">
             <intent-filter>
                 <action android:name="org.mozilla.gecko.ACTION_ALERT_CLICK" />
                 <action android:name="org.mozilla.gecko.ACTION_ALERT_CLEAR" />
             </intent-filter>
         </receiver>
 
-        <receiver android:name="org.mozilla.gecko.GeckoMessageReceiver"
-                  android:permission="@ANDROID_PACKAGE_NAME@.permissions.PASSWORD_PROVIDER">
-            <intent-filter>
-                  <action android:name="org.mozilla.gecko.INIT_PW"></action>
-            </intent-filter>
-        </receiver>
-
         <activity android:name="Restarter"
                   android:process="@ANDROID_PACKAGE_NAME@Restarter"
                   android:theme="@style/Gecko"
                   android:excludeFromRecents="true">
           <intent-filter>
             <action android:name="org.mozilla.gecko.restart"/>
             <action android:name="org.mozilla.gecko.restart_update"/>
           </intent-filter>
@@ -174,33 +166,30 @@
                   android:excludeFromRecents="true"/>
 
         <provider android:name="@ANDROID_PACKAGE_NAME@.db.BrowserProvider"
                   android:authorities="@ANDROID_PACKAGE_NAME@.db.browser"
                   android:permission="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"/>
 
         <provider android:name="@ANDROID_PACKAGE_NAME@.db.PasswordsProvider"
                   android:authorities="@ANDROID_PACKAGE_NAME@.db.passwords"
-                  android:permission="@ANDROID_PACKAGE_NAME@.permissions.PASSWORD_PROVIDER"
-                  android:process="org.mozilla.gecko.PasswordsProvider"/>
+                  android:permission="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"
+                  android:protectionLevel="signature"/>
 
         <provider android:name="@ANDROID_PACKAGE_NAME@.db.FormHistoryProvider"
                   android:authorities="@ANDROID_PACKAGE_NAME@.db.formhistory"
                   android:permission="@ANDROID_PACKAGE_NAME@.permissions.FORMHISTORY_PROVIDER"
                   android:protectionLevel="signature"/>
 
         <provider android:name="@ANDROID_PACKAGE_NAME@.db.TabsProvider"
                   android:authorities="@ANDROID_PACKAGE_NAME@.db.tabs"
                   android:permission="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"/>
 
 #include ../sync/manifests/SyncAndroidManifest_services.xml.in
     </application>
 
     <permission android:name="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"
                 android:protectionLevel="signature"/>
 
-    <permission android:name="@ANDROID_PACKAGE_NAME@.permissions.PASSWORD_PROVIDER"
-                android:protectionLevel="signature"/>
-
     <permission android:name="@ANDROID_PACKAGE_NAME@.permissions.FORMHISTORY_PROVIDER"
                 android:protectionLevel="signature"/>
 
 </manifest> 
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -104,29 +104,29 @@ abstract public class GeckoApp
 
     public static final String ACTION_ALERT_CLICK   = "org.mozilla.gecko.ACTION_ALERT_CLICK";
     public static final String ACTION_ALERT_CLEAR   = "org.mozilla.gecko.ACTION_ALERT_CLEAR";
     public static final String ACTION_WEBAPP        = "org.mozilla.gecko.WEBAPP";
     public static final String ACTION_DEBUG         = "org.mozilla.gecko.DEBUG";
     public static final String ACTION_BOOKMARK      = "org.mozilla.gecko.BOOKMARK";
     public static final String ACTION_LOAD          = "org.mozilla.gecko.LOAD";
     public static final String ACTION_UPDATE        = "org.mozilla.gecko.UPDATE";
-    public static final String ACTION_INIT_PW       = "org.mozilla.gecko.INIT_PW";
     public static final String SAVED_STATE_URI      = "uri";
     public static final String SAVED_STATE_TITLE    = "title";
     public static final String SAVED_STATE_VIEWPORT = "viewport";
     public static final String SAVED_STATE_SCREEN   = "screen";
     public static final String SAVED_STATE_SESSION  = "session";
 
     StartupMode mStartupMode = null;
     private LinearLayout mMainLayout;
     private RelativeLayout mGeckoLayout;
     public static SurfaceView cameraView;
     public static GeckoApp mAppContext;
     public static boolean mDOMFullScreen = false;
+    public static File sGREDir = null;
     public static Menu sMenu;
     private static GeckoThread sGeckoThread = null;
     public GeckoAppHandler mMainHandler;
     private GeckoProfile mProfile;
     public static boolean sIsGeckoReady = false;
     public static int mOrientation;
 
     private IntentFilter mConnectivityFilter;
@@ -1611,17 +1611,17 @@ abstract public class GeckoApp
     {
         mAppContext = this;
 
         // StrictMode is set by defaults resource flag |enableStrictMode|.
         if (getResources().getBoolean(R.bool.enableStrictMode)) {
             enableStrictMode();
         }
 
-        GeckoAppShell.loadMozGlue();
+        System.loadLibrary("mozglue");
         mMainHandler = new GeckoAppHandler();
         Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - onCreate");
         if (savedInstanceState != null) {
             mLastTitle = savedInstanceState.getString(SAVED_STATE_TITLE);
             mLastViewport = savedInstanceState.getString(SAVED_STATE_VIEWPORT);
             mLastScreen = savedInstanceState.getByteArray(SAVED_STATE_SCREEN);
             mRestoreSession = savedInstanceState.getBoolean(SAVED_STATE_SESSION);
         }
@@ -1682,16 +1682,19 @@ abstract public class GeckoApp
             if (! getProfile().hasSession()) {
                 mBrowserToolbar.updateTabCount(1);
                 showAboutHome();
             }
         } else {
             mBrowserToolbar.updateTabCount(1);
         }
 
+        if (sGREDir == null)
+            sGREDir = new File(this.getApplicationInfo().dataDir);
+
         Uri data = intent.getData();
         if (data != null && "http".equals(data.getScheme()) &&
             isHostOnPrefetchWhitelist(data.getHost())) {
             Intent copy = new Intent(intent);
             copy.setAction(ACTION_LOAD);
             GeckoAppShell.getHandler().post(new RedirectorRunnable(copy));
             // We're going to handle this uri with the redirector, so setting
             // the action to MAIN and clearing the uri data prevents us from
@@ -2505,17 +2508,17 @@ abstract public class GeckoApp
                     int period;
                     if (name == null || (period = name.lastIndexOf('.')) == -1) {
                         String mimeType = cr.getType(uri);
                         fileExt = "." + GeckoAppShell.getExtensionFromMimeType(mimeType);
                     } else {
                         fileExt = name.substring(period);
                         fileName = name.substring(0, period);
                     }
-                    File file = File.createTempFile(fileName, fileExt, GeckoAppShell.getGREDir(GeckoApp.mAppContext));
+                    File file = File.createTempFile(fileName, fileExt, sGREDir);
 
                     FileOutputStream fos = new FileOutputStream(file);
                     InputStream is = cr.openInputStream(uri);
                     byte[] buf = new byte[4096];
                     int len = is.read(buf);
                     while (len != -1) {
                         fos.write(buf, 0, len);
                         len = is.read(buf);
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -107,19 +107,16 @@ public class GeckoAppShell
     static public final int WPL_STATE_IS_DOCUMENT = 0x00020000;
     static public final int WPL_STATE_IS_NETWORK = 0x00040000;
 
     static private File sCacheFile = null;
     static private int sFreeSpace = -1;
     static File sHomeDir = null;
     static private int sDensityDpi = 0;
     private static Boolean sSQLiteLibsLoaded = false;
-    private static Boolean sNSSLibsLoaded = false;
-    private static Boolean sLibsSetup = false;
-    private static File sGREDir = null;
 
     private static HashMap<String, ArrayList<GeckoEventListener>> mEventListeners;
 
     /* Is the value in sVibrationEndTime valid? */
     private static boolean sVibrationMaybePlaying = false;
 
     /* Time (in System.nanoTime() units) when the currently-playing vibration
      * is scheduled to end.  This value is valid only when
@@ -136,18 +133,17 @@ public class GeckoAppShell
     //    public static native void setSurfaceView(GeckoSurfaceView sv);
     public static native void setSoftwareLayerClient(GeckoSoftwareLayerClient client);
     public static native void putenv(String map);
     public static native void onResume();
     public static native void onLowMemory();
     public static native void callObserver(String observerKey, String topic, String data);
     public static native void removeObserver(String observerKey);
     public static native void loadGeckoLibsNative(String apkName);
-    public static native void loadSQLiteLibsNative(String apkName);
-    public static native void loadNSSLibsNative(String apkName);
+    public static native void loadSQLiteLibsNative(String apkName, boolean shouldExtract);
     public static native void onChangeNetworkLinkStatus(String status);
 
     public static void reportJavaCrash(Throwable e) {
         Log.e(LOGTAG, "top level exception", e);
         StringWriter sw = new StringWriter();
         PrintWriter pw = new PrintWriter(sw);
         e.printStackTrace(pw);
         pw.flush();
@@ -211,173 +207,142 @@ public class GeckoAppShell
     public static Handler getMainHandler() {
         return GeckoApp.mAppContext.mMainHandler;
     }
 
     public static Handler getHandler() {
         return GeckoBackgroundThread.getHandler();
     }
 
-    public static File getCacheDir(Context context) {
+    public static File getCacheDir() {
         if (sCacheFile == null)
-            sCacheFile = context.getCacheDir();
+            sCacheFile = GeckoApp.mAppContext.getCacheDir();
         return sCacheFile;
     }
 
-    public static long getFreeSpace(Context context) {
+    public static long getFreeSpace() {
         try {
             if (sFreeSpace == -1) {
-                File cacheDir = getCacheDir(context);
+                File cacheDir = getCacheDir();
                 if (cacheDir != null) {
                     StatFs cacheStats = new StatFs(cacheDir.getPath());
                     sFreeSpace = cacheStats.getFreeBlocks() *
                         cacheStats.getBlockSize();
                 } else {
                     Log.i(LOGTAG, "Unable to get cache dir");
                 }
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "exception while stating cache dir: ", e);
         }
         return sFreeSpace;
     }
 
-    public static File getGREDir(Context context) {
-        if (sGREDir == null)
-            sGREDir = new File(context.getApplicationInfo().dataDir);
-        return sGREDir;
-    }
-
     // java-side stuff
-    public static void loadLibsSetup(Context context) {
-        if (sLibsSetup)
-            return;
-
+    public static boolean loadLibsSetup(String apkName) {
         // The package data lib directory isn't placed in ld.so's
         // search path, so we have to manually load libraries that
         // libxul will depend on.  Not ideal.
-        GeckoProfile profile = GeckoProfile.get(context);
-
-        File cacheFile = getCacheDir(context);
-        putenv("GRE_HOME=" + getGREDir(context).getPath());
+        GeckoApp geckoApp = GeckoApp.mAppContext;
+        GeckoProfile profile = geckoApp.getProfile();
+        profile.moveProfilesToAppInstallLocation();
 
-        // setup the libs cache
-        String linkerCache = System.getenv("MOZ_LINKER_CACHE");
-        if (System.getenv("MOZ_LINKER_CACHE") == null) {
-            GeckoAppShell.putenv("MOZ_LINKER_CACHE=" + cacheFile.getPath());
-        }
-        sLibsSetup = true;
-    }
-
-    private static void setupPluginEnvironment(GeckoApp context) {
-        // setup plugin path directories
         try {
-            String[] dirs = context.getPluginDirectories();
+            String[] dirs = GeckoApp.mAppContext.getPluginDirectories();
             StringBuffer pluginSearchPath = new StringBuffer();
             for (int i = 0; i < dirs.length; i++) {
                 Log.i(LOGTAG, "dir: " + dirs[i]);
                 pluginSearchPath.append(dirs[i]);
                 pluginSearchPath.append(":");
             }
             GeckoAppShell.putenv("MOZ_PLUGIN_PATH="+pluginSearchPath);
-
-            File pluginDataDir = context.getDir("plugins", 0);
-            GeckoAppShell.putenv("ANDROID_PLUGIN_DATADIR=" + pluginDataDir.getPath());
-
         } catch (Exception ex) {
             Log.i(LOGTAG, "exception getting plugin dirs", ex);
         }
-    }
+
+        GeckoAppShell.putenv("HOME=" + profile.getFilesDir().getPath());
+        GeckoAppShell.putenv("GRE_HOME=" + GeckoApp.sGREDir.getPath());
+        Intent i = geckoApp.getIntent();
+        String env = i.getStringExtra("env0");
+        Log.i(LOGTAG, "env0: "+ env);
+        for (int c = 1; env != null; c++) {
+            GeckoAppShell.putenv(env);
+            env = i.getStringExtra("env" + c);
+            Log.i(LOGTAG, "env"+ c +": "+ env);
+        }
+
+        File f = geckoApp.getDir("tmp", Context.MODE_WORLD_READABLE |
+                                 Context.MODE_WORLD_WRITEABLE );
 
-    private static void setupDownloadEnvironment(GeckoApp context) {
+        if (!f.exists())
+            f.mkdirs();
+
+        GeckoAppShell.putenv("TMPDIR=" + f.getPath());
+
+        f = Environment.getDownloadCacheDirectory();
+        GeckoAppShell.putenv("EXTERNAL_STORAGE=" + f.getPath());
+
+        File cacheFile = getCacheDir();
+        String linkerCache = System.getenv("MOZ_LINKER_CACHE");
+        if (System.getenv("MOZ_LINKER_CACHE") == null) {
+            GeckoAppShell.putenv("MOZ_LINKER_CACHE=" + cacheFile.getPath());
+        }
+
+        File pluginDataDir = GeckoApp.mAppContext.getDir("plugins", 0);
+        GeckoAppShell.putenv("ANDROID_PLUGIN_DATADIR=" + pluginDataDir.getPath());
+
+        // gingerbread introduces File.getUsableSpace(). We should use that.
+        long freeSpace = getFreeSpace();
         try {
             File downloadDir = null;
             File updatesDir  = null;
             if (Build.VERSION.SDK_INT >= 8) {
                 downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
-                updatesDir  = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
+                updatesDir  = GeckoApp.mAppContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
             } else {
                 updatesDir = downloadDir = new File(Environment.getExternalStorageDirectory().getPath(), "download");
             }
             GeckoAppShell.putenv("DOWNLOADS_DIRECTORY=" + downloadDir.getPath());
             GeckoAppShell.putenv("UPDATES_DIRECTORY="   + updatesDir.getPath());
         }
         catch (Exception e) {
             Log.i(LOGTAG, "No download directory has been found: " + e);
         }
+
+        putLocaleEnv();
+
+        boolean extractLibs = GeckoApp.ACTION_DEBUG.equals(i.getAction());
+        if (!extractLibs) {
+            // remove any previously extracted libs
+            File[] files = cacheFile.listFiles();
+            if (files != null) {
+                Iterator<File> cacheFiles = Arrays.asList(files).iterator();
+                while (cacheFiles.hasNext()) {
+                    File libFile = cacheFiles.next();
+                    if (libFile.getName().endsWith(".so"))
+                        libFile.delete();
+                }
+            }
+        }
+        return extractLibs;
     }
 
-    public static void setupGeckoEnvironment(Context context) {
-        GeckoProfile profile = GeckoProfile.get(context);
-        profile.moveProfilesToAppInstallLocation();
-
-        setupPluginEnvironment((GeckoApp) context);
-        setupDownloadEnvironment((GeckoApp) context);
-
-        // profile home path
-        GeckoAppShell.putenv("HOME=" + profile.getFilesDir().getPath());
-
-        Intent i = null;
-        i = ((Activity)context).getIntent();
-
-        // if we have an intent (we're being launched by an activity)
-        // read in any environmental variables from it here
-        String env = i.getStringExtra("env0");
-        Log.i(LOGTAG, "env0: "+ env);
-        for (int c = 1; env != null; c++) {
-            GeckoAppShell.putenv(env);
-            env = i.getStringExtra("env" + c);
-            Log.i(LOGTAG, "env"+ c +": "+ env);
-        }
-        // setup the tmp path
-        File f = context.getDir("tmp", Context.MODE_WORLD_READABLE |
-                                 Context.MODE_WORLD_WRITEABLE );
-        if (!f.exists())
-            f.mkdirs();
-        GeckoAppShell.putenv("TMPDIR=" + f.getPath());
-
-        // setup the downloads path
-        f = Environment.getDownloadCacheDirectory();
-        GeckoAppShell.putenv("EXTERNAL_STORAGE=" + f.getPath());
-
-        putLocaleEnv();
-    }
-
-    public static void loadSQLiteLibs(Context context, String apkName) {
+    public static void ensureSQLiteLibsLoaded(String apkName) {
         if (sSQLiteLibsLoaded)
             return;
         synchronized(sSQLiteLibsLoaded) {
             if (sSQLiteLibsLoaded)
                 return;
-            loadMozGlue();
-            loadLibsSetup(context);
-            loadSQLiteLibsNative(apkName);
+            loadSQLiteLibsNative(apkName, loadLibsSetup(apkName));
             sSQLiteLibsLoaded = true;
         }
     }
 
-    public static void loadNSSLibs(Context context, String apkName) {
-        if (sNSSLibsLoaded)
-            return;
-        synchronized(sNSSLibsLoaded) {
-            if (sNSSLibsLoaded)
-                return;
-            loadMozGlue();
-            loadLibsSetup(context);
-            loadNSSLibsNative(apkName);
-            sNSSLibsLoaded = true;
-        }
-    }
-
-    public static void loadMozGlue() {
-        System.loadLibrary("mozglue");
-    }
-
     public static void loadGeckoLibs(String apkName) {
-        loadLibsSetup(GeckoApp.mAppContext);
+        boolean extractLibs = loadLibsSetup(apkName);
         loadGeckoLibsNative(apkName);
     }
 
     private static void putLocaleEnv() {
         GeckoAppShell.putenv("LANG=" + Locale.getDefault().toString());
         NumberFormat nf = NumberFormat.getInstance();
         if (nf instanceof DecimalFormat) {
             DecimalFormat df = (DecimalFormat)nf;
deleted file mode 100644
--- a/mobile/android/base/GeckoMessageReceiver.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/* 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 android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-public class GeckoMessageReceiver extends BroadcastReceiver {
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        final String action = intent.getAction();
-        if (GeckoApp.ACTION_INIT_PW.equals(action)) {
-            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Passwords:Init", null));
-        }
-    }
-}
--- a/mobile/android/base/GeckoThread.java
+++ b/mobile/android/base/GeckoThread.java
@@ -61,17 +61,17 @@ public class GeckoThread extends Thread 
     GeckoThread (Intent intent, String uri, boolean restoreSession) {
         mIntent = intent;
         mUri = uri;
         mRestoreSession = restoreSession;
     }
 
     public void run() {
         final GeckoApp app = GeckoApp.mAppContext;
-        File cacheFile = GeckoAppShell.getCacheDir(app);
+        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");
                 }
@@ -81,23 +81,19 @@ public class GeckoThread extends Thread 
                     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();
-
         String resourcePath = app.getApplication().getPackageResourcePath();
-        GeckoAppShell.setupGeckoEnvironment(app);
-        GeckoAppShell.loadSQLiteLibs(app, resourcePath);
-        GeckoAppShell.loadNSSLibs(app, resourcePath);
+        GeckoAppShell.ensureSQLiteLibsLoaded(resourcePath);
         GeckoAppShell.loadGeckoLibs(resourcePath);
-
         Locale.setDefault(locale);
         Resources res = app.getBaseContext().getResources();
         Configuration config = res.getConfiguration();
         config.locale = locale;
         res.updateConfiguration(config, res.getDisplayMetrics());
 
         Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - runGecko");
 
@@ -107,11 +103,10 @@ public class GeckoThread extends Thread 
 
             GeckoAppShell.runGecko(app.getApplication().getPackageResourcePath(),
                                    mIntent.getStringExtra("args"),
                                    mUri,
                                    mRestoreSession);
         } catch (Exception e) {
             GeckoAppShell.reportJavaCrash(e);
         }
-
     }
 }
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -83,24 +83,22 @@ FENNEC_JAVA_FILES = \
   GeckoAsyncTask.java \
   GeckoBatteryManager.java \
   GeckoBackgroundThread.java \
   GeckoConnectivityReceiver.java \
   GeckoEvent.java \
   GeckoEventListener.java \
   GeckoEventResponder.java \
   GeckoInputConnection.java \
-  GeckoMessageReceiver.java \
   GeckoPreferences.java \
   GeckoProfile.java \
   GeckoStateListDrawable.java \
   GeckoThread.java \
   GlobalHistory.java \
   LinkPreference.java \
-  NSSBridge.java \
   ProfileMigrator.java \
   PromptService.java \
   sqlite/ByteBufferInputStream.java \
   sqlite/MatrixBlobCursor.java \
   sqlite/SQLiteBridge.java \
   sqlite/SQLiteBridgeException.java \
   SetupScreen.java \
   SurfaceLockInfo.java \
deleted file mode 100644
--- a/mobile/android/base/NSSBridge.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/* 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 android.app.Activity;
-import android.util.Log;
-import android.content.Context;
-import java.lang.String;
-
-public class NSSBridge {
-    private static final String LOGTAG = "NSSBridge";
-
-    private static native String nativeEncrypt(String aDb, String aValue);
-    private static native String nativeDecrypt(String aDb, String aValue);
-
-    static public String encrypt(Context context, String aValue) {
-        String resourcePath = context.getPackageResourcePath();
-        GeckoAppShell.loadNSSLibs(context, resourcePath);
-
-        String res = "";
-        try {
-            String path = GeckoProfile.get(context).getDir().toString();
-            res = nativeEncrypt(path, aValue);
-        } catch(Exception ex) { }
-        return res;
-    }
-
-    static public String encrypt(Context context, String profilePath, String aValue) {
-        String resourcePath = context.getPackageResourcePath();
-        GeckoAppShell.loadNSSLibs(context, resourcePath);
-
-        String res = "";
-        try {
-            res = nativeEncrypt(profilePath, aValue);
-        } catch(Exception ex) { }
-        return res;
-    }
-
-    static public String decrypt(Context context, String aValue) {
-        String resourcePath = context.getPackageResourcePath();
-        GeckoAppShell.loadNSSLibs(context, resourcePath);
-
-        String res = "";
-        try {
-            String path = GeckoProfile.get(context).getDir().toString();
-            res = nativeDecrypt(path, aValue);
-        } catch(Exception ex) { }
-        return res;
-    }
-
-    static public String decrypt(Context context, String profilePath, String aValue) {
-        String resourcePath = context.getPackageResourcePath();
-        GeckoAppShell.loadNSSLibs(context, resourcePath);
-
-        String res = "";
-        try {
-            res = nativeDecrypt(profilePath, aValue);
-        } catch(Exception ex) { }
-        return res;
-    }
-}
--- a/mobile/android/base/ProfileMigrator.java
+++ b/mobile/android/base/ProfileMigrator.java
@@ -635,17 +635,17 @@ public class ProfileMigrator {
             if (!dbFile.exists()) {
                 Log.i(LOGTAG, "No database");
                 return;
             }
             File dbFileWal = new File(dbPathWal);
             File dbFileShm = new File(dbPathShm);
 
             SQLiteBridge db = null;
-            GeckoAppShell.loadSQLiteLibs(GeckoApp.mAppContext, GeckoApp.mAppContext.getApplication().getPackageResourcePath());
+            GeckoAppShell.ensureSQLiteLibsLoaded(GeckoApp.mAppContext.getApplication().getPackageResourcePath());
             try {
                 db = new SQLiteBridge(dbPath);
                 calculateReroot(db);
                 migrateBookmarks(db);
                 migrateHistory(db);
                 db.close();
 
                 // Clean up
@@ -659,17 +659,17 @@ public class ProfileMigrator {
                     db.close();
                 }
                 Log.e(LOGTAG, "Error on places database:", e);
                 return;
             }
         }
 
         protected void cleanupXULLibCache() {
-            File cacheFile = GeckoAppShell.getCacheDir(GeckoApp.mAppContext);
+            File cacheFile = GeckoAppShell.getCacheDir();
             File[] files = cacheFile.listFiles();
             if (files != null) {
                 Iterator<File> cacheFiles = Arrays.asList(files).iterator();
                 while (cacheFiles.hasNext()) {
                     File libFile = cacheFiles.next();
                     if (libFile.getName().endsWith(".so")) {
                         libFile.delete();
                     }
--- a/mobile/android/base/db/BrowserContract.java.in
+++ b/mobile/android/base/db/BrowserContract.java.in
@@ -40,20 +40,25 @@ package org.mozilla.gecko.db;
 
 import android.net.Uri;
 
 public class BrowserContract {
     public static final String AUTHORITY = "@ANDROID_PACKAGE_NAME@.db.browser";
     public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
 
     public static final String PASSWORDS_AUTHORITY = "@ANDROID_PACKAGE_NAME@.db.passwords";
+    public static final String DELETED_PASSWORDS_AUTHORITY = "@ANDROID_PACKAGE_NAME@.db.deleted-passwords";
+
     public static final Uri PASSWORDS_AUTHORITY_URI = Uri.parse("content://" + PASSWORDS_AUTHORITY);
+    public static final Uri DELETED_PASSWORDS_AUTHORITY_URI = Uri.parse("content://" + DELETED_PASSWORDS_AUTHORITY);
 
     public static final String FORM_HISTORY_AUTHORITY = "@ANDROID_PACKAGE_NAME@.db.formhistory";
+    public static final String DELETED_FORM_HISTORY_AUTHORITY = "@ANDROID_PACKAGE_NAME@.db.deleted-formhistory";
     public static final Uri FORM_HISTORY_AUTHORITY_URI = Uri.parse("content://" + FORM_HISTORY_AUTHORITY);
+    public static final Uri DELETED_FORM_HISTORY_AUTHORITY_URI = Uri.parse("content://" + DELETED_FORM_HISTORY_AUTHORITY);
     
     public static final String TABS_AUTHORITY = "@ANDROID_PACKAGE_NAME@.db.tabs";
     public static final Uri TABS_AUTHORITY_URI = Uri.parse("content://" + TABS_AUTHORITY);
 
     public static final String DEFAULT_PROFILE = "default";
     public static final String PARAM_PROFILE = "profile";
     public static final String PARAM_PROFILE_PATH = "profilePath";
     public static final String PARAM_LIMIT = "limit";
@@ -158,17 +163,17 @@ public class BrowserContract {
         public static final String TIME_PASSWORD_CHANGED = "timePasswordChanged";
         public static final String TIMES_USED = "timesUsed";
         public static final String GUID = "guid";
     }
 
     public static final class DeletedPasswords implements DeletedColumns {
         private DeletedPasswords() {}
         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/deleted-passwords";
-        public static final Uri CONTENT_URI = Uri.withAppendedPath(PASSWORDS_AUTHORITY_URI, "deleted-passwords");
+        public static final Uri CONTENT_URI = Uri.withAppendedPath(DELETED_PASSWORDS_AUTHORITY_URI, "deleted-formhistory");
     }
 
     public static final class FormHistory {
         private FormHistory() {}
         public static final Uri CONTENT_URI = Uri.withAppendedPath(FORM_HISTORY_AUTHORITY_URI, "formhistory");
         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/formhistory";
 
         public static final String ID = "id";
@@ -177,17 +182,17 @@ public class BrowserContract {
         public static final String TIMES_USED = "timesUsed";
         public static final String FIRST_USED = "firstUsed";
         public static final String LAST_USED = "lastUsed";
         public static final String GUID = "guid";
     }
 
     public static final class DeletedFormHistory implements DeletedColumns {
         private DeletedFormHistory() {}
-        public static final Uri CONTENT_URI = Uri.withAppendedPath(FORM_HISTORY_AUTHORITY_URI, "deleted-formhistory");
+        public static final Uri CONTENT_URI = Uri.withAppendedPath(DELETED_FORM_HISTORY_AUTHORITY_URI, "deleted-formhistory");
         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/deleted-formhistory";
     }
 
     public static final class Tabs implements CommonColumns {
         private Tabs() {}
         public static final Uri CONTENT_URI = Uri.withAppendedPath(TABS_AUTHORITY_URI, "tabs");
         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/tab";
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/tab";
--- a/mobile/android/base/db/DBUtils.java
+++ b/mobile/android/base/db/DBUtils.java
@@ -54,13 +54,13 @@ public class DBUtils {
     public static void replaceKey(ContentValues aValues, String aOriginalKey,
                                   String aNewKey, String aDefault) {
         String value = aDefault;
         if (aOriginalKey != null && aValues.containsKey(aOriginalKey)) {
             value = aValues.get(aOriginalKey).toString();
             aValues.remove(aOriginalKey);
         }
 
-        if (!aValues.containsKey(aNewKey)) {
+        if (!aValues.containsKey(aOriginalKey)) {
             aValues.put(aNewKey, value);
         }
     }
 }
--- a/mobile/android/base/db/FormHistoryProvider.java.in
+++ b/mobile/android/base/db/FormHistoryProvider.java.in
@@ -28,16 +28,19 @@ import org.mozilla.gecko.sqlite.SQLiteBr
 import org.mozilla.gecko.sync.Utils;
 
 import android.content.ContentProvider;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.UriMatcher;
 import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
 import android.os.Build;
 import android.text.TextUtils;
 import android.util.Log;
 
 public class FormHistoryProvider extends GeckoProvider {
     static final String TABLE_FORM_HISTORY = "moz_formhistory";
     static final String TABLE_DELETED_FORM_HISTORY = "moz_deleted_formhistory";
@@ -52,17 +55,17 @@ public class FormHistoryProvider extends
 
     // This should be kept in sync with the db version in toolkit/components/satchel/nsFormHistory.js
     private static int DB_VERSION = 4;
     private static String DB_FILENAME = "formhistory.sqlite";
 
     static {
         URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
         URI_MATCHER.addURI(BrowserContract.FORM_HISTORY_AUTHORITY, "formhistory", FORM_HISTORY);
-        URI_MATCHER.addURI(BrowserContract.FORM_HISTORY_AUTHORITY, "deleted-formhistory", DELETED_FORM_HISTORY);
+        URI_MATCHER.addURI(BrowserContract.DELETED_FORM_HISTORY_AUTHORITY, "deleted-formhistory", DELETED_FORM_HISTORY);
         FORM_HISTORY_PROJECTION_MAP = new HashMap<String, String>();
         DELETED_FORM_HISTORY_PROJECTION_MAP = new HashMap<String, String>();
     }
 
     @Override
     public boolean onCreate() {
         setLogTag("FormHistoryProvider");
         setDBName(DB_FILENAME);
@@ -138,34 +141,9 @@ public class FormHistoryProvider extends
             default:
                 throw new UnsupportedOperationException("Unknown insert URI " + uri);
         }
     }
 
     public void initGecko() {
         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FormHistory:Init", null));
     }
-
-    @Override
-    public void onPreInsert(ContentValues values, Uri uri, SQLiteBridge db) {
-        if (!values.containsKey(FormHistory.GUID)) {
-            return;
-        }
-        String guid = values.getAsString(FormHistory.GUID);
-        String where = BrowserContract.DeletedFormHistory.GUID + " = ?";
-        String[] args = new String[] { guid };
-        if (guid == null) {
-            where = BrowserContract.DeletedFormHistory.GUID + " IS NULL";
-            args = null;
-        }
-        try {
-            db.delete(TABLE_DELETED_FORM_HISTORY, where, args);
-        } catch(SQLiteBridgeException ex) {
-            Log.w(getLogTag(), "Error removing entry with GUID " + guid, ex);
-        }
-     }
-
-    @Override
-    public void onPreUpdate(ContentValues values, Uri uri, SQLiteBridge db) { }
-
-    @Override
-    public void onPostQuery(Cursor cursor, Uri uri, SQLiteBridge db) { }
 }
--- a/mobile/android/base/db/GeckoProvider.java.in
+++ b/mobile/android/base/db/GeckoProvider.java.in
@@ -83,19 +83,16 @@ public abstract class GeckoProvider exte
         return mDBVersion;
     }
 
     private SQLiteBridge getDB(Context context, final String databasePath) {
         SQLiteBridge bridge = null;
 
         boolean dbNeedsSetup = true;
         try {
-            String resourcePath = context.getPackageResourcePath();
-            GeckoAppShell.loadSQLiteLibs(context, resourcePath);
-            GeckoAppShell.loadNSSLibs(context, resourcePath);
             bridge = new SQLiteBridge(databasePath);
             int version = bridge.getVersion();
             Log.i(mLogTag, version + " == " + mDBVersion);
             dbNeedsSetup = version != mDBVersion;
         } catch(SQLiteBridgeException ex) {
             // this will throw if the database can't be found
             // we should attempt to set it up if Gecko is running
             dbNeedsSetup = true;
@@ -217,18 +214,16 @@ public abstract class GeckoProvider exte
         // If we can not get a SQLiteBridge instance, its likely that the database
         // has not been set up and Gecko is not running. We return null and expect
         // callers to try again later
         if (db == null)
             return null;
 
         setupDefaults(uri, values);
 
-        onPreInsert(values, uri, db);
-
         try {
             id = db.insert(getTable(uri), null, values);
         } catch(SQLiteBridgeException ex) {
             Log.e(mLogTag, "Error inserting in db", ex);
         }
 
         return ContentUris.withAppendedId(uri, id);
     }
@@ -240,18 +235,16 @@ public abstract class GeckoProvider exte
         final SQLiteBridge db = getDatabase(uri);
 
         // If we can not get a SQLiteBridge instance, its likely that the database
         // has not been set up and Gecko is not running. We return null and expect
         // callers to try again later
         if (db == null)
             return updated;
 
-        onPreUpdate(values, uri, db);
-
         try {
             updated = db.update(getTable(uri), values, selection, selectionArgs);
         } catch(SQLiteBridgeException ex) {
             Log.e(mLogTag, "Error updating table", ex);
         }
 
         return updated;
     }
@@ -267,30 +260,23 @@ public abstract class GeckoProvider exte
         // callers to try again later
         if (db == null)
             return cursor;
 
         sortOrder = getSortOrder(uri, sortOrder);
 
         try {
             cursor = db.query(getTable(uri), projection, selection, selectionArgs, null, null, sortOrder, null);
-            onPostQuery(cursor, uri, db);
         } catch (SQLiteBridgeException ex) {
             Log.e(mLogTag, "Error querying database", ex);
         }
 
         return cursor;
     }
 
     public abstract String getTable(Uri uri);
 
     public abstract String getSortOrder(Uri uri, String aRequested);
 
     public abstract void setupDefaults(Uri uri, ContentValues values);
 
     public abstract void initGecko();
-
-    public abstract void onPreInsert(ContentValues values, Uri uri, SQLiteBridge db);
-
-    public abstract void onPreUpdate(ContentValues values, Uri uri, SQLiteBridge db);
-
-    public abstract void onPostQuery(Cursor cursor, Uri uri, SQLiteBridge db);
 }
--- a/mobile/android/base/db/PasswordsProvider.java.in
+++ b/mobile/android/base/db/PasswordsProvider.java.in
@@ -12,34 +12,35 @@ import java.util.HashMap;
 import java.util.ArrayList;
 import java.util.Random;
 
 import org.mozilla.gecko.GeckoApp;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.GeckoEventListener;
 import org.mozilla.gecko.GeckoProfile;
-import org.mozilla.gecko.NSSBridge;
+import org.mozilla.gecko.db.BrowserContract.CommonColumns;
 import org.mozilla.gecko.db.DBUtils;
 import org.mozilla.gecko.db.BrowserContract.Passwords;
 import org.mozilla.gecko.db.BrowserContract.DeletedPasswords;
 import org.mozilla.gecko.db.BrowserContract.SyncColumns;
 import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.sqlite.MatrixBlobCursor;
 import org.mozilla.gecko.sqlite.SQLiteBridge;
 import org.mozilla.gecko.sqlite.SQLiteBridgeException;
 import org.mozilla.gecko.sync.Utils;
 
 import android.content.ContentProvider;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.Intent;
 import android.content.UriMatcher;
 import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
 import android.os.Build;
 import android.text.TextUtils;
 import android.util.Log;
 
 public class PasswordsProvider extends GeckoProvider {
     static final String TABLE_PASSWORDS = "moz_logins";
     static final String TABLE_DELETED_PASSWORDS = "moz_deleted_logins";
@@ -76,23 +77,22 @@ public class PasswordsProvider extends G
         PASSWORDS_PROJECTION_MAP.put(Passwords.ENCRYPTED_PASSWORD, Passwords.ENCRYPTED_PASSWORD);
         PASSWORDS_PROJECTION_MAP.put(Passwords.GUID, Passwords.GUID);
         PASSWORDS_PROJECTION_MAP.put(Passwords.ENC_TYPE, Passwords.ENC_TYPE);
         PASSWORDS_PROJECTION_MAP.put(Passwords.TIME_CREATED, Passwords.TIME_CREATED);
         PASSWORDS_PROJECTION_MAP.put(Passwords.TIME_LAST_USED, Passwords.TIME_LAST_USED);
         PASSWORDS_PROJECTION_MAP.put(Passwords.TIME_PASSWORD_CHANGED, Passwords.TIME_PASSWORD_CHANGED);
         PASSWORDS_PROJECTION_MAP.put(Passwords.TIMES_USED, Passwords.TIMES_USED);
 
-        URI_MATCHER.addURI(BrowserContract.PASSWORDS_AUTHORITY, "deleted-passwords", DELETED_PASSWORDS);
+        URI_MATCHER.addURI(BrowserContract.DELETED_PASSWORDS_AUTHORITY, "deleted-passwords", DELETED_PASSWORDS);
 
         DELETED_PASSWORDS_PROJECTION_MAP = new HashMap<String, String>();
         DELETED_PASSWORDS_PROJECTION_MAP.put(DeletedPasswords.ID, DeletedPasswords.ID);
         DELETED_PASSWORDS_PROJECTION_MAP.put(DeletedPasswords.GUID, DeletedPasswords.GUID);
         DELETED_PASSWORDS_PROJECTION_MAP.put(DeletedPasswords.TIME_DELETED, DeletedPasswords.TIME_DELETED);
-        System.loadLibrary("mozglue");
     }
 
     @Override
     public boolean onCreate() {
         setLogTag("GeckoPasswordsProvider");
         setDBName(DB_FILENAME);
         setDBVersion(DB_VERSION);
         return super.onCreate();
@@ -163,16 +163,19 @@ public class PasswordsProvider extends G
                 values.put(Passwords.TIME_CREATED, now);
 
                 // Generate GUID for new password. Don't override specified GUIDs.
                 if (!values.containsKey(Passwords.GUID)) {
                     String guid = Utils.generateGuid();
                     values.put(Passwords.GUID, guid);
                 }
                 String nowString = new Long(now).toString();
+                DBUtils.replaceKey(values, CommonColumns._ID, Passwords.ID, "");
+                DBUtils.replaceKey(values, SyncColumns.DATE_CREATED, Passwords.TIME_CREATED, nowString);
+                DBUtils.replaceKey(values, SyncColumns.DATE_MODIFIED, Passwords.TIME_PASSWORD_CHANGED, nowString);
                 DBUtils.replaceKey(values, null, Passwords.HOSTNAME, "");
                 DBUtils.replaceKey(values, null, Passwords.HTTP_REALM, "");
                 DBUtils.replaceKey(values, null, Passwords.FORM_SUBMIT_URL, "");
                 DBUtils.replaceKey(values, null, Passwords.USERNAME_FIELD, "");
                 DBUtils.replaceKey(values, null, Passwords.PASSWORD_FIELD, "");
                 DBUtils.replaceKey(values, null, Passwords.ENCRYPTED_USERNAME, "");
                 DBUtils.replaceKey(values, null, Passwords.ENCRYPTED_PASSWORD, "");
                 DBUtils.replaceKey(values, null, Passwords.ENC_TYPE, "0");
@@ -184,102 +187,10 @@ public class PasswordsProvider extends G
             default:
                 throw new UnsupportedOperationException("Unknown URI " + uri);
         }
     }
 
     @Override
     public void initGecko() {
         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Passwords:Init", null));
-        Intent initIntent = new Intent(GeckoApp.ACTION_INIT_PW);
-        mContext.sendBroadcast(initIntent);
-    }
-
-    private String doCrypto(String initialValue, Uri uri, Boolean encrypt) {
-        String profilePath = null;
-        if (uri != null) {
-            profilePath = uri.getQueryParameter(BrowserContract.PARAM_PROFILE_PATH);
-        }
-
-        String result = "";
-        if (encrypt) {
-          if (profilePath != null) result = NSSBridge.encrypt(mContext, profilePath, initialValue);
-          else result = NSSBridge.encrypt(mContext, initialValue);
-        } else {
-          if (profilePath != null) result = NSSBridge.decrypt(mContext, profilePath, initialValue);
-          else result = NSSBridge.decrypt(mContext, initialValue);            
-        }
-        return result;
-    }
-
-    @Override
-    public void onPreInsert(ContentValues values, Uri uri, SQLiteBridge db) {
-        if (values.containsKey(Passwords.GUID)) {
-            String guid = values.getAsString(Passwords.GUID);
-            String where = BrowserContract.DeletedPasswords.GUID + " = ?";
-            String[] args = new String[] { guid };
-            if (guid == null) {
-                where = BrowserContract.DeletedPasswords.GUID + " IS NULL";
-                args = null;
-            }
-    
-            try {
-                db.delete(TABLE_DELETED_PASSWORDS, where, args);
-            } catch(SQLiteBridgeException ex) {
-                Log.w(getLogTag(), "Error removing entry with GUID " + guid, ex);
-            }
-        }
-
-        if (values.containsKey(Passwords.ENCRYPTED_PASSWORD)) {
-            String res = doCrypto(values.getAsString(Passwords.ENCRYPTED_PASSWORD), uri, true);
-            values.put(Passwords.ENCRYPTED_PASSWORD, res);
-        }
-
-        if (values.containsKey(Passwords.ENCRYPTED_USERNAME)) {
-            String res = doCrypto(values.getAsString(Passwords.ENCRYPTED_USERNAME), uri, true);
-            values.put(Passwords.ENCRYPTED_USERNAME, res);
-        }
-    }
-
-    @Override
-    public void onPreUpdate(ContentValues values, Uri uri, SQLiteBridge db) {
-        if (values.containsKey(Passwords.ENCRYPTED_PASSWORD)) {
-            String res = doCrypto(values.getAsString(Passwords.ENCRYPTED_PASSWORD), uri, true);
-            values.put(Passwords.ENCRYPTED_PASSWORD, res);
-        }
-
-        if (values.containsKey(Passwords.ENCRYPTED_USERNAME)) {
-            String res = doCrypto(values.getAsString(Passwords.ENCRYPTED_USERNAME), uri, true);
-            values.put(Passwords.ENCRYPTED_USERNAME, res);
-        }
-    }
-
-    @Override
-    public void onPostQuery(Cursor cursor, Uri uri, SQLiteBridge db) {
-        int passwordIndex = -1;
-        int usernameIndex = -1;
-        String profilePath = null;
-
-        try {
-            passwordIndex = cursor.getColumnIndexOrThrow(Passwords.ENCRYPTED_PASSWORD);
-        } catch(Exception ex) { }
-        try {
-            usernameIndex = cursor.getColumnIndexOrThrow(Passwords.ENCRYPTED_USERNAME);
-        } catch(Exception ex) { }
-
-        if (passwordIndex > -1 || usernameIndex > -1) {
-            MatrixBlobCursor m = (MatrixBlobCursor)cursor;
-            if (cursor.moveToFirst()) {
-                do {
-                    if (passwordIndex > -1) {
-                        String decrypted = doCrypto(cursor.getString(passwordIndex), uri, false);;
-                        m.set(passwordIndex, decrypted);
-                    }
-
-                    if (usernameIndex > -1) {
-                        String decrypted = doCrypto(cursor.getString(usernameIndex), uri, false);
-                        m.set(usernameIndex, decrypted);
-                    }
-                } while(cursor.moveToNext());
-            }
-        }
     }
 }
--- a/mobile/android/base/sqlite/MatrixBlobCursor.java
+++ b/mobile/android/base/sqlite/MatrixBlobCursor.java
@@ -223,31 +223,18 @@ public class MatrixBlobCursor extends Ab
                         "No more columns left.");
             }
 
             data[index++] = columnValue;
             return this;
         }
     }
 
-    public void set(int column, Object value) {
-        if (column < 0 || column >= columnCount) {
-            throw new CursorIndexOutOfBoundsException("Requested column: "
-                    + column + ", # of columns: " +  columnCount);
-        }
-        if (mPos < 0) {
-            throw new CursorIndexOutOfBoundsException("Before first row.");
-        }
-        if (mPos >= rowCount) {
-            throw new CursorIndexOutOfBoundsException("After last row.");
-        }
-        data[mPos * columnCount + column] = value;
-    }
+    // AbstractCursor implementation.
 
-    // AbstractCursor implementation.
     @Override
     public int getCount() {
         return rowCount;
     }
 
     @Override
     public String[] getColumnNames() {
         return columnNames;
--- a/mobile/android/base/tests/BaseTest.java.in
+++ b/mobile/android/base/tests/BaseTest.java.in
@@ -1,39 +1,35 @@
 #filter substitution
 package @ANDROID_PACKAGE_NAME@.tests;
 
 import com.jayway.android.robotium.solo.Solo;
 import @ANDROID_PACKAGE_NAME@.*;
 
 import android.app.Activity;
 import android.app.Instrumentation;
-import android.database.Cursor;
-import android.content.ContentValues;
 import android.content.Intent;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
-import java.io.File;
 
 import java.util.HashMap;
 
 abstract class BaseTest extends ActivityInstrumentationTestCase2<Activity> {
     private static final String TARGET_PACKAGE_ID = "org.mozilla.gecko";
     private static final String LAUNCH_ACTIVITY_FULL_CLASSNAME="@ANDROID_PACKAGE_NAME@.App";
 
     private static Class<Activity> mLauncherActivityClass;
     private Activity mActivity;
     protected Solo mSolo;
     protected Driver mDriver;
     protected Assert mAsserter;
     protected Actions mActions;
     protected String mBaseUrl;
     private String mTestType;
     private String mLogFile;
-    protected String mProfile;
 
     static {
         try {
             mLauncherActivityClass = (Class<Activity>)Class.forName(LAUNCH_ACTIVITY_FULL_CLASSNAME);
         } catch (ClassNotFoundException e) {
             throw new RuntimeException(e);
         }
     }
@@ -45,18 +41,17 @@ abstract class BaseTest extends Activity
     @Override
     protected void setUp() throws Exception {
         // Load config file from sdcard (setup by python script)
         String configFile = FennecNativeDriver.getFile("/mnt/sdcard/robotium.config");
         HashMap config = FennecNativeDriver.convertTextToTable(configFile);
 
         // Create the intent to be used with all the important arguments.
         Intent i = new Intent(Intent.ACTION_MAIN);
-        mProfile = (String)config.get("profile");
-        i.putExtra("args", "-no-remote -profile " + mProfile);
+        i.putExtra("args", "-no-remote -profile " + (String)config.get("profile"));
 
         // Start the activity
         setActivityIntent(i);
         mActivity = getActivity();
 
         // Set up Robotium.solo and Driver objects
         mSolo = new Solo(getInstrumentation());
         mDriver = new FennecNativeDriver(mActivity, mSolo);
@@ -148,60 +143,9 @@ abstract class BaseTest extends Activity
             mSolo.sleep(100);
         }
         return false;
     }
 
     protected interface BooleanTest {
         public boolean test();
     }
-
-    @SuppressWarnings({"unchecked", "non-varargs"})
-    public void SqliteCompare(String dbName, String sqlCommand, ContentValues[] cvs) {
-        File profile = new File(mProfile);
-        String dbPath = new File(profile, dbName).getPath();
-
-        Cursor c = mActions.querySql(dbPath, sqlCommand);
-        SqliteCompare(c, cvs);
-    }
-
-    private boolean CursorMatches(Cursor c, String[] columns, ContentValues cv) {
-        for (int i = 0; i < columns.length; i++) {
-            String column = columns[i];
-            if (cv.containsKey(column)) {
-                mAsserter.info("Comparing", "Column value " + c.getString(i) + " ?= " + cv.get(column).toString());
-                if (!cv.get(column).toString().equals(c.getString(i))) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    @SuppressWarnings({"unchecked", "non-varargs"})
-    public void SqliteCompare(Cursor c, ContentValues[] cvs) {
-        mAsserter.is(c.getCount(), cvs.length, "List is correct length");
-        if (c.moveToFirst()) {
-            do {
-                boolean found = false;
-                for (int i = 0; !found && i < cvs.length; i++) {
-                    if (CursorMatches(c, cvs[i])) {
-                        found = true;
-                    }
-                }
-                mAsserter.is(found, true, "Password was found");
-            } while(c.moveToNext());
-        }
-    }
-
-    public boolean CursorMatches(Cursor c, ContentValues cv) {
-        for (int i = 0; i < c.getColumnCount(); i++) {
-            String column = c.getColumnName(i);
-             if (cv.containsKey(column)) {
-                mAsserter.info("Pass","Column value " + c.getString(i) + " ?= " + cv.get(column).toString());
-                if (!cv.get(column).toString().equals(c.getString(i))) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
 }
--- a/mobile/android/base/tests/robocop.ini
+++ b/mobile/android/base/tests/robocop.ini
@@ -5,14 +5,12 @@
 [testNewTab]
 [testPanCorrectness]
 [test_bug720538]
 # [testFlingCorrectness] # see bug 727351
 [testOverscroll]
 [testAxisLocking]
 [testAboutPage]
 [testWebContentContextMenu]
-[testPasswordProvider]
-[testFormHistory]
 
 # Used for Talos, please don't use in mochitest
 #[testPan]
 #[testCheck]
deleted file mode 100644
--- a/mobile/android/base/tests/testFormHistory.java.in
+++ /dev/null
@@ -1,91 +0,0 @@
-#filter substitution
-package @ANDROID_PACKAGE_NAME@.tests;
-
-import @ANDROID_PACKAGE_NAME@.*;
-import android.app.Activity;
-import android.content.ContentValues;
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.content.Context;
-import android.net.Uri;
-import java.io.File;
-import java.lang.ClassLoader;
-import java.util.ArrayList;
-
-/**
- * A basic form history contentprovider test.
- * - inserts an element in form history when it is not yet set up
- * - inserts an element in form history
- * - updates an element in form history
- * - deletes an element in form history
- */
-public class testFormHistory extends BaseTest {
-    private static final String DB_NAME = "formhistory.sqlite";
-    public void testFormHistory() {
-        setTestType("mochitest");
-        Context context = (Context)getActivity();
-        ContentResolver cr = context.getContentResolver();
-        ContentValues[] cvs = new ContentValues[1];
-        cvs[0] = new ContentValues();
-  
-        Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("Gecko:Ready");
-        contentEventExpecter.blockForEvent();
-  
-        Uri formHistoryUri;
-        try {
-            ClassLoader classLoader = getActivity().getClassLoader();
-            Class fh = classLoader.loadClass("org.mozilla.gecko.db.BrowserContract$FormHistory");
-      
-            cvs[0].put("fieldname", "fieldname");
-            cvs[0].put("value", "value");
-            cvs[0].put("timesUsed", "0");
-            cvs[0].put("guid", "guid");
-    
-            // Attempt to insert into the db
-            formHistoryUri = (Uri)fh.getField("CONTENT_URI").get(null);
-            Uri.Builder builder = formHistoryUri.buildUpon();
-            formHistoryUri = builder.appendQueryParameter("profilePath", mProfile).build();
-        } catch(ClassNotFoundException ex) {
-            mAsserter.is(false, true, "Error getting class");
-            return;
-        } catch(NoSuchFieldException ex) {
-            mAsserter.is(false, true, "Error getting field");
-            return;
-        } catch(IllegalAccessException ex) {
-            mAsserter.is(false, true, "Error using field");
-            return;
-        }
-  
-        // Trying to insert should fail the first time round because there is no form history database
-        // Wait for gecko to reply and then we'll try again
-        contentEventExpecter = mActions.expectGeckoEvent("FormHistory:Init:Return");
-        Uri uri = cr.insert(formHistoryUri, cvs[0]);
-        mAsserter.is(uri, null, "Insert returned null correctly");
-        contentEventExpecter.blockForEvent();
-  
-        uri = cr.insert(formHistoryUri, cvs[0]);
-        Uri expectedUri = formHistoryUri.buildUpon().appendPath("1").build();
-        mAsserter.is(expectedUri.toString(), uri.toString(), "Insert returned correct uri");
-        SqliteCompare(DB_NAME, "SELECT * FROM moz_formhistory", cvs);
-  
-        cvs[0].put("fieldname", "fieldname2");
-  
-        int numUpdated = cr.update(formHistoryUri, cvs[0], null, null);
-        mAsserter.is(1, numUpdated, "Correct number updated");
-        SqliteCompare(DB_NAME, "SELECT * FROM moz_formhistory", cvs);
-  
-        int numDeleted = cr.delete(formHistoryUri, null, null);
-        mAsserter.is(1, numDeleted, "Correct number deleted");
-        cvs = new ContentValues[0];
-        SqliteCompare(DB_NAME, "SELECT * FROM moz_formhistory", cvs);
-    }
-
-    public void tearDown() throws Exception {
-      super.tearDown();
-
-      // remove the entire signons.sqlite file
-      File profile = new File(mProfile);
-      File db = new File(profile, "formhistory.sqlite");
-      db.delete();
-    }
-}
deleted file mode 100644
--- a/mobile/android/base/tests/testPasswordProvider.java.in
+++ /dev/null
@@ -1,93 +0,0 @@
-#filter substitution
-package @ANDROID_PACKAGE_NAME@.tests;
-
-import @ANDROID_PACKAGE_NAME@.*;
-import android.app.Activity;
-import android.content.ContentValues;
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.content.Context;
-import android.net.Uri;
-import java.io.File;
-
-/**
- * A basic password contentprovider test.
- * - inserts a password when the database is not yet set up
- * - inserts a password
- * - updates a password
- * - deletes a password
- */
-public class testPasswordProvider extends BaseTest {
-    private static final String DB_NAME = "signons.sqlite";
-    public void testPasswordProvider() {
-        setTestType("mochitest");
-        Context context = (Context)getActivity();
-        ContentResolver cr = context.getContentResolver();
-        ContentValues[] cvs = new ContentValues[1];
-        cvs[0] = new ContentValues();
-  
-        Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("Gecko:Ready");
-        contentEventExpecter.blockForEvent();
-  
-        Uri passwordUri;
-        try {
-            ClassLoader classLoader = getActivity().getClassLoader();
-            Class pwds = classLoader.loadClass("org.mozilla.gecko.db.BrowserContract$Passwords");
-      
-            cvs[0].put("hostname", "http://www.example.com");
-            cvs[0].put("httpRealm", "http://www.example.com");
-            cvs[0].put("formSubmitURL", "http://www.example.com");
-            cvs[0].put("usernameField", "usernameField");
-            cvs[0].put("passwordField", "passwordField");
-            cvs[0].put("encryptedUsername", "username");
-            cvs[0].put("encryptedPassword", "password");
-            cvs[0].put("encType", "0");
-    
-            // Attempt to insert into the db
-            passwordUri = (Uri)pwds.getField("CONTENT_URI").get(null);
-            Uri.Builder builder = passwordUri.buildUpon();
-            passwordUri = builder.appendQueryParameter("profilePath", mProfile).build();
-        } catch(ClassNotFoundException ex) {
-            mAsserter.is(false, true, "Error getting class");
-            return;
-        } catch(NoSuchFieldException ex) {
-            mAsserter.is(false, true, "Error getting field");
-            return;
-        } catch(IllegalAccessException ex) {
-            mAsserter.is(false, true, "Error using field");
-            return;
-        }
-        // Trying to inset should fail the first time round because there is no pw database
-        // Wait for gecko to reply and then we'll try again
-        contentEventExpecter = mActions.expectGeckoEvent("Passwords:Init:Return");
-        Uri uri = cr.insert(passwordUri, cvs[0]);
-        mAsserter.is(uri, null, "Insert returned null correctly");
-        contentEventExpecter.blockForEvent();
-  
-        uri = cr.insert(passwordUri, cvs[0]);
-        SqliteCompare(DB_NAME, "SELECT * FROM moz_logins", cvs);
-        Uri expectedUri = passwordUri.buildUpon().appendPath("1").build();
-        mAsserter.is(expectedUri.toString(), uri.toString(), "Insert returned correct uri");
-  
-        cvs[0].put("usernameField", "usernameField2");
-        cvs[0].put("passwordField", "passwordField2");
-  
-        int numUpdated = cr.update(passwordUri, cvs[0], null, null);
-        mAsserter.is(1, numUpdated, "Correct number updated");
-        SqliteCompare(DB_NAME, "SELECT * FROM moz_logins", cvs);
-  
-        int numDeleted = cr.delete(passwordUri, null, null);
-        mAsserter.is(1, numDeleted, "Correct number deleted");
-        cvs = new ContentValues[0];
-        SqliteCompare(DB_NAME, "SELECT * FROM moz_logins", cvs);
-    }
-
-    public void tearDown() throws Exception {
-        super.tearDown();
-  
-        // remove the entire signons.sqlite file
-        File profile = new File(mProfile);
-        File db = new File(profile, "signons.sqlite");
-        db.delete();
-    }
-}
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -61,29 +61,26 @@
 #endif
 #include "dlfcn.h"
 #include "APKOpen.h"
 #include <sys/time.h>
 #include <sys/resource.h>
 #include "Zip.h"
 #include "sqlite3.h"
 #include "SQLiteBridge.h"
-#include "NSSBridge.h"
 #ifndef MOZ_OLD_LINKER
 #include "ElfLoader.h"
 #endif
 #include "application.ini.h"
 
 /* Android headers don't define RUSAGE_THREAD */
 #ifndef RUSAGE_THREAD
 #define RUSAGE_THREAD 1
 #endif
 
-typedef int mozglueresult;
-
 enum StartupEvent {
 #define mozilla_StartupTimeline_Event(ev, z) ev,
 #include "StartupTimeline.h"
 #undef mozilla_StartupTimeline_Event
 };
 
 using namespace mozilla;
 
@@ -97,33 +94,16 @@ void StartupTimeline_Record(StartupEvent
 static struct mapping_info * lib_mapping = NULL;
 
 NS_EXPORT const struct mapping_info *
 getLibraryMapping()
 {
   return lib_mapping;
 }
 
-void
-JNI_Throw(JNIEnv* jenv, const char* classname, const char* msg)
-{
-    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Throw\n");
-    jclass cls = jenv->FindClass(classname);
-    if (cls == NULL) {
-        __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't find exception class (or exception pending) %s\n", classname);
-        exit(FAILURE);
-    }
-    int rc = jenv->ThrowNew(cls, msg);
-    if (rc < 0) {
-        __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Error throwing exception %s\n", msg);
-        exit(FAILURE);
-    }
-    jenv->DeleteLocalRef(cls);
-}
-
 #ifdef MOZ_OLD_LINKER
 static int
 createAshmem(size_t bytes, const char *name)
 {
   int fd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600);
   if (fd < 0)
     return -1;
 
@@ -328,19 +308,89 @@ SHELL_WRAPPER3(notifySmsDeleted, jboolea
 SHELL_WRAPPER3(notifySmsDeleteFailed, jint, jint, jlong)
 SHELL_WRAPPER2(notifyNoMessageInList, jint, jlong)
 SHELL_WRAPPER8(notifyListCreated, jint, jint, jstring, jstring, jstring, jlong, jint, jlong)
 SHELL_WRAPPER7(notifyGotNextMessage, jint, jstring, jstring, jstring, jlong, jint, jlong)
 SHELL_WRAPPER3(notifyReadingMessageListFailed, jint, jint, jlong)
 
 static void * xul_handle = NULL;
 static void * sqlite_handle = NULL;
-static void * nss_handle = NULL;
-static void * nspr_handle = NULL;
-static void * plc_handle = NULL;
+#ifdef MOZ_OLD_LINKER
+static time_t apk_mtime = 0;
+#ifdef DEBUG
+extern "C" int extractLibs = 1;
+#else
+extern "C" int extractLibs = 0;
+#endif
+
+static void
+extractFile(const char * path, Zip::Stream &s)
+{
+  uint32_t size = s.GetUncompressedSize();
+
+  struct stat status;
+  if (!stat(path, &status) &&
+      status.st_size == size &&
+      apk_mtime < status.st_mtime)
+    return;
+
+  int fd = open(path, O_CREAT | O_NOATIME | O_TRUNC | O_RDWR, S_IRWXU);
+  if (fd == -1) {
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't open %s to decompress library", path);
+    return;
+  }
+
+  if (ftruncate(fd, size) == -1) {
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't ftruncate %s to decompress library", path);
+    close(fd);
+    return;
+  }
+
+  void * buf = mmap(NULL, size, PROT_READ | PROT_WRITE,
+                    MAP_SHARED, fd, 0);
+  if (buf == (void *)-1) {
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer");
+    close(fd);
+    return;
+  }
+
+  z_stream strm = {
+    next_in: (Bytef *)s.GetBuffer(),
+    avail_in: s.GetSize(),
+    total_in: 0,
+
+    next_out: (Bytef *)buf,
+    avail_out: size,
+    total_out: 0
+  };
+
+  int ret;
+  ret = inflateInit2(&strm, -MAX_WBITS);
+  if (ret != Z_OK)
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateInit failed: %s", strm.msg);
+
+  if (inflate(&strm, Z_FINISH) != Z_STREAM_END)
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflate failed: %s", strm.msg);
+
+  if (strm.total_out != size)
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "extracted %d, expected %d!", strm.total_out, size);
+
+  ret = inflateEnd(&strm);
+  if (ret != Z_OK)
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateEnd failed: %s", strm.msg);
+
+  close(fd);
+#ifdef ANDROID_ARM_LINKER
+  /* We just extracted data that is going to be executed in the future.
+   * We thus need to ensure Instruction and Data cache coherency. */
+  cacheflush((unsigned) buf, (unsigned) buf + size, 0);
+#endif
+  munmap(buf, size);
+}
+#endif
 
 #if defined(MOZ_CRASHREPORTER) || defined(MOZ_OLD_LINKER)
 static void
 extractLib(Zip::Stream &s, void * dest)
 {
   z_stream strm = {
     next_in: (Bytef *)s.GetBuffer(),
     avail_in: s.GetSize(),
@@ -455,16 +505,35 @@ static void * mozload(const char * path,
   gettimeofday(&t0, 0);
 #endif
 
   void *handle;
   Zip::Stream s;
   if (!zip->GetStream(path, &s))
     return NULL;
 
+  if (extractLibs) {
+    char fullpath[PATH_MAX];
+    snprintf(fullpath, PATH_MAX, "%s/%s", getenv("MOZ_LINKER_CACHE"), path);
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "resolved %s to %s", path, fullpath);
+    extractFile(fullpath, s);
+    handle = __wrap_dlopen(fullpath, RTLD_LAZY);
+    if (!handle)
+      __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", fullpath, __wrap_dlerror());
+#ifdef DEBUG
+    gettimeofday(&t1, 0);
+    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "%s: spent %d", path,
+                        (((long long)t1.tv_sec * 1000000LL) +
+                          (long long)t1.tv_usec) -
+                        (((long long)t0.tv_sec * 1000000LL) +
+                          (long long)t0.tv_usec));
+#endif
+    return handle;
+  }
+
   bool skipLibCache = false;
   int fd;
   void * buf = NULL;
   uint32_t lib_size = s.GetUncompressedSize();
   int cache_fd = 0;
   if (s.GetType() == Zip::Stream::DEFLATE) {
     cache_fd = lookupLibCacheFd(path);
     fd = cache_fd;
@@ -567,21 +636,27 @@ report_mapping(char *name, void *base, u
   if (entry)
     info->file_id = strndup(entry + strlen(name) + 1, 32);
 }
 
 #ifdef MOZ_OLD_LINKER
 extern "C" void simple_linker_init(void);
 #endif
 
-static mozglueresult
+static void
 loadGeckoLibs(const char *apkName)
 {
   chdir(getenv("GRE_HOME"));
 
+#ifdef MOZ_OLD_LINKER
+  struct stat status;
+  if (!stat(apkName, &status))
+    apk_mtime = status.st_mtime;
+#endif
+
   struct timeval t0, t1;
   gettimeofday(&t0, 0);
   struct rusage usage1;
   getrusage(RUSAGE_THREAD, &usage1);
   
   RefPtr<Zip> zip = new Zip(apkName);
 
 #ifdef MOZ_CRASHREPORTER
@@ -592,38 +667,39 @@ loadGeckoLibs(const char *apkName)
   char *file = new char[strlen(apkName) + sizeof("!/libxpcom.so")];
   sprintf(file, "%s!/libxpcom.so", apkName);
   __wrap_dlopen(file, RTLD_GLOBAL | RTLD_LAZY);
   // libxul.so is pulled from libxpcom.so, so we don't need to give the full path
   xul_handle = __wrap_dlopen("libxul.so", RTLD_GLOBAL | RTLD_LAZY);
   delete[] file;
 #else
 #define MOZLOAD(name) mozload("lib" name ".so", zip)
-  if (!MOZLOAD("mozalloc")) return FAILURE;
-  if (!MOZLOAD("plds4")) return FAILURE;
-  if (!MOZLOAD("nssutil3")) return FAILURE;
-  if (!MOZLOAD("ssl3")) return FAILURE;
-  if (!MOZLOAD("smime3")) return FAILURE;
+  MOZLOAD("mozalloc");
+  MOZLOAD("nspr4");
+  MOZLOAD("plc4");
+  MOZLOAD("plds4");
+  MOZLOAD("nssutil3");
+  MOZLOAD("nss3");
+  MOZLOAD("ssl3");
+  MOZLOAD("smime3");
   xul_handle = MOZLOAD("xul");
-  if (!MOZLOAD("xpcom")) return FAILURE;
-  if (!MOZLOAD("nssckbi")) return FAILURE;
-  if (!MOZLOAD("freebl3")) return FAILURE;
-  if (!MOZLOAD("softokn3")) return FAILURE;
+  MOZLOAD("xpcom");
+  MOZLOAD("nssckbi");
+  MOZLOAD("freebl3");
+  MOZLOAD("softokn3");
 #undef MOZLOAD
 #endif
 
 #ifdef MOZ_CRASHREPORTER
   free(file_ids);
   file_ids = NULL;
 #endif
 
-  if (!xul_handle) {
+  if (!xul_handle)
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libxul!");
-    return FAILURE;
-  }
 
 #define GETFUNC(name) f_ ## name = (name ## _t) __wrap_dlsym(xul_handle, "Java_org_mozilla_gecko_GeckoAppShell_" #name)
   GETFUNC(nativeInit);
   GETFUNC(notifyGeckoOfEvent);
   GETFUNC(processNextNativeEvent);
   GETFUNC(setSurfaceView);
   GETFUNC(setSoftwareLayerClient);
   GETFUNC(onResume);
@@ -657,25 +733,28 @@ loadGeckoLibs(const char *apkName)
   __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loaded libs in %ldms total, %ldms user, %ldms system, %ld faults",
                       (t1.tv_sec - t0.tv_sec)*1000 + (t1.tv_usec - t0.tv_usec)/1000, 
                       (usage2.ru_utime.tv_sec - usage1.ru_utime.tv_sec)*1000 + (usage2.ru_utime.tv_usec - usage1.ru_utime.tv_usec)/1000,
                       (usage2.ru_stime.tv_sec - usage1.ru_stime.tv_sec)*1000 + (usage2.ru_stime.tv_usec - usage1.ru_stime.tv_usec)/1000,
                       usage2.ru_majflt-usage1.ru_majflt);
 
   StartupTimeline_Record(LINKER_INITIALIZED, &t0);
   StartupTimeline_Record(LIBRARIES_LOADED, &t1);
-  return SUCCESS;
 }
 
-static int loadSQLiteLibs(const char *apkName)
+static void loadSQLiteLibs(const char *apkName)
 {
   chdir(getenv("GRE_HOME"));
 
 #ifdef MOZ_OLD_LINKER
   simple_linker_init();
+
+  struct stat status;
+  if (!stat(apkName, &status))
+    apk_mtime = status.st_mtime;
 #endif
 
   RefPtr<Zip> zip = new Zip(apkName);
   lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping));
 
 #ifdef MOZ_CRASHREPORTER
   file_ids = (char *)extractBuf("lib.id", zip);
 #endif
@@ -691,143 +770,54 @@ static int loadSQLiteLibs(const char *ap
 #undef MOZLOAD
 #endif
 
 #ifdef MOZ_CRASHREPORTER
   free(file_ids);
   file_ids = NULL;
 #endif
 
-  if (!sqlite_handle) {
+  if (!sqlite_handle)
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libmozsqlite3!");
-    return FAILURE;
-  }
 
   setup_sqlite_functions(sqlite_handle);
-  return SUCCESS;
-}
-
-static mozglueresult
-loadNSSLibs(const char *apkName)
-{
-  __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "loadNSSLibs");
-  chdir(getenv("GRE_HOME"));
-
-#ifdef MOZ_OLD_LINKER
-  simple_linker_init();
-#endif
-
-  Zip *zip = new Zip(apkName);
-  lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping));
-
-#ifdef MOZ_CRASHREPORTER
-  file_ids = (char *)extractBuf("lib.id", zip);
-#endif
-
-#ifndef MOZ_OLD_LINKER
-  char *file = new char[strlen(apkName) + sizeof("!/libnss3.so")];
-  sprintf(file, "%s!/libnss3.so", apkName);
-  nss_handle = __wrap_dlopen(file, RTLD_GLOBAL | RTLD_LAZY);
-  delete [] file;
-
-  file = new char[strlen(apkName) + sizeof("!/libnspr4.so")];
-  sprintf(file, "%s!/libnspr4.so", apkName);
-  nspr_handle = __wrap_dlopen(file, RTLD_GLOBAL | RTLD_LAZY);
-  delete [] file;
-
-  file = new char[strlen(apkName) + sizeof("!/libplc4.so")];
-  sprintf(file, "%s!/libplc4.so", apkName);
-  plc_handle = __wrap_dlopen(file, RTLD_GLOBAL | RTLD_LAZY);
-  delete [] file;
-#else
-#define MOZLOAD(name) mozload("lib" name ".so", zip)
-  nss_handle  = MOZLOAD("libnss3");
-  nspr_handle = MOZLOAD("libnspr4");
-  plc_handle  = MOZLOAD("libplc4");
-#undef MOZLOAD
-#endif
-
-  delete zip;
-
-#ifdef MOZ_CRASHREPORTER
-  free(file_ids);
-  file_ids = NULL;
-#endif
-
-  __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "loadNSSLibs 2");
-  if (!nss_handle) {
-    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libnss3!");
-    return FAILURE;
-  }
-
-  if (!nspr_handle) {
-    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libnspr4!");
-    return FAILURE;
-  }
-
-  if (!plc_handle) {
-    __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libplc4!");
-    return FAILURE;
-  }
-
-  __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "loadNSSLibs 3");
-  return setup_nss_functions(nss_handle, nspr_handle, plc_handle);
 }
 
 extern "C" NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_loadGeckoLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName)
 {
   const char* str;
   // XXX: java doesn't give us true UTF8, we should figure out something
   // better to do here
   str = jenv->GetStringUTFChars(jApkName, NULL);
   if (str == NULL)
     return;
 
-  int res = loadGeckoLibs(str);
-  if (res != SUCCESS) {
-    JNI_Throw(jenv, "java/lang/Exception", "Error loading gecko libraries");
-  }
+  loadGeckoLibs(str);
   jenv->ReleaseStringUTFChars(jApkName, str);
 }
 
 extern "C" NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_loadSQLiteLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName, jboolean jShouldExtract) {
-  putenv("MOZ_LINKER_EXTRACT=1");
+  if (jShouldExtract) {
+#ifdef MOZ_OLD_LINKER
+    extractLibs = 1;
+#else
+    putenv("MOZ_LINKER_EXTRACT=1");
+#endif
+  }
+
   const char* str;
   // XXX: java doesn't give us true UTF8, we should figure out something
   // better to do here
   str = jenv->GetStringUTFChars(jApkName, NULL);
   if (str == NULL)
     return;
 
-  __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load sqlite start\n");
-  mozglueresult rv = loadSQLiteLibs(str);
-  if (rv != SUCCESS) {
-      JNI_Throw(jenv, "java/lang/Exception", "Error loading sqlite libraries");
-  }
-  __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load sqlite done\n");
-  jenv->ReleaseStringUTFChars(jApkName, str);
-}
-
-extern "C" NS_EXPORT void JNICALL
-Java_org_mozilla_gecko_GeckoAppShell_loadNSSLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName) {
-  const char* str;
-  // XXX: java doesn't give us true UTF8, we should figure out something
-  // better to do here
-  str = jenv->GetStringUTFChars(jApkName, NULL);
-  if (str == NULL)
-    return;
-
-  __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load nss start\n");
-  mozglueresult rv = loadNSSLibs(str);
-  if (rv != SUCCESS) {
-    JNI_Throw(jenv, "java/lang/Exception", "Error loading nss libraries");
-  }
-  __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load nss done\n");
+  loadSQLiteLibs(str);
   jenv->ReleaseStringUTFChars(jApkName, str);
 }
 
 typedef void (*GeckoStart_t)(void *, const nsXREAppData *);
 
 extern "C" NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_nativeRun(JNIEnv *jenv, jclass jc, jstring jargs)
 {
@@ -841,49 +831,47 @@ Java_org_mozilla_gecko_GeckoAppShell_nat
   char *args = (char *) malloc(len + 1);
   jenv->GetStringUTFRegion(jargs, 0, len, args);
   args[len] = '\0';
   GeckoStart(args, &sAppData);
   free(args);
 }
 
 typedef int GeckoProcessType;
+typedef int nsresult;
 
-extern "C" NS_EXPORT mozglueresult
+extern "C" NS_EXPORT int
 ChildProcessInit(int argc, char* argv[])
 {
   int i;
   for (i = 0; i < (argc - 1); i++) {
     if (strcmp(argv[i], "-greomni"))
       continue;
 
     i = i + 1;
     break;
   }
 
 #ifdef MOZ_OLD_LINKER
   fillLibCache(argv[argc - 1]);
 #endif
-  if (loadNSSLibs(argv[i]) != SUCCESS) {
-    return FAILURE;
-  }
-  if (loadSQLiteLibs(argv[i]) != SUCCESS) {
-    return FAILURE;
-  }
-  if (loadGeckoLibs(argv[i]) != SUCCESS) {
-    return FAILURE;
-  }
+  loadSQLiteLibs(argv[i]);
+  loadGeckoLibs(argv[i]);
 
   // don't pass the last arg - it's only recognized by the lib cache
   argc--;
 
   typedef GeckoProcessType (*XRE_StringToChildProcessType_t)(char*);
-  typedef mozglueresult (*XRE_InitChildProcess_t)(int, char**, GeckoProcessType);
+  typedef nsresult (*XRE_InitChildProcess_t)(int, char**, GeckoProcessType);
   XRE_StringToChildProcessType_t fXRE_StringToChildProcessType =
     (XRE_StringToChildProcessType_t)__wrap_dlsym(xul_handle, "XRE_StringToChildProcessType");
   XRE_InitChildProcess_t fXRE_InitChildProcess =
     (XRE_InitChildProcess_t)__wrap_dlsym(xul_handle, "XRE_InitChildProcess");
 
   GeckoProcessType proctype = fXRE_StringToChildProcessType(argv[--argc]);
 
-  return fXRE_InitChildProcess(argc, argv, proctype);
+  nsresult rv = fXRE_InitChildProcess(argc, argv, proctype);
+  if (rv != 0)
+    return 1;
+
+  return 0;
 }
 
--- a/mozglue/android/APKOpen.h
+++ b/mozglue/android/APKOpen.h
@@ -32,42 +32,35 @@
  * 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 ***** */
 
 #ifndef APKOpen_h
 #define APKOpen_h
 
-#include <jni.h>
-
 #ifndef NS_EXPORT
 #define NS_EXPORT __attribute__ ((visibility("default")))
 #endif
 
 struct mapping_info {
   char * name;
   char * file_id;
   uintptr_t base;
   size_t len;
   size_t offset;
 };
 
 const struct mapping_info * getLibraryMapping();
 
-static const int SUCCESS = 0;
-static const int FAILURE = 1;
-void JNI_Throw(JNIEnv* jenv, const char* classname, const char* msg);
-
 #define MAX_LIB_CACHE_ENTRIES 32
 #define MAX_LIB_CACHE_NAME_LEN 32
 
 struct lib_cache_info {
   char name[MAX_LIB_CACHE_NAME_LEN];
   int fd;
   uint32_t lib_size;
   void* buffer;
 };
 
 NS_EXPORT const struct lib_cache_info * getLibraryCache();
 
-
 #endif /* APKOpen_h */
--- a/mozglue/android/Makefile.in
+++ b/mozglue/android/Makefile.in
@@ -50,47 +50,24 @@ STL_FLAGS=
 DEFINES += \
   -DANDROID_PACKAGE_NAME='"$(ANDROID_PACKAGE_NAME)"' \
   $(NULL)
 
 CPPSRCS = \
   nsGeckoUtils.cpp \
   APKOpen.cpp \
   SQLiteBridge.cpp \
-	NSSBridge.cpp \
   $(NULL)
 
 LOCAL_INCLUDES += -I$(DEPTH)/build
 LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
 
 LOCAL_INCLUDES += -I$(srcdir)/../linker
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/startup
 LOCAL_INCLUDES += -I$(topsrcdir)/db/sqlite3/src
-LOCAL_INCLUDES += -I$(topsrcdir)/base/src
-LOCAL_INCLUDES += -I$(topsrcdir)/nsprpub/lib/ds
-LOCAL_INCLUDES += -I$(topsrcdir)/nsprpub/lib/libc/include
-LOCAL_INCLUDES += -I$(topsrcdir)/nsprpub/pr/include
-LOCAL_INCLUDES += -I$(topsrcdir)/ipc/chromium/src/base/third_party/nspr
-LOCAL_INCLUDES += -I$(topsrcdir)/ipc/chromium/src
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/nss
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/util
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/softoken
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/pk11wrap
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/cmd/ecperf
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/pkcs7
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/certdb
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/cryptohi
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/dev
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/base
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/pki
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/smime
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/freebl/
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/lib/ssl
-LOCAL_INCLUDES += -I$(topsrcdir)/security/nss/cmd/lib/
-
 ifdef MOZ_OLD_LINKER
 DEFINES += -DMOZ_OLD_LINKER
 LOCAL_INCLUDES += -I$(topsrcdir)/other-licenses/android
 ifeq ($(CPU_ARCH),arm)
 DEFINES += -DANDROID_ARM_LINKER
 endif
 endif
 
deleted file mode 100644
--- a/mozglue/android/NSSBridge.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-/* 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/. */
-
-#include <stdlib.h>
-#include "dlfcn.h"
-#include "NSSBridge.h"
-#include "APKOpen.h"
-#ifdef ANDROID
-#include <jni.h>
-#include <android/log.h>
-#endif
-
-#ifndef MOZ_OLD_LINKER
-#include "ElfLoader.h"
-#endif
-
-#define DEBUG 1
-
-#ifdef DEBUG
-#define LOG(x...) __android_log_print(ANDROID_LOG_INFO, "GeckoJNI", x)
-#else
-#define LOG(x...) printf(x);
-#endif
-
-static bool initialized = false;
-
-#define NSS_WRAPPER_INT(name) name ## _t f_ ## name;
-NSS_WRAPPER_INT(NSS_Initialize)
-NSS_WRAPPER_INT(NSS_Shutdown)
-NSS_WRAPPER_INT(SECITEM_ZfreeItem)
-NSS_WRAPPER_INT(PK11SDR_Encrypt)
-NSS_WRAPPER_INT(PK11SDR_Decrypt)
-NSS_WRAPPER_INT(PK11_GetInternalKeySlot)
-NSS_WRAPPER_INT(PK11_NeedUserInit)
-NSS_WRAPPER_INT(PK11_InitPin)
-NSS_WRAPPER_INT(PR_ErrorToString)
-NSS_WRAPPER_INT(PR_GetError)
-NSS_WRAPPER_INT(PR_Free)
-NSS_WRAPPER_INT(PL_Base64Encode)
-NSS_WRAPPER_INT(PL_Base64Decode)
-NSS_WRAPPER_INT(PL_strfree)
-
-int
-setup_nss_functions(void *nss_handle,
-                        void *nspr_handle,
-                        void *plc_handle)
-{
-  __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "setup nss 1");
-  if (nss_handle == NULL || nspr_handle == NULL || plc_handle == NULL) {
-    LOG("missing handle\n");
-    return FAILURE;
-  }
-#define GETFUNC(name) f_ ## name = (name ## _t) __wrap_dlsym(nss_handle, #name); \
-                      if (!f_ ##name) return FAILURE;
-  GETFUNC(NSS_Initialize);
-  GETFUNC(NSS_Shutdown);
-  GETFUNC(PK11SDR_Encrypt);
-  GETFUNC(PK11SDR_Decrypt);
-  GETFUNC(PK11_GetInternalKeySlot);
-  GETFUNC(PK11_NeedUserInit);
-  GETFUNC(PK11_InitPin);
-  GETFUNC(SECITEM_ZfreeItem);
-#undef GETFUNC
-#define NSPRFUNC(name) f_ ## name = (name ## _t) __wrap_dlsym(nspr_handle, #name); \
-                       if (!f_ ##name) return FAILURE;
-  NSPRFUNC(PR_ErrorToString);
-  NSPRFUNC(PR_GetError);
-  NSPRFUNC(PR_Free);
-#undef NSPRFUNC
-#define PLCFUNC(name) f_ ## name = (name ## _t) __wrap_dlsym(plc_handle, #name); \
-                      if (!f_ ##name) return FAILURE;
-  PLCFUNC(PL_Base64Encode);
-  PLCFUNC(PL_Base64Decode);
-  PLCFUNC(PL_strfree);
-#undef PLCFUNC
-
-  return SUCCESS;
-}
-
-/* Throws the current NSS error. */
-static void
-throwError(JNIEnv* jenv, const char * funcString) {
-    char *msg;
-
-    PRErrorCode perr = f_PR_GetError();
-    char * errString = f_PR_ErrorToString(perr, 0);
-    asprintf(&msg, "%s returned error %d: %s\n", funcString, perr, errString);
-    LOG("Throwing error: %s\n", msg);
-
-    JNI_Throw(jenv, "java/lang/Exception", msg);
-    free(msg);
-    LOG("Error thrown\n");
-}
-
-extern "C" NS_EXPORT jstring JNICALL
-Java_org_mozilla_gecko_NSSBridge_nativeEncrypt(JNIEnv* jenv, jclass,
-                                               jstring jPath,
-                                               jstring jValue)
-{
-    jstring ret = jenv->NewStringUTF("");
-
-    const char* path;
-    path = jenv->GetStringUTFChars(jPath, NULL);
-
-    const char* value;
-    value = jenv->GetStringUTFChars(jValue, NULL);
-
-    char* result;
-    SECStatus rv = doCrypto(jenv, path, value, &result, true);
-    if (rv == SECSuccess) {
-      ret = jenv->NewStringUTF(result);
-      free(result);
-    }
-
-    jenv->ReleaseStringUTFChars(jValue, value);
-    jenv->ReleaseStringUTFChars(jPath, path);
-
-    return ret;
-}
-
-extern "C" NS_EXPORT jstring JNICALL
-Java_org_mozilla_gecko_NSSBridge_nativeDecrypt(JNIEnv* jenv, jclass,
-                                               jstring jPath,
-                                               jstring jValue)
-{
-    jstring ret = jenv->NewStringUTF("");
-
-    const char* path;
-    path = jenv->GetStringUTFChars(jPath, NULL);
-
-    const char* value;
-    value = jenv->GetStringUTFChars(jValue, NULL);
-
-    char* result;
-    SECStatus rv = doCrypto(jenv, path, value, &result, false);
-    if (rv == SECSuccess) {
-      ret = jenv->NewStringUTF(result);
-      free(result);
-    }
-
-    jenv->ReleaseStringUTFChars(jValue, value);
-    jenv->ReleaseStringUTFChars(jPath, path);
-
-    return ret;
-}
-
-
-/* Encrypts or decrypts a string. result should be freed with free() when done */
-SECStatus
-doCrypto(JNIEnv* jenv, const char *path, const char *value, char** result, bool encrypt)
-{
-    SECStatus rv;
-    PK11SlotInfo *slot;
-    if (!initialized) {
-      LOG("initialize crypto %s\n", path);
-      rv = f_NSS_Initialize(path, "", "", "secmod.db", NSS_INIT_NOROOTINIT);
-      if (rv != SECSuccess) {
-          throwError(jenv, "NSS_Initialize");
-          return rv;
-      }
-      initialized = true;
-    }
-
-    slot = f_PK11_GetInternalKeySlot();
-    if (!slot) {
-      throwError(jenv, "PK11_GetInternalKeySlot");
-      return SECFailure;
-    }
-
-    if (f_PK11_NeedUserInit(slot)) {
-      LOG("Initializing key3.db with default blank password.");
-      rv = f_PK11_InitPin(slot, NULL, NULL);
-      if (rv != SECSuccess) {
-        throwError(jenv, "PK11_InitPin");
-        return rv;
-      }
-    }
-
-    SECItem request;
-    SECItem reply;
-
-    reply.data = 0;
-    reply.len = 0;
-
-    if (encrypt) {
-      LOG("encrypting %s\n", value);
-      request.data = (unsigned char*)value;
-      request.len = strlen(value);
-
-      SECItem keyid;
-      keyid.data = 0;
-      keyid.len = 0;
-      rv = f_PK11SDR_Encrypt(&keyid, &request, &reply, NULL);
-
-      if (rv != SECSuccess) {
-        throwError(jenv, "PK11SDR_Encrypt");
-        goto done;
-      }
-
-      rv = encode(reply.data, reply.len, result);
-      if (rv != SECSuccess) {
-          throwError(jenv, "encode");
-          goto done;
-      }
-      LOG("encrypted %s\n", *result);
-    } else {
-      LOG("decoding %s\n", value);
-      rv = decode(value, &request.data, (PRInt32*)&request.len);
-      if (rv != SECSuccess) {
-          throwError(jenv, "decode");
-          return rv;
-      }
-
-      rv = f_PK11SDR_Decrypt(&request, &reply, NULL);
-      if (rv != SECSuccess) {
-        throwError(jenv, "PK11SDR_Decrypt");
-        goto done;
-      }
-
-      *result = (char *)malloc(reply.len);
-      (*result)[reply.len] = '\0';
-      strncpy(*result, (char *)reply.data, reply.len);
-      //asprintf(result, "%s", (char *)reply.data);
-
-      LOG("decoded %i letters %s\n", reply.len, *result);
-      free(request.data);
-    }
-
-done:
-    f_SECITEM_ZfreeItem(&reply, false);
-    return rv;
-}
-
-/*
- * Base64 encodes the data passed in. The caller must deallocate _retval using free();
- */
-SECStatus
-encode(const unsigned char *data, PRInt32 dataLen, char **_retval)
-{
-  SECStatus rv = SECSuccess;
-  char *encoded = f_PL_Base64Encode((const char *)data, dataLen, NULL);
-  if (!encoded)
-    rv = SECFailure;
-  if (!*encoded)
-    rv = SECFailure;
-
-  if (rv == SECSuccess) {
-    *_retval = (char *)malloc(strlen(encoded));
-    strcpy(*_retval, encoded);
-  }
-
-  if (encoded) {
-    f_PR_Free(encoded);
-  }
-
-  return rv;
-}
-
-/*
- * Base64 decodes the data passed in. The caller must deallocate result using free();
- */
-SECStatus
-decode(const char *data, unsigned char **result, PRInt32 *length)
-{
-  SECStatus rv = SECSuccess;
-  PRUint32 len = strlen(data);
-  int adjust = 0;
-
-  /* Compute length adjustment */
-  if (len > 0 && data[len-1] == '=') {
-    adjust++;
-    if (data[len-2] == '=') adjust++;
-  }
-
-  char *decoded;
-  decoded = f_PL_Base64Decode(data, len, NULL);
-  if (!decoded) {
-    return SECFailure;
-  }
-
-  LOG("xxx Decoded: %s\n", decoded);
-
-  if (!*decoded) {
-    return SECFailure;
-  }
-
-  *length = (len*3)/4 - adjust;
-  *result = (unsigned char*)malloc((size_t)len);
-
-  if (!*result) {
-    rv = SECFailure;
-  } else {
-    memcpy((char*)*result, decoded, len);
-  }
-  f_PR_Free(decoded);
-  return rv;
-}
-
-
deleted file mode 100644
--- a/mozglue/android/NSSBridge.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef NSSBridge_h
-#define NSSBridge_h
-
-#include "nss.h"
-#include "seccomon.h"
-#include "secmodt.h"
-#include "secutil.h"
-#include "pk11func.h"
-#include <jni.h>
-
-int setup_nss_functions(void *nss_handle, void *nssutil_handle, void *plc_handle);
-
-#define NSS_WRAPPER(name, return_type, args...) \
-typedef return_type (*name ## _t)(args);  \
-extern name ## _t f_ ## name;
-
-NSS_WRAPPER(NSS_Initialize, SECStatus, const char*, const char*, const char*, const char*, PRUint32)
-NSS_WRAPPER(NSS_Shutdown, void, void)
-NSS_WRAPPER(PK11SDR_Encrypt, SECStatus, SECItem *, SECItem *, SECItem *, void *)
-NSS_WRAPPER(PK11SDR_Decrypt, SECStatus, SECItem *, SECItem *, void *)
-NSS_WRAPPER(SECITEM_ZfreeItem, void, SECItem*, PRBool)
-NSS_WRAPPER(PR_ErrorToString, char *, PRErrorCode, PRLanguageCode)
-NSS_WRAPPER(PR_GetError, PRErrorCode, void)
-NSS_WRAPPER(PR_Free, PRErrorCode, char *)
-NSS_WRAPPER(PL_Base64Encode, char*, const char*, PRUint32, char*)
-NSS_WRAPPER(PL_Base64Decode, char*, const char*, PRUint32, char*)
-NSS_WRAPPER(PL_strfree, void, char*)
-NSS_WRAPPER(PK11_GetInternalKeySlot, PK11SlotInfo *, void)
-NSS_WRAPPER(PK11_NeedUserInit, PRBool, PK11SlotInfo *)
-NSS_WRAPPER(PK11_InitPin, SECStatus, PK11SlotInfo*, const char*, const char*)
-
-bool setPassword(PK11SlotInfo *slot);
-SECStatus doCrypto(JNIEnv* jenv, const char *path, const char *value, char** result, bool doEncrypt);
-SECStatus encode(const unsigned char *data, PRInt32 dataLen, char **_retval);
-SECStatus decode(const char *data, unsigned char **result, PRInt32 * _retval);
-#endif /* NSS_h */
--- a/mozglue/android/SQLiteBridge.cpp
+++ b/mozglue/android/SQLiteBridge.cpp
@@ -97,16 +97,31 @@ static jclass stringClass;
 static jclass objectClass;
 static jclass byteBufferClass;
 static jclass cursorClass;
 static jmethodID jByteBufferAllocateDirect;
 static jmethodID jCursorConstructor;
 static jmethodID jCursorAddRow;
 
 static void
+JNI_Throw(JNIEnv* jenv, const char* name, const char* msg)
+{
+    jclass cls = jenv->FindClass(name);
+    if (cls == NULL) {
+        LOG("Couldn't find exception class (or exception pending)\n");
+        return;
+    }
+    int rc = jenv->ThrowNew(cls, msg);
+    if (rc < 0) {
+        LOG("Error throwing exception\n");
+    }
+    jenv->DeleteLocalRef(cls);
+}
+
+static void
 JNI_Setup(JNIEnv* jenv)
 {
     if (initialized) return;
 
     jclass lObjectClass       = jenv->FindClass("java/lang/Object");
     jclass lStringClass       = jenv->FindClass("java/lang/String");
     jclass lByteBufferClass   = jenv->FindClass("java/nio/ByteBuffer");
     jclass lCursorClass       = jenv->FindClass("org/mozilla/gecko/sqlite/MatrixBlobCursor");
--- a/other-licenses/android/dlfcn.c
+++ b/other-licenses/android/dlfcn.c
@@ -38,26 +38,30 @@ static const char *dl_errors[] = {
     [DL_ERR_SYMBOL_NOT_FOUND] = "Symbol not found",
     [DL_ERR_SYMBOL_NOT_GLOBAL] = "Symbol is not global",
 };
 
 #define likely(expr)   __builtin_expect (expr, 1)
 #define unlikely(expr) __builtin_expect (expr, 0)
 
 static pthread_mutex_t dl_lock = PTHREAD_MUTEX_INITIALIZER;
+extern int extractLibs;
 
 static void set_dlerror(int err)
 {
     format_buffer(dl_err_buf, sizeof(dl_err_buf), "%s: %s", dl_errors[err],
              linker_get_error());
     dl_err_str = (const char *)&dl_err_buf[0];
 }
 
 void *__wrap_dlopen(const char *filename, int flag)
 {
+    if (extractLibs)
+        return dlopen(filename, flag);
+
     soinfo *ret;
 
     pthread_mutex_lock(&dl_lock);
     ret = find_library(filename);
     if (unlikely(ret == NULL)) {
         set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY);
     } else {
         ret->refcount++;
@@ -79,23 +83,29 @@ void *moz_mapped_dlopen(const char *file
         ret->refcount++;
     }
     pthread_mutex_unlock(&dl_lock);
     return ret;
 }
 
 const char *__wrap_dlerror(void)
 {
+    if (extractLibs)
+        return dlerror();
+
     const char *tmp = dl_err_str;
     dl_err_str = NULL;
     return (const char *)tmp;
 }
 
 void *__wrap_dlsym(void *handle, const char *symbol)
 {
+    if (extractLibs)
+        return dlsym(handle, symbol);
+
     soinfo *found;
     Elf32_Sym *sym;
     unsigned bind;
 
     pthread_mutex_lock(&dl_lock);
 
     if(unlikely(handle == 0)) { 
         set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE);
@@ -168,16 +178,19 @@ int __wrap_dladdr(void *addr, Dl_info *i
 
     pthread_mutex_unlock(&dl_lock);
 
     return ret;
 }
 
 int __wrap_dlclose(void *handle)
 {
+    if (extractLibs)
+        return dlclose(handle);
+
     pthread_mutex_lock(&dl_lock);
     (void)unload_library((soinfo*)handle);
     pthread_mutex_unlock(&dl_lock);
     return 0;
 }
 
 #if defined(ANDROID_ARM_LINKER)
 //                     0000000 00011111 111112 22222222 2333333 333344444444445555555