Bug 731341 - LoadLibs should take a context. r=blassey
☠☠ backed out by 5940fe8d1af9 ☠ ☠
authorWes Johnston <wjohnston@mozilla.com>
Thu, 08 Mar 2012 10:25:44 -0800
changeset 91436 a965cebe44623ba09f4e3a938d677b7b85e7541a
parent 91435 7876e5486b517392339633d00ce5aed4a800d008
child 91437 32220d7085e049de7aa02e6f47793b0101a208d1
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)
reviewersblassey
bugs731341
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 731341 - LoadLibs should take a context. r=blassey
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/GeckoThread.java
mobile/android/base/ProfileMigrator.java
mobile/android/base/db/GeckoProvider.java.in
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -116,17 +116,16 @@ abstract public class GeckoApp
     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 +1610,17 @@ abstract public class GeckoApp
     {
         mAppContext = this;
 
         // StrictMode is set by defaults resource flag |enableStrictMode|.
         if (getResources().getBoolean(R.bool.enableStrictMode)) {
             enableStrictMode();
         }
 
-        System.loadLibrary("mozglue");
+        GeckoAppShell.loadMozGlue();
         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,19 +1681,16 @@ 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
@@ -2508,17 +2504,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, sGREDir);
+                    File file = File.createTempFile(fileName, fileExt, GeckoAppShell.getGREDir(GeckoApp.mAppContext));
 
                     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,16 +107,18 @@ 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 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
@@ -207,142 +209,169 @@ public class GeckoAppShell
     public static Handler getMainHandler() {
         return GeckoApp.mAppContext.mMainHandler;
     }
 
     public static Handler getHandler() {
         return GeckoBackgroundThread.getHandler();
     }
 
-    public static File getCacheDir() {
+    public static File getCacheDir(Context context) {
         if (sCacheFile == null)
-            sCacheFile = GeckoApp.mAppContext.getCacheDir();
+            sCacheFile = context.getCacheDir();
         return sCacheFile;
     }
 
-    public static long getFreeSpace() {
+    public static long getFreeSpace(Context context) {
         try {
             if (sFreeSpace == -1) {
-                File cacheDir = getCacheDir();
+                File cacheDir = getCacheDir(context);
                 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 boolean loadLibsSetup(String apkName) {
+    public static void loadLibsSetup(Context context) {
+        if (sLibsSetup)
+            return;
+
         // 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.
-        GeckoApp geckoApp = GeckoApp.mAppContext;
-        GeckoProfile profile = geckoApp.getProfile();
-        profile.moveProfilesToAppInstallLocation();
+        GeckoProfile profile = GeckoProfile.get(context);
 
+        File cacheFile = getCacheDir(context);
+        putenv("GRE_HOME=" + getGREDir(context).getPath());
+        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();
+            }
+        }
+
+        // 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 = GeckoApp.mAppContext.getPluginDirectories();
+            String[] dirs = context.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 );
+    }
 
-        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();
+    private static void setupDownloadEnvironment(GeckoApp context) {
         try {
             File downloadDir = null;
             File updatesDir  = null;
             if (Build.VERSION.SDK_INT >= 8) {
                 downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
-                updatesDir  = GeckoApp.mAppContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
+                updatesDir  = context.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);
         }
+    }
+
+    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();
-
-        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 ensureSQLiteLibsLoaded(String apkName) {
+    public static void loadSQLiteLibs(Context context, String apkName) {
         if (sSQLiteLibsLoaded)
             return;
         synchronized(sSQLiteLibsLoaded) {
             if (sSQLiteLibsLoaded)
                 return;
-            loadSQLiteLibsNative(apkName, loadLibsSetup(apkName));
+            loadMozGlue();
+            // the extract libs parameter is being removed in bug 732069
+            loadSQLiteLibsNative(apkName, false);
             sSQLiteLibsLoaded = true;
         }
     }
 
+    public static void loadMozGlue() {
+        System.loadLibrary("mozglue");
+    }
+
     public static void loadGeckoLibs(String apkName) {
-        boolean extractLibs = loadLibsSetup(apkName);
+        loadLibsSetup(GeckoApp.mAppContext);
         loadGeckoLibsNative(apkName);
     }
 
     private static void putLocaleEnv() {
         GeckoAppShell.putenv("LANG=" + Locale.getDefault().toString());
         NumberFormat nf = NumberFormat.getInstance();
         if (nf instanceof DecimalFormat) {
             DecimalFormat df = (DecimalFormat)nf;
--- 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();
+        File cacheFile = GeckoAppShell.getCacheDir(app);
         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,19 +81,22 @@ 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.ensureSQLiteLibsLoaded(resourcePath);
+        GeckoAppShell.setupGeckoEnvironment(app);
+        GeckoAppShell.loadSQLiteLibs(app, 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");
 
--- 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.ensureSQLiteLibsLoaded(GeckoApp.mAppContext.getApplication().getPackageResourcePath());
+            GeckoAppShell.loadSQLiteLibs(GeckoApp.mAppContext, 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();
+            File cacheFile = GeckoAppShell.getCacheDir(GeckoApp.mAppContext);
             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/GeckoProvider.java.in
+++ b/mobile/android/base/db/GeckoProvider.java.in
@@ -83,16 +83,18 @@ 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);
             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;