diff --git a/embedding/android/GeckoAppShell.java b/embedding/android/GeckoAppShell.java index ca13fea03a7a..683f3831cdf1 100644 --- a/embedding/android/GeckoAppShell.java +++ b/embedding/android/GeckoAppShell.java @@ -114,8 +114,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 native void reportJavaCrash(String stack); @@ -398,8 +397,7 @@ public class GeckoAppShell } } } - loadSQLiteLibsNative(apkName); - loadNSSLibsNative(apkName); + loadSQLiteLibsNative(apkName, extractLibs); loadGeckoLibsNative(apkName); } diff --git a/mobile/android/base/AndroidManifest.xml.in b/mobile/android/base/AndroidManifest.xml.in index e2fb272ee5a9..33a9e5730ad4 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 4d239a6e288c..c59c1cb90a26 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"; diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 35250a1e034a..08c92daf641f 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -112,7 +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; @@ -141,8 +140,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 registerGlobalExceptionHandler() { @@ -267,6 +265,15 @@ public class GeckoAppShell File cacheFile = getCacheDir(context); putenv("GRE_HOME=" + getGREDir(context).getPath()); + 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(); + } + } // setup the libs cache String linkerCache = System.getenv("MOZ_LINKER_CACHE"); @@ -359,24 +366,11 @@ public class GeckoAppShell loadMozGlue(); // the extract libs parameter is being removed in bug 732069 loadLibsSetup(context); - loadSQLiteLibsNative(apkName); + loadSQLiteLibsNative(apkName, false); 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"); } diff --git a/mobile/android/base/GeckoMessageReceiver.java b/mobile/android/base/GeckoMessageReceiver.java deleted file mode 100644 index 02856fa41049..000000000000 --- 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 8e2df22bf24b..2f3392787031 100644 --- a/mobile/android/base/GeckoThread.java +++ b/mobile/android/base/GeckoThread.java @@ -90,7 +90,6 @@ public class GeckoThread extends Thread { String resourcePath = app.getApplication().getPackageResourcePath(); GeckoAppShell.setupGeckoEnvironment(app); GeckoAppShell.loadSQLiteLibs(app, resourcePath); - GeckoAppShell.loadNSSLibs(app, resourcePath); GeckoAppShell.loadGeckoLibs(resourcePath); Locale.setDefault(locale); diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 6b48b93b156f..08b23bc70897 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -88,7 +88,6 @@ FENNEC_JAVA_FILES = \ GeckoEventListener.java \ GeckoEventResponder.java \ GeckoInputConnection.java \ - GeckoMessageReceiver.java \ GeckoPreferences.java \ GeckoProfile.java \ GeckoStateListDrawable.java \ @@ -96,7 +95,6 @@ FENNEC_JAVA_FILES = \ GlobalHistory.java \ LinkPreference.java \ LinkTextView.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 d3b11dd15aab..000000000000 --- 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/db/BrowserContract.java.in b/mobile/android/base/db/BrowserContract.java.in index 725a13ff2b37..9cbc319d4298 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 593adbd14cfe..cc651ab573b7 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 874a01d5f939..257250cc2372 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; @@ -54,13 +57,10 @@ public class FormHistoryProvider extends GeckoProvider { private static int DB_VERSION = 4; private static String DB_FILENAME = "formhistory.sqlite"; - private static final String WHERE_GUID_IS_NULL = BrowserContract.DeletedFormHistory.GUID + " IS NULL"; - private static final String WHERE_GUID_IS_VALUE = BrowserContract.DeletedFormHistory.GUID + " = ?"; - 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(); } @@ -146,28 +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); - try { - if (guid == null) { - db.delete(TABLE_DELETED_FORM_HISTORY, WHERE_GUID_IS_NULL, null); - return; - } - String[] args = new String[] { guid }; - db.delete(TABLE_DELETED_FORM_HISTORY, WHERE_GUID_IS_VALUE, 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 ea90b8653f59..6944efc18ff4 100644 --- a/mobile/android/base/db/GeckoProvider.java.in +++ b/mobile/android/base/db/GeckoProvider.java.in @@ -90,7 +90,6 @@ public abstract class GeckoProvider extends ContentProvider { 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 +221,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 +242,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 +267,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 +281,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 3c24082e2b0e..6e452fa4cca8 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; @@ -59,9 +60,6 @@ public class PasswordsProvider extends GeckoProvider { private static final int DB_VERSION = 5; private static final String DB_FILENAME = "signons.sqlite"; - private static final String WHERE_GUID_IS_NULL = BrowserContract.DeletedPasswords.GUID + " IS NULL"; - private static final String WHERE_GUID_IS_VALUE = BrowserContract.DeletedPasswords.GUID + " = ?"; - static { URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); @@ -84,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 @@ -192,95 +189,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); - try { - if (guid == null) { - db.delete(TABLE_DELETED_PASSWORDS, WHERE_GUID_IS_NULL, null); - return; - } - String[] args = new String[] { guid }; - db.delete(TABLE_DELETED_PASSWORDS, WHERE_GUID_IS_VALUE, 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 f4ca2d09494c..6fa996bd55e3 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 025763280c97..bfbc26f758e7 100644 --- a/mobile/android/base/tests/BaseTest.java.in +++ b/mobile/android/base/tests/BaseTest.java.in @@ -204,33 +204,4 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2 { } 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 f8cfb46046b8..7824b5945d18 100644 --- a/mobile/android/base/tests/robocop.ini +++ b/mobile/android/base/tests/robocop.ini @@ -11,8 +11,6 @@ [testAboutPage] [testWebContentContextMenu] [testPasswordProvider] -[testPasswordEncrypt] -[testPasswordUndeletion] [testFormHistory] # Used for Talos, please don't use in mochitest diff --git a/mobile/android/base/tests/testPasswordEncrypt.java.in b/mobile/android/base/tests/testPasswordEncrypt.java.in deleted file mode 100644 index 67d0edfc11f8..000000000000 --- a/mobile/android/base/tests/testPasswordEncrypt.java.in +++ /dev/null @@ -1,112 +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.reflect.Method; - -public class testPasswordEncrypt extends BaseTest { - public void testPasswordEncrypt() { - setTestType("mochitest"); - Context context = (Context)getActivity(); - ContentResolver cr = context.getContentResolver(); - ContentValues cvs = new ContentValues(); - - Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("Gecko:Ready"); - contentEventExpecter.blockForEvent(); - - File db = new File(mProfile, "signons.sqlite"); - String dbPath = db.getPath(); - - Uri passwordUri; - try { - ClassLoader classLoader = getActivity().getClassLoader(); - Class pwds = classLoader.loadClass("org.mozilla.gecko.db.BrowserContract$Passwords"); - Class nss = classLoader.loadClass("org.mozilla.gecko.NSSBridge"); - Class contextClass = classLoader.loadClass("android.content.Context"); - Class stringClass = classLoader.loadClass("java.lang.String"); - Class appshell = classLoader.loadClass("org.mozilla.gecko.GeckoAppShell"); - - Method loadNSSLibs = appshell.getMethod("loadNSSLibs", contextClass, stringClass); - Method decrypt = nss.getMethod("decrypt", contextClass, stringClass, stringClass); - Method encrypt = nss.getMethod("encrypt", contextClass, stringClass, stringClass); - - cvs.put("hostname", "http://www.example.com"); - cvs.put("encryptedUsername", "username"); - cvs.put("encryptedPassword", "password"); - - // 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(); - - // This 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); - contentEventExpecter.blockForEvent(); - mAsserter.is(uri, null, "Insert returned null correctly"); - - uri = cr.insert(passwordUri, cvs); - Uri expectedUri = passwordUri.buildUpon().appendPath("1").build(); - mAsserter.is(uri.toString(), expectedUri.toString(), "Insert returned correct uri"); - - Cursor list = mActions.querySql(dbPath, "SELECT encryptedUsername FROM moz_logins"); - String resourcePath = getActivity().getApplication().getPackageResourcePath(); - loadNSSLibs.invoke(null, (Context)getActivity(), resourcePath); - - list.moveToFirst(); - String decryptedU = (String)decrypt.invoke(null, context, mProfile, list.getString(0)); - mAsserter.is(decryptedU, "username", "Username was encrypted correctly when inserting"); - - list = mActions.querySql(dbPath, "SELECT encryptedPassword FROM moz_logins"); - list.moveToFirst(); - String decryptedP = (String)decrypt.invoke(null, context, mProfile, list.getString(0)); - mAsserter.is(decryptedP, "password", "Password was encrypted correctly when inserting"); - - cvs.put("encryptedUsername", "username2"); - cvs.put("encryptedPassword", "password2"); - cr.update(passwordUri, cvs, null, null); - - list = mActions.querySql(dbPath, "SELECT encryptedUsername FROM moz_logins"); - list.moveToFirst(); - decryptedU = (String)decrypt.invoke(null, context, mProfile, list.getString(0)); - mAsserter.is(decryptedU, "username2", "Username was encrypted when updating"); - - list = mActions.querySql(dbPath, "SELECT encryptedPassword FROM moz_logins"); - list.moveToFirst(); - decryptedP = (String)decrypt.invoke(null, context, mProfile, list.getString(0)); - mAsserter.is(decryptedP, "password2", "Password was encrypted when updating"); - } catch(ClassNotFoundException ex) { - mAsserter.ok(false, "Error getting class", ex.toString()); - return; - } catch(NoSuchFieldException ex) { - mAsserter.ok(false, "Error getting field", ex.toString()); - return; - } catch(IllegalAccessException ex) { - mAsserter.ok(false, "Error using field", ex.toString()); - return; - } catch(java.lang.NoSuchMethodException ex) { - mAsserter.ok(false, "Error getting method", ex.toString()); - return; - } catch(java.lang.reflect.InvocationTargetException ex) { - mAsserter.ok(false, "Error invoking method", ex.toString()); - return; - } - } - - 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/mobile/android/base/tests/testPasswordProvider.java.in b/mobile/android/base/tests/testPasswordProvider.java.in index 5dbab8e9c4b7..6db2c3279533 100644 --- a/mobile/android/base/tests/testPasswordProvider.java.in +++ b/mobile/android/base/tests/testPasswordProvider.java.in @@ -65,24 +65,21 @@ public class testPasswordProvider extends BaseTest { 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(uri.toString(), expectedUri.toString(), "Insert returned correct uri"); - Cursor c = cr.query(passwordUri, null, null, null, null); - SqliteCompare(c, cvs); + 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"); - c = cr.query(passwordUri, null, null, null, null); - SqliteCompare(c, cvs); + 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]; - c = cr.query(passwordUri, null, null, null, null); - SqliteCompare(c, cvs); + SqliteCompare(DB_NAME, "SELECT * FROM moz_logins", cvs); } public void tearDown() throws Exception { diff --git a/mobile/android/base/tests/testPasswordUndeletion.java.in b/mobile/android/base/tests/testPasswordUndeletion.java.in deleted file mode 100644 index 0639d2ab20e4..000000000000 --- a/mobile/android/base/tests/testPasswordUndeletion.java.in +++ /dev/null @@ -1,98 +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/. */ - -#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 android.util.Log; -import java.util.ArrayList; -import java.lang.reflect.Method; - -public class testPasswordUndeletion extends BaseTest { - public void testPasswordUndeletion() { - 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(); - - File db = new File(mProfile, "signons.sqlite"); - String dbPath = db.getPath(); - - Uri passwordUri; - Uri deletedPasswordUri; - try { - ClassLoader classLoader = getActivity().getClassLoader(); - Class pwds = classLoader.loadClass("org.mozilla.gecko.db.BrowserContract$Passwords"); - Class deletedpwds = classLoader.loadClass("org.mozilla.gecko.db.BrowserContract$DeletedPasswords"); - Class nss = classLoader.loadClass("org.mozilla.gecko.NSSBridge"); - Class contextClass = classLoader.loadClass("android.content.Context"); - Class stringClass = classLoader.loadClass("java.lang.String"); - Class appshell = classLoader.loadClass("org.mozilla.gecko.GeckoAppShell"); - - Method ensureNSSLibsLoaded = appshell.getMethod("ensureNSSLibsLoaded", contextClass, stringClass); - Method decrypt = nss.getMethod("decrypt", contextClass, stringClass, stringClass); - Method encrypt = nss.getMethod("encrypt", contextClass, stringClass, stringClass); - - cvs[0].put("guid", "MtaVURdK-eRl"); - - // Attempt to insert into the database. - deletedPasswordUri = (Uri) deletedpwds.getField("CONTENT_URI").get(null); - deletedPasswordUri = deletedPasswordUri.buildUpon().appendQueryParameter("profilePath", mProfile).build(); - passwordUri = (Uri) pwds.getField("CONTENT_URI").get(null); - passwordUri = passwordUri.buildUpon().appendQueryParameter("profilePath", mProfile).build(); - - Uri uri = cr.insert(deletedPasswordUri, cvs[0]); - mAsserter.is(uri, null, "Insert returned null correctly"); - - // This 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"); - contentEventExpecter.blockForEvent(); - cr.insert(deletedPasswordUri, cvs[0]); - - // Attempting to insert another item with the same guid should - // remove the item from deletedPasswords database. - cr.insert(passwordUri, cvs[0]); - Cursor c = cr.query(deletedPasswordUri, null, null, null, null); - SqliteCompare(c, new ContentValues[0]); - - c = cr.query(passwordUri, null, null, null, null); - SqliteCompare(c, cvs); - - } catch(ClassNotFoundException ex) { - mAsserter.ok(false, "Error getting class", ex.toString()); - return; - } catch(NoSuchFieldException ex) { - mAsserter.ok(false, "Error getting field", ex.toString()); - return; - } catch(IllegalAccessException ex) { - mAsserter.ok(false, "Error using field", ex.toString()); - return; - } catch(java.lang.NoSuchMethodException ex) { - mAsserter.ok(false, "Error getting method", ex.toString()); - return; - } - } - - 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 fa90ff1fd147..a648970cae04 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,10 +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; -static bool simple_linker_initialized = false; +#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 @@ -461,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; @@ -573,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; @@ -599,8 +673,18 @@ loadGeckoLibs(const char *apkName) #else #define MOZLOAD(name) mozload("lib" name ".so", zip) MOZLOAD("mozalloc"); + MOZLOAD("nspr4"); + MOZLOAD("plc4"); + MOZLOAD("plds4"); + MOZLOAD("nssutil3"); + MOZLOAD("nss3"); + MOZLOAD("ssl3"); + MOZLOAD("smime3"); xul_handle = MOZLOAD("xul"); MOZLOAD("xpcom"); + MOZLOAD("nssckbi"); + MOZLOAD("freebl3"); + MOZLOAD("softokn3"); #undef MOZLOAD #endif @@ -609,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); @@ -656,24 +738,22 @@ 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 - if (!simple_linker_initialized) { - simple_linker_init(); - simple_linker_initialized = true; - } + simple_linker_init(); + + struct stat status; + if (!stat(apkName, &status)) + apk_mtime = status.st_mtime; #endif RefPtr zip = new Zip(apkName); - if (!lib_mapping) { - lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping)); - } + lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping)); #ifdef MOZ_CRASHREPORTER file_ids = (char *)extractBuf("lib.id", zip); @@ -695,92 +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 - if (!simple_linker_initialized) { - simple_linker_init(); - simple_linker_initialized = true; - } -#endif - - Zip *zip = new Zip(apkName); - if (!lib_mapping) { - 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) - nspr_handle = MOZLOAD("nspr4"); - plc_handle = MOZLOAD("plc4"); - MOZLOAD("plds4"); - MOZLOAD("nssutil3"); - nss_handle = MOZLOAD("nss3"); - MOZLOAD("ssl3"); - MOZLOAD("smime3"); - MOZLOAD("nssckbi"); - MOZLOAD("freebl3"); - MOZLOAD("softokn3"); -#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 @@ -793,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) { - putenv("MOZ_LINKER_EXTRACT=1"); +Java_org_mozilla_gecko_GeckoAppShell_loadSQLiteLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName, jboolean jShouldExtract) { + 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 @@ -810,31 +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) { - putenv("MOZ_LINKER_EXTRACT=1"); - 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); } @@ -858,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; @@ -874,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 = @@ -896,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 9392dac36b25..899756919fa4 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 564d57ccfb56..47c0db1001a0 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 f7b6ee9cfdb1..000000000000 --- 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 1ed49f62dea5..000000000000 --- 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 319b2d88f069..b113bf6c189b 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 4295669d5f5e..bbde8bf41df5 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);