From 822a6bc976f8f357effe4440b7c11642033a5ef1 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Wed, 25 Apr 2012 17:24:48 -0400 Subject: [PATCH] Bug 741224 - Move database unlock function to DBUtils (r=blassey) --- .../android/base/db/BrowserProvider.java.in | 43 +++++-------------- mobile/android/base/db/DBUtils.java | 28 ++++++++++++ 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/mobile/android/base/db/BrowserProvider.java.in b/mobile/android/base/db/BrowserProvider.java.in index a2f908b5732..1292080721d 100644 --- a/mobile/android/base/db/BrowserProvider.java.in +++ b/mobile/android/base/db/BrowserProvider.java.in @@ -21,7 +21,6 @@ import java.util.Random; import java.util.regex.Pattern; import java.util.regex.Matcher; -import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoBackgroundThread; import org.mozilla.gecko.GeckoProfile; import org.mozilla.gecko.R; @@ -947,35 +946,6 @@ public class BrowserProvider extends ContentProvider { } } - private void ensureDatabaseIsNotLocked(DatabaseHelper dbHelper, String profile, boolean isTest) { - SQLiteDatabase db = dbHelper.getWritableDatabase(); - - // The returned writable database is read-only, this probably means that the - // database is permanently locked due to a crash or a non-clean quit in Fennec. - // We can assume it's safe to forcefully unlock the database file in this case - // as all database access happens through this content provider (see bug 741718). - if (db.isReadOnly()) { - debug("Database is in read-only mode, trying to forcefully unlock the database file"); - - // Close read-only connection, we don't want to use it - dbHelper.close(); - - // When running inside a test or on Android releases older than 8, - // the returned database path is just filename, not the full path. - // We need to full path when unlocking the database. - String databasePath = getDatabasePath(profile, false); - if (isTest || Build.VERSION.SDK_INT <= 8) { - databasePath = mContext.getDatabasePath(databasePath).getAbsolutePath(); - } - - // Forcefully unlock the database file - GeckoAppShell.unlockDatabaseFile(databasePath); - - // TODO: maybe check if the connection is still read-only and let the - // user know that the device needs rebooting? - } - } - private DatabaseHelper getDatabaseHelperForProfile(String profile, boolean isTest) { // Each profile has a separate browser.db database. The target // profile is provided using a URI query argument in each request @@ -992,10 +962,19 @@ public class BrowserProvider extends ContentProvider { if (dbHelper != null) { return dbHelper; } - dbHelper = new DatabaseHelper(getContext(), getDatabasePath(profile, isTest)); + + String databasePath = getDatabasePath(profile, isTest); + dbHelper = new DatabaseHelper(getContext(), databasePath); mDatabasePerProfile.put(profile, dbHelper); - ensureDatabaseIsNotLocked(dbHelper, profile, isTest); + // When running inside a test or on Android releases older than 8, + // the returned database path is just filename, not the full path. + // We need the full path when unlocking the database. + if (isTest || Build.VERSION.SDK_INT <= 8) { + databasePath = mContext.getDatabasePath(databasePath).getAbsolutePath(); + } + + DBUtils.ensureDatabaseIsNotLocked(dbHelper, databasePath); } debug("Created database helper for profile: " + profile); diff --git a/mobile/android/base/db/DBUtils.java b/mobile/android/base/db/DBUtils.java index 593adbd14cf..ddf47044018 100644 --- a/mobile/android/base/db/DBUtils.java +++ b/mobile/android/base/db/DBUtils.java @@ -4,9 +4,14 @@ package org.mozilla.gecko.db; +import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.sync.Utils; import android.content.ContentValues; +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.os.Build; import android.text.TextUtils; import android.util.Base64; import android.util.Log; @@ -15,6 +20,8 @@ import java.util.UUID; import java.util.Random; public class DBUtils { + private static final String LOGTAG = "GeckoDBUtils"; + public static final String qualifyColumn(String table, String column) { return table + "." + column; } @@ -63,4 +70,25 @@ public class DBUtils { aValues.put(aNewKey, value); } } + + public static void ensureDatabaseIsNotLocked(SQLiteOpenHelper dbHelper, String databasePath) { + SQLiteDatabase db = dbHelper.getWritableDatabase(); + + // The returned writable database is read-only, this probably means that the + // database is permanently locked due to a crash or a non-clean quit in Fennec. + // We can assume it's safe to forcefully unlock the database file in this case + // as all database access happens through this content provider (see bug 741718). + if (db.isReadOnly()) { + // Close read-only connection, we don't want to use it + dbHelper.close(); + + Log.d(LOGTAG, "Database is in read-only mode, trying to forcefully unlock the database file: " + databasePath); + + // Forcefully unlock the database file + GeckoAppShell.unlockDatabaseFile(databasePath); + + // TODO: maybe check if the connection is still read-only and let the + // user know that the device needs rebooting? + } + } }