Bug 990130 - Fall back to full path of library on failure. r=mfinkle
authorRichard Newman <rnewman@mozilla.com>
Wed, 16 Apr 2014 10:57:59 -0700
changeset 179333 be14df51e362a840d94fc7826edcfc4639dc300d
parent 179332 5cf9041418fa3033411ef2d3fcc84efe030c1c32
child 179334 59f4f732f6d7969faff8894cbb97949f38d76aab
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersmfinkle
bugs990130
milestone31.0a1
Bug 990130 - Fall back to full path of library on failure. r=mfinkle
mobile/android/base/background/nativecode/NativeCrypto.java
mobile/android/base/db/PasswordsProvider.java
mobile/android/base/mozglue/GeckoLoader.java.in
--- a/mobile/android/base/background/nativecode/NativeCrypto.java
+++ b/mobile/android/base/background/nativecode/NativeCrypto.java
@@ -1,22 +1,40 @@
 /* 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.background.nativecode;
 
+import java.security.GeneralSecurityException;
+
+import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.mozglue.RobocopTarget;
 
-import java.security.GeneralSecurityException;
+import android.util.Log;
 
 @RobocopTarget
 public class NativeCrypto {
   static {
-    System.loadLibrary("mozglue");
+    try {
+      System.loadLibrary("mozglue");
+    } catch (UnsatisfiedLinkError e) {
+      Log.wtf("NativeCrypto", "Couldn't load mozglue. Trying /data/app-lib path.");
+      try {
+        System.load("/data/app-lib/" + AppConstants.ANDROID_PACKAGE_NAME + "/libmozglue.so");
+      } catch (Throwable ee) {
+          try {
+            Log.wtf("NativeCrypto", "Couldn't load mozglue: " + ee + ". Trying /data/data path.");
+            System.load("/data/data/" + AppConstants.ANDROID_PACKAGE_NAME + "/lib/libmozglue.so");
+          } catch (UnsatisfiedLinkError eee) {
+              Log.wtf("NativeCrypto", "Failed every attempt to load mozglue. Giving up.");
+              throw new RuntimeException("Unable to load mozglue", eee);
+          }
+      }
+    }
   }
 
   /**
    * Wrapper to perform PBKDF2-HMAC-SHA-256 in native code.
    */
   public native static byte[] pbkdf2SHA256(byte[] password, byte[] salt, int c, int dkLen)
       throws GeneralSecurityException;
 
--- a/mobile/android/base/db/PasswordsProvider.java
+++ b/mobile/android/base/db/PasswordsProvider.java
@@ -1,27 +1,27 @@
 /* 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.db;
 
-import java.lang.IllegalArgumentException;
 import java.util.HashMap;
+
 import org.mozilla.gecko.GeckoApp;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.NSSBridge;
-import org.mozilla.gecko.db.DBUtils;
+import org.mozilla.gecko.db.BrowserContract.DeletedPasswords;
 import org.mozilla.gecko.db.BrowserContract.Passwords;
-import org.mozilla.gecko.db.BrowserContract.DeletedPasswords;
-import org.mozilla.gecko.db.BrowserContract;
+import org.mozilla.gecko.mozglue.GeckoLoader;
 import org.mozilla.gecko.sqlite.MatrixBlobCursor;
 import org.mozilla.gecko.sqlite.SQLiteBridge;
 import org.mozilla.gecko.sync.Utils;
+
 import android.content.ContentValues;
 import android.content.Intent;
 import android.content.UriMatcher;
 import android.database.Cursor;
 import android.net.Uri;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -71,17 +71,20 @@ public class PasswordsProvider extends S
         PASSWORDS_PROJECTION_MAP.put(Passwords.TIMES_USED, Passwords.TIMES_USED);
 
         URI_MATCHER.addURI(BrowserContract.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");
+
+        // We don't use .loadMozGlue because we're in a different process,
+        // and we just want to reuse code rather than use the loader lock etc.
+        GeckoLoader.doLoadLibrary("mozglue");
     }
 
     public PasswordsProvider() {
         super(LOG_TAG);
     }
 
     @Override
     protected String getDBName(){
--- a/mobile/android/base/mozglue/GeckoLoader.java.in
+++ b/mobile/android/base/mozglue/GeckoLoader.java.in
@@ -1,8 +1,9 @@
+#filter substitution
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.mozglue;
 
 import android.content.Context;
@@ -15,16 +16,19 @@ import java.io.File;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.text.NumberFormat;
 import java.util.Locale;
 
 public final class GeckoLoader {
     private static final String LOGTAG = "GeckoLoader";
 
+    // This matches AppConstants, but we're built earlier.
+    private static final String ANDROID_PACKAGE_NAME = "@ANDROID_PACKAGE_NAME@";
+
     private static volatile Intent sIntent;
     private static File sCacheFile;
     private static File sGREDir;
 
     private static final Object sLibLoadingLock = new Object();
     // Must hold sLibLoadingLock while accessing the following boolean variables.
     private static boolean sSQLiteLibsLoaded;
     private static boolean sNSSLibsLoaded;
@@ -254,25 +258,44 @@ public final class GeckoLoader {
             sNSSLibsLoaded = true;
         }
 
         loadMozGlue();
         loadLibsSetup(context);
         loadNSSLibsNative(apkName, false);
     }
 
+    public static void doLoadLibrary(final String lib) {
+        try {
+            System.loadLibrary(lib);
+        } catch (UnsatisfiedLinkError e) {
+            Log.wtf(LOGTAG, "Couldn't load " + lib + ". Trying /data/app-lib path.");
+            try {
+                System.load("/data/app-lib/" + ANDROID_PACKAGE_NAME + "/lib" + lib + ".so");
+            } catch (Throwable ee) {
+                try {
+                    Log.wtf(LOGTAG, "Couldn't load " + lib + ": " + ee + ". Trying /data/data path.");
+                    System.load("/data/data/" + ANDROID_PACKAGE_NAME + "/lib/lib" + lib + ".so");
+                } catch (Throwable eee) {
+                    Log.wtf(LOGTAG, "Failed every attempt to load " + lib + ". Giving up.");
+                    throw new RuntimeException("Unable to load " + lib, eee);
+                }
+            }
+        }
+    }
+
     public static void loadMozGlue() {
         synchronized (sLibLoadingLock) {
             if (sMozGlueLoaded) {
                 return;
             }
             sMozGlueLoaded = true;
         }
 
-        System.loadLibrary("mozglue");
+        doLoadLibrary("mozglue");
     }
 
     public static void loadGeckoLibs(Context context, String apkName) {
         loadLibsSetup(context);
         loadGeckoLibsNative(apkName);
     }
 
     private static void setupLocaleEnvironment() {