diff --git a/build/mobile/robocop/Actions.java.in b/build/mobile/robocop/Actions.java.in index baeeabd9151..0c123016921 100644 --- a/build/mobile/robocop/Actions.java.in +++ b/build/mobile/robocop/Actions.java.in @@ -39,9 +39,6 @@ package @ANDROID_PACKAGE_NAME@; import java.util.List; -import java.util.ArrayList; - -import android.database.Cursor; public interface Actions { @@ -95,9 +92,4 @@ public interface Actions { 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); } diff --git a/build/mobile/robocop/FennecMochitestAssert.java.in b/build/mobile/robocop/FennecMochitestAssert.java.in index 58841a6a3ca..20199ec5110 100644 --- a/build/mobile/robocop/FennecMochitestAssert.java.in +++ b/build/mobile/robocop/FennecMochitestAssert.java.in @@ -166,13 +166,21 @@ public class FennecMochitestAssert implements Assert { } 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) { @@ -199,50 +207,21 @@ public class FennecMochitestAssert implements Assert { } 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) { diff --git a/build/mobile/robocop/FennecNativeActions.java.in b/build/mobile/robocop/FennecNativeActions.java.in index 7f8d88de317..973a3fd70bb 100644 --- a/build/mobile/robocop/FennecNativeActions.java.in +++ b/build/mobile/robocop/FennecNativeActions.java.in @@ -40,24 +40,19 @@ 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.*; @@ -79,7 +74,6 @@ public class FennecNativeActions implements Actions { 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; @@ -355,36 +349,4 @@ public class FennecNativeActions implements Actions { 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; - } } diff --git a/mobile/android/base/AndroidManifest.xml.in b/mobile/android/base/AndroidManifest.xml.in index 9f8ac674809..401117e480c 100644 --- a/mobile/android/base/AndroidManifest.xml.in +++ b/mobile/android/base/AndroidManifest.xml.in @@ -23,7 +23,6 @@ - #ifdef MOZ_WEBSMS_BACKEND @@ -117,13 +116,6 @@ - - - - - - + android:permission="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER" + android:protectionLevel="signature"/> - - diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index dbefa7c79d2..6009168dc7f 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -109,7 +109,6 @@ abstract public class GeckoApp 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"; @@ -122,6 +121,7 @@ abstract public class GeckoApp 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; @@ -1616,7 +1616,7 @@ abstract public class GeckoApp enableStrictMode(); } - GeckoAppShell.loadMozGlue(); + System.loadLibrary("mozglue"); mMainHandler = new GeckoAppHandler(); Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - onCreate"); if (savedInstanceState != null) { @@ -1687,6 +1687,9 @@ abstract public class GeckoApp 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())) { @@ -2510,7 +2513,7 @@ abstract public class GeckoApp 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); diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 2693f1845ef..8857d2fd54f 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -112,9 +112,6 @@ public class GeckoAppShell 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> mEventListeners; @@ -141,8 +138,7 @@ public class GeckoAppShell 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) { @@ -216,16 +212,16 @@ public class GeckoAppShell 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() * @@ -240,37 +236,17 @@ public class GeckoAppShell 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); + GeckoApp geckoApp = GeckoApp.mAppContext; + GeckoProfile profile = geckoApp.getProfile(); + profile.moveProfilesToAppInstallLocation(); - File cacheFile = getCacheDir(context); - putenv("GRE_HOME=" + getGREDir(context).getPath()); - - // 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]); @@ -278,22 +254,49 @@ public class GeckoAppShell 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); } - } - private static void setupDownloadEnvironment(GeckoApp context) { + 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(); 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"); } @@ -303,76 +306,38 @@ public class GeckoAppShell 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 cacheFiles = Arrays.asList(files).iterator(); + while (cacheFiles.hasNext()) { + File libFile = cacheFiles.next(); + if (libFile.getName().endsWith(".so")) + libFile.delete(); + } + } + } + return extractLibs; } - 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); } diff --git a/mobile/android/base/GeckoMessageReceiver.java b/mobile/android/base/GeckoMessageReceiver.java deleted file mode 100644 index 02856fa4104..00000000000 --- 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)); - } - } -} diff --git a/mobile/android/base/GeckoThread.java b/mobile/android/base/GeckoThread.java index b47404dbdcf..3276ed219aa 100644 --- a/mobile/android/base/GeckoThread.java +++ b/mobile/android/base/GeckoThread.java @@ -66,7 +66,7 @@ public class GeckoThread extends Thread { 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() || @@ -86,13 +86,9 @@ public class GeckoThread extends Thread { // 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(); @@ -112,6 +108,5 @@ public class GeckoThread extends Thread { } catch (Exception e) { GeckoAppShell.reportJavaCrash(e); } - } } diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 9e9b19c7dad..a7c9f102770 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -88,14 +88,12 @@ FENNEC_JAVA_FILES = \ 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 \ diff --git a/mobile/android/base/NSSBridge.java b/mobile/android/base/NSSBridge.java deleted file mode 100644 index d3b11dd15aa..00000000000 --- 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; - } -} diff --git a/mobile/android/base/ProfileMigrator.java b/mobile/android/base/ProfileMigrator.java index 2c0544ba95c..7c956d47e8c 100644 --- a/mobile/android/base/ProfileMigrator.java +++ b/mobile/android/base/ProfileMigrator.java @@ -640,7 +640,7 @@ public class ProfileMigrator { 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); @@ -664,7 +664,7 @@ public class ProfileMigrator { } protected void cleanupXULLibCache() { - File cacheFile = GeckoAppShell.getCacheDir(GeckoApp.mAppContext); + File cacheFile = GeckoAppShell.getCacheDir(); File[] files = cacheFile.listFiles(); if (files != null) { Iterator cacheFiles = Arrays.asList(files).iterator(); diff --git a/mobile/android/base/db/BrowserContract.java.in b/mobile/android/base/db/BrowserContract.java.in index 725a13ff2b3..9cbc319d429 100644 --- a/mobile/android/base/db/BrowserContract.java.in +++ b/mobile/android/base/db/BrowserContract.java.in @@ -45,10 +45,15 @@ public class BrowserContract { 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); @@ -163,7 +168,7 @@ public class BrowserContract { 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 { @@ -182,7 +187,7 @@ public class BrowserContract { 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"; } diff --git a/mobile/android/base/db/DBUtils.java b/mobile/android/base/db/DBUtils.java index 593adbd14cf..cc651ab573b 100644 --- a/mobile/android/base/db/DBUtils.java +++ b/mobile/android/base/db/DBUtils.java @@ -59,7 +59,7 @@ public class DBUtils { aValues.remove(aOriginalKey); } - if (!aValues.containsKey(aNewKey)) { + if (!aValues.containsKey(aOriginalKey)) { aValues.put(aNewKey, value); } } diff --git a/mobile/android/base/db/FormHistoryProvider.java.in b/mobile/android/base/db/FormHistoryProvider.java.in index a293cc61b65..257250cc237 100644 --- a/mobile/android/base/db/FormHistoryProvider.java.in +++ b/mobile/android/base/db/FormHistoryProvider.java.in @@ -33,6 +33,9 @@ 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; @@ -57,7 +60,7 @@ public class FormHistoryProvider extends GeckoProvider { 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(); DELETED_FORM_HISTORY_PROJECTION_MAP = new HashMap(); } @@ -143,29 +146,4 @@ public class FormHistoryProvider extends GeckoProvider { 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) { } } diff --git a/mobile/android/base/db/GeckoProvider.java.in b/mobile/android/base/db/GeckoProvider.java.in index ea90b8653f5..4cbb30cdf2f 100644 --- a/mobile/android/base/db/GeckoProvider.java.in +++ b/mobile/android/base/db/GeckoProvider.java.in @@ -88,9 +88,6 @@ public abstract class GeckoProvider extends ContentProvider { 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); @@ -222,8 +219,6 @@ public abstract class GeckoProvider extends ContentProvider { setupDefaults(uri, values); - onPreInsert(values, uri, db); - try { id = db.insert(getTable(uri), null, values); } catch(SQLiteBridgeException ex) { @@ -245,8 +240,6 @@ public abstract class GeckoProvider extends ContentProvider { if (db == null) return updated; - onPreUpdate(values, uri, db); - try { updated = db.update(getTable(uri), values, selection, selectionArgs); } catch(SQLiteBridgeException ex) { @@ -272,7 +265,6 @@ public abstract class GeckoProvider extends ContentProvider { 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); } @@ -287,10 +279,4 @@ public abstract class GeckoProvider extends ContentProvider { 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); } diff --git a/mobile/android/base/db/PasswordsProvider.java.in b/mobile/android/base/db/PasswordsProvider.java.in index dc61b1ee16d..7ad3e240305 100644 --- a/mobile/android/base/db/PasswordsProvider.java.in +++ b/mobile/android/base/db/PasswordsProvider.java.in @@ -17,13 +17,12 @@ 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; @@ -32,9 +31,11 @@ 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; @@ -81,13 +82,12 @@ public class PasswordsProvider extends GeckoProvider { 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(); 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 @@ -168,6 +168,9 @@ public class PasswordsProvider extends GeckoProvider { 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, ""); @@ -189,97 +192,5 @@ public class PasswordsProvider extends GeckoProvider { @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()); - } - } } } diff --git a/mobile/android/base/sqlite/MatrixBlobCursor.java b/mobile/android/base/sqlite/MatrixBlobCursor.java index f4ca2d09494..6fa996bd55e 100644 --- a/mobile/android/base/sqlite/MatrixBlobCursor.java +++ b/mobile/android/base/sqlite/MatrixBlobCursor.java @@ -228,21 +228,8 @@ public class MatrixBlobCursor extends AbstractCursor { } } - 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. + @Override public int getCount() { return rowCount; diff --git a/mobile/android/base/tests/BaseTest.java.in b/mobile/android/base/tests/BaseTest.java.in index bfbc26f758e..158ae1998e6 100644 --- a/mobile/android/base/tests/BaseTest.java.in +++ b/mobile/android/base/tests/BaseTest.java.in @@ -6,12 +6,9 @@ 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; @@ -28,7 +25,6 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2 { protected String mBaseUrl; private String mTestType; private String mLogFile; - protected String mProfile; static { try { @@ -50,8 +46,7 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2 { // 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); @@ -153,55 +148,4 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2 { 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; - } } diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini index 7824b5945d1..3f8686626e1 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -10,8 +10,6 @@ [testAxisLocking] [testAboutPage] [testWebContentContextMenu] -[testPasswordProvider] -[testFormHistory] # Used for Talos, please don't use in mochitest #[testPan] diff --git a/mobile/android/base/tests/testFormHistory.java.in b/mobile/android/base/tests/testFormHistory.java.in deleted file mode 100644 index 90c9231bbac..00000000000 --- 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(); - } -} diff --git a/mobile/android/base/tests/testPasswordProvider.java.in b/mobile/android/base/tests/testPasswordProvider.java.in deleted file mode 100644 index 6db2c327953..00000000000 --- 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(); - } -} diff --git a/mozglue/android/APKOpen.cpp b/mozglue/android/APKOpen.cpp index 295e6fbbc3a..a648970cae0 100644 --- a/mozglue/android/APKOpen.cpp +++ b/mozglue/android/APKOpen.cpp @@ -66,7 +66,6 @@ #include "Zip.h" #include "sqlite3.h" #include "SQLiteBridge.h" -#include "NSSBridge.h" #ifndef MOZ_OLD_LINKER #include "ElfLoader.h" #endif @@ -77,8 +76,6 @@ #define RUSAGE_THREAD 1 #endif -typedef int mozglueresult; - enum StartupEvent { #define mozilla_StartupTimeline_Event(ev, z) ev, #include "StartupTimeline.h" @@ -102,23 +99,6 @@ 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) @@ -333,9 +313,79 @@ 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 @@ -460,6 +510,25 @@ static void * mozload(const char * path, Zip *zip) 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; @@ -572,11 +641,17 @@ report_mapping(char *name, void *base, uint32_t len, uint32_t offset) 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; @@ -597,16 +672,19 @@ loadGeckoLibs(const char *apkName) 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 @@ -615,10 +693,8 @@ loadGeckoLibs(const char *apkName) 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); @@ -662,15 +738,18 @@ loadGeckoLibs(const char *apkName) 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 = new Zip(apkName); @@ -696,80 +775,10 @@ static int loadSQLiteLibs(const char *apkName) 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 @@ -782,16 +791,20 @@ Java_org_mozilla_gecko_GeckoAppShell_loadGeckoLibsNative(JNIEnv *jenv, jclass jG 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 @@ -799,30 +812,7 @@ Java_org_mozilla_gecko_GeckoAppShell_loadSQLiteLibsNative(JNIEnv *jenv, jclass j 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); } @@ -846,8 +836,9 @@ Java_org_mozilla_gecko_GeckoAppShell_nativeRun(JNIEnv *jenv, jclass jc, jstring } typedef int GeckoProcessType; +typedef int nsresult; -extern "C" NS_EXPORT mozglueresult +extern "C" NS_EXPORT int ChildProcessInit(int argc, char* argv[]) { int i; @@ -862,21 +853,14 @@ ChildProcessInit(int argc, char* argv[]) #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 = @@ -884,6 +868,10 @@ ChildProcessInit(int argc, char* argv[]) 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; } diff --git a/mozglue/android/APKOpen.h b/mozglue/android/APKOpen.h index 9392dac36b2..899756919fa 100644 --- a/mozglue/android/APKOpen.h +++ b/mozglue/android/APKOpen.h @@ -37,8 +37,6 @@ #ifndef APKOpen_h #define APKOpen_h -#include - #ifndef NS_EXPORT #define NS_EXPORT __attribute__ ((visibility("default"))) #endif @@ -53,10 +51,6 @@ struct mapping_info { 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 @@ -69,5 +63,4 @@ struct lib_cache_info { NS_EXPORT const struct lib_cache_info * getLibraryCache(); - #endif /* APKOpen_h */ diff --git a/mozglue/android/Makefile.in b/mozglue/android/Makefile.in index 564d57ccfb5..47c0db1001a 100644 --- a/mozglue/android/Makefile.in +++ b/mozglue/android/Makefile.in @@ -55,7 +55,6 @@ CPPSRCS = \ nsGeckoUtils.cpp \ APKOpen.cpp \ SQLiteBridge.cpp \ - NSSBridge.cpp \ $(NULL) LOCAL_INCLUDES += -I$(DEPTH)/build @@ -64,28 +63,6 @@ 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 diff --git a/mozglue/android/NSSBridge.cpp b/mozglue/android/NSSBridge.cpp deleted file mode 100644 index f7b6ee9cfdb..00000000000 --- 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 -#include "dlfcn.h" -#include "NSSBridge.h" -#include "APKOpen.h" -#ifdef ANDROID -#include -#include -#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; -} - - diff --git a/mozglue/android/NSSBridge.h b/mozglue/android/NSSBridge.h deleted file mode 100644 index 1ed49f62dea..00000000000 --- 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 - -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 */ diff --git a/mozglue/android/SQLiteBridge.cpp b/mozglue/android/SQLiteBridge.cpp index 319b2d88f06..b113bf6c189 100644 --- a/mozglue/android/SQLiteBridge.cpp +++ b/mozglue/android/SQLiteBridge.cpp @@ -101,6 +101,21 @@ 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) { diff --git a/other-licenses/android/dlfcn.c b/other-licenses/android/dlfcn.c index 4295669d5f5..bbde8bf41df 100644 --- a/other-licenses/android/dlfcn.c +++ b/other-licenses/android/dlfcn.c @@ -43,6 +43,7 @@ static const char *dl_errors[] = { #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) { @@ -53,6 +54,9 @@ static void set_dlerror(int err) void *__wrap_dlopen(const char *filename, int flag) { + if (extractLibs) + return dlopen(filename, flag); + soinfo *ret; pthread_mutex_lock(&dl_lock); @@ -84,6 +88,9 @@ void *moz_mapped_dlopen(const char *filename, int flag, const char *__wrap_dlerror(void) { + if (extractLibs) + return dlerror(); + const char *tmp = dl_err_str; dl_err_str = NULL; return (const char *)tmp; @@ -91,6 +98,9 @@ const char *__wrap_dlerror(void) void *__wrap_dlsym(void *handle, const char *symbol) { + if (extractLibs) + return dlsym(handle, symbol); + soinfo *found; Elf32_Sym *sym; unsigned bind; @@ -173,6 +183,9 @@ int __wrap_dladdr(void *addr, Dl_info *info) 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);