☠☠ backed out by c347f2c72963 ☠ ☠ | |
author | Wes Johnston <wjohnston@mozilla.com> |
Mon, 09 Apr 2012 10:08:37 -0700 | |
changeset 94566 | f5d6cc2e47260ec824438c5a2caae64cd9f5f62e |
parent 94565 | 9a736b04b47fb62fdf549ce697f60d8d65c49a3d |
child 94567 | c347f2c7296346c6041ff31c3023fe61c1fc1f2c |
push id | 886 |
push user | lsblakk@mozilla.com |
push date | Mon, 04 Jun 2012 19:57:52 +0000 |
treeherder | mozilla-beta@bbd8d5efd6d1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | gcp, rnewman, lucasr |
bugs | 740218 |
milestone | 14.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -36,16 +36,19 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "mozilla/layers/PLayers.h" #include "mozilla/layers/ShadowLayers.h" +#define MOZ_DUMP_PAINTING 1 +#define MOZ_LAYERS_HAVE_LOG 1 + #include "ImageLayers.h" #include "Layers.h" #include "gfxPlatform.h" #include "ReadbackLayer.h" #include "gfxUtils.h" #include "nsPrintfCString.h" #include "mozilla/Util.h" #include "LayerSorter.h"
--- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -49,16 +49,18 @@ #include "gfxColor.h" #include "gfxPattern.h" #include "nsTArray.h" #include "nsThreadUtils.h" #include "mozilla/gfx/2D.h" #include "mozilla/TimeStamp.h" +#define MOZ_DUMP_PAINTING 1 + #if defined(DEBUG) || defined(PR_LOGGING) # include <stdio.h> // FILE # include "prlog.h" # define MOZ_LAYERS_HAVE_LOG # define MOZ_LAYERS_LOG(_args) \ PR_LOG(LayerManager::GetLog(), PR_LOG_DEBUG, _args) #else struct PRLogModuleInfo;
--- a/gfx/thebes/gfxASurface.cpp +++ b/gfx/thebes/gfxASurface.cpp @@ -66,16 +66,18 @@ #if defined(CAIRO_HAS_QT_SURFACE) && defined(MOZ_WIDGET_QT) #include "gfxQPainterSurface.h" #endif #include <stdio.h> #include <limits.h> +#define MOZ_DUMP_PAINTING 1 + #include "imgIEncoder.h" #include "nsComponentManagerUtils.h" #include "prmem.h" #include "nsISupportsUtils.h" #include "plbase64.h" #include "nsCOMPtr.h" #include "nsIConsoleService.h" #include "nsServiceManagerUtils.h"
--- a/gfx/thebes/gfxASurface.h +++ b/gfx/thebes/gfxASurface.h @@ -39,16 +39,17 @@ #define GFX_ASURFACE_H #include "gfxTypes.h" #include "gfxRect.h" #include "nsAutoPtr.h" #include "nsAutoRef.h" #include "nsThreadUtils.h" +#define MOZ_DUMP_PAINTING 1 typedef struct _cairo_surface cairo_surface_t; typedef struct _cairo_user_data_key cairo_user_data_key_t; typedef void (*thebes_destroy_func_t) (void *data); class gfxImageSurface; struct nsIntPoint;
--- a/gfx/thebes/gfxUtils.cpp +++ b/gfx/thebes/gfxUtils.cpp @@ -42,16 +42,18 @@ #include "nsRegion.h" #include "yuv_convert.h" #include "ycbcr_to_rgb565.h" #ifdef XP_WIN #include "gfxWindowsPlatform.h" #endif +#define MOZ_DUMP_PAINTING 1 + using namespace mozilla; using namespace mozilla::layers; using namespace mozilla::gfx; static PRUint8 sUnpremultiplyTable[256*256]; static PRUint8 sPremultiplyTable[256*256]; static bool sTablesInitialized = false;
--- a/gfx/thebes/gfxUtils.h +++ b/gfx/thebes/gfxUtils.h @@ -39,16 +39,18 @@ #define GFX_UTILS_H #include "gfxTypes.h" #include "gfxPattern.h" #include "gfxImageSurface.h" #include "ImageLayers.h" #include "mozilla/gfx/2D.h" +#define MOZ_DUMP_PAINTING 1 + class gfxDrawable; class nsIntRegion; struct nsIntRect; class THEBES_API gfxUtils { public: /* * Premultiply or Unpremultiply aSourceSurface, writing the result
--- a/layout/base/nsLayoutDebugger.cpp +++ b/layout/base/nsLayoutDebugger.cpp @@ -222,16 +222,17 @@ PrintDisplayListTo(nsDisplayListBuilder* fputc('\n', aOutput); if (list) { PrintDisplayListTo(aBuilder, *list, aOutput); } fprintf(aOutput, "</li>"); } fprintf(aOutput, "</ul>"); + printf_stderr("DL: %s", aOutput); } void nsFrame::PrintDisplayList(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, FILE* aFile) { PrintDisplayListTo(aBuilder, aList, aFile);
--- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -107,16 +107,18 @@ #include "nsSVGUtils.h" #include "nsSVGIntegrationUtils.h" #include "nsSVGForeignObjectFrame.h" #include "nsSVGOuterSVGFrame.h" #include "mozilla/Preferences.h" +#define MOZ_DUMP_PAINTING 1 + #ifdef MOZ_XUL #include "nsXULPopupManager.h" #endif #include "sampler.h" using namespace mozilla; using namespace mozilla::layers; @@ -1342,33 +1344,34 @@ nsLayoutUtils::CombineBreakType(PRUint8 } } return breakType; } #ifdef MOZ_DUMP_PAINTING #include <stdio.h> -static bool gDumpEventList = false; +static bool gDumpEventList = true; int gPaintCount = 0; #endif nsresult nsLayoutUtils::GetRemoteContentIds(nsIFrame* aFrame, const nsRect& aTarget, nsTArray<ViewID> &aOutIDs, bool aIgnoreRootScrollFrame) { nsDisplayListBuilder builder(aFrame, nsDisplayListBuilder::EVENT_DELIVERY, false); nsDisplayList list; + nsIFrame* rootScrollFrame = + aFrame->PresContext()->PresShell()->GetRootScrollFrame(); + if (aIgnoreRootScrollFrame) { - nsIFrame* rootScrollFrame = - aFrame->PresContext()->PresShell()->GetRootScrollFrame(); if (rootScrollFrame) { builder.SetIgnoreScrollFrame(rootScrollFrame); } } builder.EnterPresShell(aFrame, aTarget); nsresult rv = @@ -1408,36 +1411,50 @@ nsLayoutUtils::GetFramesForArea(nsIFrame false); nsDisplayList list; nsRect target(aRect); if (aShouldIgnoreSuppression) { builder.IgnorePaintSuppression(); } + nsIFrame* rootScrollFrame = + aFrame->PresContext()->PresShell()->GetRootScrollFrame(); if (aIgnoreRootScrollFrame) { - nsIFrame* rootScrollFrame = - aFrame->PresContext()->PresShell()->GetRootScrollFrame(); if (rootScrollFrame) { builder.SetIgnoreScrollFrame(rootScrollFrame); } } + nsRect displayport; + if (rootScrollFrame) { + nsIContent* content = rootScrollFrame->GetContent(); + bool usingDisplayPort = GetDisplayPort(content, &displayport); + if (usingDisplayPort) { + //printf_stderr(" xxx Setting display port %i%,%i,%i,%i", + // displayport.x, displayport.y, displayport.width, displayport.height); + builder.SetDisplayPort(displayport); + } + } + builder.EnterPresShell(aFrame, target); nsresult rv = aFrame->BuildDisplayListForStackingContext(&builder, target, &list); builder.LeavePresShell(aFrame, target); NS_ENSURE_SUCCESS(rv, rv); #ifdef MOZ_DUMP_PAINTING if (gDumpEventList) { - fprintf(stdout, "Event handling --- (%d,%d):\n", aRect.x, aRect.y); - nsFrame::PrintDisplayList(&builder, list); + printf_stderr("Event handling --- (%d,%d):\n", aRect.x, aRect.y); + FILE *handle; + handle = fopen("/sdcard/test.txt","rw"); + nsFrame::PrintDisplayList(&builder, list, handle); + fclose(handle); } #endif nsDisplayItem::HitTestState hitTestState; list.HitTest(&builder, target, &hitTestState, &aOutFrames); list.DeleteAll(); return NS_OK; }
--- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -2015,18 +2015,21 @@ nsIFrame::BuildDisplayListForChild(nsDis // We can stop if child's frame subtree's intersection with the // dirty area is empty. // If the child is a scrollframe that we want to ignore, then we need // to descend into it because its scrolled child may intersect the dirty // area even if the scrollframe itself doesn't. if (child != aBuilder->GetIgnoreScrollFrame()) { nsRect childDirty; - if (!childDirty.IntersectRect(dirty, child->GetVisualOverflowRect())) + nsRect overflow = child->GetVisualOverflowRect(); + + if (!childDirty.IntersectRect(dirty, overflow)) { return NS_OK; + } // Usually we could set dirty to childDirty now but there's no // benefit, and it can be confusing. It can especially confuse // situations where we're going to ignore a scrollframe's clipping; // we wouldn't want to clip the dirty area to the scrollframe's // bounds in that case. } }
--- a/mobile/android/base/db/FormHistoryProvider.java.in +++ b/mobile/android/base/db/FormHistoryProvider.java.in @@ -147,27 +147,24 @@ public class FormHistoryProvider extends 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); + 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); } @Override public void onPreUpdate(ContentValues values, Uri uri, SQLiteBridge db) { } @Override public void onPostQuery(Cursor cursor, Uri uri, SQLiteBridge db) { } }
--- a/mobile/android/base/db/GeckoProvider.java.in +++ b/mobile/android/base/db/GeckoProvider.java.in @@ -5,16 +5,18 @@ #filter substitution package @ANDROID_PACKAGE_NAME@.db; import java.io.File; import java.io.IOException; import java.lang.IllegalArgumentException; import java.util.HashMap; import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import java.util.Random; import org.mozilla.gecko.GeckoApp; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoProfile; import org.mozilla.gecko.GeckoEvent; import org.mozilla.gecko.GeckoEventListener; import org.mozilla.gecko.db.BrowserContract.CommonColumns; @@ -54,16 +56,40 @@ import android.util.Log; public abstract class GeckoProvider extends ContentProvider { private String mLogTag = "GeckoPasswordsProvider"; private String mDBName = ""; private int mDBVersion = 0; private HashMap<String, SQLiteBridge> mDatabasePerProfile; protected Context mContext = null; + @Override + public void shutdown() { + if (mDatabasePerProfile == null) + return; + + Collection<SQLiteBridge> bridges = mDatabasePerProfile.values(); + Iterator<SQLiteBridge> it = bridges.iterator(); + + while (it.hasNext()) { + SQLiteBridge bridge = it.next(); + if (bridge != null) { + try { + bridge.close(); + } catch (Exception ex) { } + } + } + + mDatabasePerProfile = null; + } + + public void finalize() { + shutdown(); + } + protected void setLogTag(String aLogTag) { mLogTag = aLogTag; } protected String getLogTag() { return mLogTag; } @@ -86,21 +112,24 @@ public abstract class GeckoProvider exte private SQLiteBridge getDB(Context context, final String databasePath) { SQLiteBridge bridge = null; boolean dbNeedsSetup = true; try { String resourcePath = context.getPackageResourcePath(); GeckoAppShell.loadSQLiteLibs(context, resourcePath); GeckoAppShell.loadNSSLibs(context, resourcePath); - bridge = new SQLiteBridge(databasePath); + bridge = SQLiteBridge.openDatabase(databasePath, null, 0); int version = bridge.getVersion(); - Log.i(mLogTag, version + " == " + mDBVersion); dbNeedsSetup = version != mDBVersion; - } catch(SQLiteBridgeException ex) { + } catch (SQLiteBridgeException ex) { + // close the database + if (bridge != null) + bridge.close(); + // this will throw if the database can't be found // we should attempt to set it up if Gecko is running dbNeedsSetup = true; Log.e(mLogTag, "Error getting version ", ex); // if Gecko is not running, we should bail out. Otherwise we try to // let Gecko build the database for us if (!GeckoApp.checkLaunchState(GeckoApp.LaunchState.GeckoRunning)) { @@ -112,17 +141,18 @@ public abstract class GeckoProvider exte // If the database is not set up yet, or is the wrong schema version, we send an initialize // call to Gecko. Gecko will handle building the database file correctly, as well as any // migrations that are necessary if (dbNeedsSetup) { Log.i(mLogTag, "Sending init to gecko"); bridge = null; initGecko(); } - mDatabasePerProfile.put(databasePath, bridge); + if (bridge != null) + mDatabasePerProfile.put(databasePath, bridge); return bridge; } private SQLiteBridge getDatabaseForProfile(String profile) { if (TextUtils.isEmpty(profile)) { Log.d(mLogTag, "No profile provided, using default"); profile = BrowserContract.DEFAULT_PROFILE; @@ -199,16 +229,17 @@ public abstract class GeckoProvider exte final SQLiteBridge db = getDatabase(uri); if (db == null) return deleted; try { deleted = db.delete(getTable(uri), selection, selectionArgs); } catch (SQLiteBridgeException ex) { Log.e(mLogTag, "Error deleting record", ex); + throw ex; } return deleted; } @Override public Uri insert(Uri uri, ContentValues values) { long id = -1; @@ -217,45 +248,94 @@ public abstract class GeckoProvider exte // If we can not get a SQLiteBridge instance, its likely that the database // has not been set up and Gecko is not running. We return null and expect // callers to try again later if (db == null) return null; setupDefaults(uri, values); - onPreInsert(values, uri, db); - + boolean useTransaction = !db.inTransaction(); try { + if (useTransaction) { + db.beginTransaction(); + } + + // onPreInsert does a check for the item in the deleted table in some cases + // so we put it inside this transaction + onPreInsert(values, uri, db); id = db.insert(getTable(uri), null, values); - } catch(SQLiteBridgeException ex) { + + if (useTransaction) { + db.setTransactionSuccessful(); + } + } catch (SQLiteBridgeException ex) { Log.e(mLogTag, "Error inserting in db", ex); + throw ex; + } finally { + if (useTransaction) { + db.endTransaction(); + } } return ContentUris.withAppendedId(uri, id); } @Override + public int bulkInsert(Uri uri, ContentValues[] allValues) { + final SQLiteBridge db = getDatabase(uri); + // If we can not get a SQLiteBridge instance, its likely that the database + // has not been set up and Gecko is not running. We return 0 and expect + // callers to try again later + if (db == null) + return 0; + + long id = -1; + int rowsAdded = 0; + + String table = getTable(uri); + + try { + db.beginTransaction(); + for (ContentValues initialValues : allValues) { + ContentValues values = new ContentValues(initialValues); + setupDefaults(uri, values); + onPreInsert(values, uri, db); + id = db.insert(table, null, values); + rowsAdded++; + } + db.setTransactionSuccessful(); + } catch (SQLiteBridgeException ex) { + Log.e(mLogTag, "Error inserting in db", ex); + throw ex; + } finally { + db.endTransaction(); + } + return rowsAdded; + } + + @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int updated = 0; final SQLiteBridge db = getDatabase(uri); // If we can not get a SQLiteBridge instance, its likely that the database // has not been set up and Gecko is not running. We return null and expect // callers to try again later if (db == null) return updated; onPreUpdate(values, uri, db); try { updated = db.update(getTable(uri), values, selection, selectionArgs); - } catch(SQLiteBridgeException ex) { + } catch (SQLiteBridgeException ex) { Log.e(mLogTag, "Error updating table", ex); + throw ex; } return updated; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { @@ -270,16 +350,17 @@ public abstract class GeckoProvider exte sortOrder = getSortOrder(uri, sortOrder); try { cursor = db.query(getTable(uri), projection, selection, selectionArgs, null, null, sortOrder, null); onPostQuery(cursor, uri, db); } catch (SQLiteBridgeException ex) { Log.e(mLogTag, "Error querying database", ex); + throw ex; } return cursor; } public abstract String getTable(Uri uri); public abstract String getSortOrder(Uri uri, String aRequested);
--- a/mobile/android/base/db/PasswordsProvider.java.in +++ b/mobile/android/base/db/PasswordsProvider.java.in @@ -212,26 +212,22 @@ public class PasswordsProvider extends G } 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 (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); } 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)) {
--- a/mobile/android/base/sqlite/SQLiteBridge.java +++ b/mobile/android/base/sqlite/SQLiteBridge.java @@ -3,49 +3,64 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.sqlite; import org.mozilla.gecko.sqlite.SQLiteBridgeException; import org.mozilla.gecko.sqlite.MatrixBlobCursor; import android.content.ContentValues; import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; +import android.database.DatabaseErrorHandler; import android.text.TextUtils; -import android.util.Log; import java.lang.String; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; +import android.util.Log; import java.util.Map.Entry; import java.util.Set; /* * This class allows using the mozsqlite3 library included with Firefox * to read SQLite databases, instead of the Android SQLiteDataBase API, * which might use whatever outdated DB is present on the Android system. */ public class SQLiteBridge { private static final String LOGTAG = "SQLiteBridge"; - // Path to the database. We reopen it every query. + // Path to the database. If this database was not opened with openDatabase, we reopen it every query. private String mDb; + // pointer to the database if it was opened with openDatabase + protected long mDbPointer = 0; // Values remembered after a query. private long[] mQueryResults; + private boolean mTransactionSuccess = false; + private boolean mInTransaction = false; + private static final int RESULT_INSERT_ROW_ID = 0; private static final int RESULT_ROWS_CHANGED = 1; // JNI code in $(topdir)/mozglue/android/.. private static native MatrixBlobCursor sqliteCall(String aDb, String aQuery, String[] aParams, long[] aUpdateResult) throws SQLiteBridgeException; + private static native MatrixBlobCursor sqliteCallWithDb(long aDb, String aQuery, + String[] aParams, + long[] aUpdateResult) + throws SQLiteBridgeException; + private static native long openDatabase(String aDb) + throws SQLiteBridgeException; + private static native void closeDatabase(long aDb); // Takes the path to the database we want to access. public SQLiteBridge(String aDb) throws SQLiteBridgeException { mDb = aDb; } // Executes a simple line of sql. public void execSQL(String sql) @@ -199,15 +214,97 @@ public class SQLiteBridge { return ret; } // Do an SQL query, substituting the parameters in the query with the passed // parameters. The parameters are subsituded in order, so named parameters // are not supported. private Cursor internalQuery(String aQuery, String[] aParams) throws SQLiteBridgeException { + mQueryResults = new long[2]; + if (isOpen()) { + return sqliteCallWithDb(mDbPointer, aQuery, aParams, mQueryResults); + } return sqliteCall(mDb, aQuery, aParams, mQueryResults); } - // nop, provided for API compatibility with SQLiteDatabase. - public void close() { } + /* + * The second two parameters here are just provided for compatbility with SQLiteDatabase + * Support for them is not currently implemented + */ + public static SQLiteBridge openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags) + throws SQLiteException { + SQLiteBridge bridge = null; + try { + bridge = new SQLiteBridge(path); + bridge.mDbPointer = bridge.openDatabase(path); + } catch(SQLiteBridgeException ex) { + // catch and rethrow as a SQLiteException to match SQLiteDatabase + throw new SQLiteException(ex.getMessage()); + } + return bridge; + } + + public void close() { + if (isOpen()) { + closeDatabase(mDbPointer); + } + mDbPointer = 0; + } + + public boolean isOpen() { + return mDbPointer > 0; + } + + public void beginTransaction() throws SQLiteBridgeException { + if (inTransaction()) { + throw new SQLiteBridgeException("Nested transactions are not supported"); + } + execSQL("BEGIN EXCLUSIVE"); + mTransactionSuccess = false; + mInTransaction = true; + } + + public void beginTransactionNonExclusive() throws SQLiteBridgeException { + if (inTransaction()) { + throw new SQLiteBridgeException("Nested transactions are not supported"); + } + execSQL("BEGIN IMMEDIATE"); + mTransactionSuccess = false; + mInTransaction = true; + } + + public void endTransaction() { + if (!inTransaction()) + return; + + try { + if (mTransactionSuccess) { + execSQL("COMMIT TRANSACTION"); + } else { + execSQL("ROLLBACK TRANSACTION"); + } + } catch(SQLiteBridgeException ex) { + Log.e(LOGTAG, "Error ending transaction", ex); + } + mInTransaction = false; + mTransactionSuccess = false; + } + + public void setTransactionSuccessful() throws SQLiteBridgeException { + if (!inTransaction()) { + throw new SQLiteBridgeException("setTransactionSuccessful called outside a transaction"); + } + mTransactionSuccess = true; + } + + public boolean inTransaction() { + return mInTransaction; + } + + public void finalize() { + if (isOpen()) { + Log.e(LOGTAG, "Bridge finalized without closing the database"); + close(); + } + } }
--- a/mobile/android/base/sqlite/SQLiteBridgeException.java +++ b/mobile/android/base/sqlite/SQLiteBridgeException.java @@ -32,16 +32,16 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.gecko.sqlite; -public class SQLiteBridgeException extends Exception { +public class SQLiteBridgeException extends RuntimeException { static final long serialVersionUID = 1L; public SQLiteBridgeException() {} public SQLiteBridgeException(String msg) { super(msg); } -} \ No newline at end of file +}
--- a/mozglue/android/SQLiteBridge.cpp +++ b/mozglue/android/SQLiteBridge.cpp @@ -163,37 +163,104 @@ extern "C" NS_EXPORT jobject JNICALL Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, jstring jDb, jstring jQuery, jobjectArray jParams, jlongArray jQueryRes) { JNI_Setup(jenv); + int rc; + jobject jCursor = NULL; + const char* dbPath; + sqlite3 *db; + char* errorMsg; + + dbPath = jenv->GetStringUTFChars(jDb, NULL); + rc = f_sqlite3_open(dbPath, &db); + jenv->ReleaseStringUTFChars(jDb, dbPath); + if (rc != SQLITE_OK) { + asprintf(&errorMsg, "Can't open database: %s\n", f_sqlite3_errmsg(db)); + LOG("Error in SQLiteBridge: %s\n", errorMsg); + JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", errorMsg); + free(errorMsg); + } else { + jCursor = sqliteInternalCall(jenv, db, jQuery, jParams, jQueryRes); + } + f_sqlite3_close(db); + return jCursor; +} + +extern "C" NS_EXPORT jobject JNICALL +Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCallWithDb(JNIEnv* jenv, jclass, + jlong jDb, + jstring jQuery, + jobjectArray jParams, + jlongArray jQueryRes) +{ + JNI_Setup(jenv); + + jobject jCursor = NULL; + sqlite3 *db = (sqlite3*)jDb; + jCursor = sqliteInternalCall(jenv, db, jQuery, jParams, jQueryRes); + return jCursor; +} + +extern "C" NS_EXPORT jlong JNICALL +Java_org_mozilla_gecko_sqlite_SQLiteBridge_openDatabase(JNIEnv* jenv, jclass, + jstring jDb) +{ + JNI_Setup(jenv); + + int rc; + const char* dbPath; + sqlite3 *db; + char* errorMsg; + + dbPath = jenv->GetStringUTFChars(jDb, NULL); + rc = f_sqlite3_open(dbPath, &db); + jenv->ReleaseStringUTFChars(jDb, dbPath); + if (rc != SQLITE_OK) { + asprintf(&errorMsg, "Can't open database: %s\n", f_sqlite3_errmsg(db)); + LOG("Error in SQLiteBridge: %s\n", errorMsg); + JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", errorMsg); + free(errorMsg); + } + return (jlong)db; +} + +extern "C" NS_EXPORT void JNICALL +Java_org_mozilla_gecko_sqlite_SQLiteBridge_closeDatabase(JNIEnv* jenv, jclass, + jlong jDb) +{ + JNI_Setup(jenv); + + sqlite3 *db = (sqlite3*)jDb; + f_sqlite3_close(db); +} + +static jobject +sqliteInternalCall(JNIEnv* jenv, + sqlite3 *db, + jstring jQuery, + jobjectArray jParams, + jlongArray jQueryRes) +{ + JNI_Setup(jenv); + jobject jCursor = NULL; char* errorMsg; jsize numPars = 0; - const char* queryStr; - queryStr = jenv->GetStringUTFChars(jQuery, NULL); - - const char* dbPath; - dbPath = jenv->GetStringUTFChars(jDb, NULL); - const char *pzTail; sqlite3_stmt *ppStmt; - sqlite3 *db; int rc; - rc = f_sqlite3_open(dbPath, &db); - jenv->ReleaseStringUTFChars(jDb, dbPath); - if (rc != SQLITE_OK) { - asprintf(&errorMsg, "Can't open database: %s\n", f_sqlite3_errmsg(db)); - goto error_close; - } + const char* queryStr; + queryStr = jenv->GetStringUTFChars(jQuery, NULL); rc = f_sqlite3_prepare_v2(db, queryStr, -1, &ppStmt, &pzTail); if (rc != SQLITE_OK || ppStmt == NULL) { asprintf(&errorMsg, "Can't prepare statement: %s\n", f_sqlite3_errmsg(db)); goto error_close; } jenv->ReleaseStringUTFChars(jQuery, queryStr); @@ -348,18 +415,16 @@ Java_org_mozilla_gecko_sqlite_SQLiteBrid } rc = f_sqlite3_finalize(ppStmt); if (rc != SQLITE_OK) { asprintf(&errorMsg, "Can't finalize statement: %s\n", f_sqlite3_errmsg(db)); goto error_close; } - f_sqlite3_close(db); return jCursor; error_close: - f_sqlite3_close(db); LOG("Error in SQLiteBridge: %s\n", errorMsg); JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", errorMsg); free(errorMsg); return jCursor; }
--- a/mozglue/android/SQLiteBridge.h +++ b/mozglue/android/SQLiteBridge.h @@ -35,16 +35,17 @@ * ***** END LICENSE BLOCK ***** */ #ifndef SQLiteBridge_h #define SQLiteBridge_h #include "sqlite3.h" void setup_sqlite_functions(void *sqlite_handle); +static jobject sqliteInternalCall(JNIEnv* jenv, sqlite3 *db, jstring jQuery, jobjectArray jParams, jlongArray jQueryRes); #define SQLITE_WRAPPER(name, return_type, args...) \ typedef return_type (*name ## _t)(args); \ extern name ## _t f_ ## name; SQLITE_WRAPPER(sqlite3_open, int, const char*, sqlite3**) SQLITE_WRAPPER(sqlite3_errmsg, const char*, sqlite3*) SQLITE_WRAPPER(sqlite3_prepare_v2, int, sqlite3*, const char*, int, sqlite3_stmt**, const char**)