From c05d87817a26488ea0989f17cae3fac2a2b884b7 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 24 Apr 2012 16:34:03 -0400 Subject: [PATCH] Bug 746444 - Force unlock database file when database is opened in read-only mode (r=blassey) --- .../android/base/db/BrowserProvider.java.in | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/mobile/android/base/db/BrowserProvider.java.in b/mobile/android/base/db/BrowserProvider.java.in index c3cbb1ee04e..a2f908b5732 100644 --- a/mobile/android/base/db/BrowserProvider.java.in +++ b/mobile/android/base/db/BrowserProvider.java.in @@ -21,6 +21,7 @@ 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; @@ -946,6 +947,35 @@ 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 @@ -964,6 +994,8 @@ public class BrowserProvider extends ContentProvider { } dbHelper = new DatabaseHelper(getContext(), getDatabasePath(profile, isTest)); mDatabasePerProfile.put(profile, dbHelper); + + ensureDatabaseIsNotLocked(dbHelper, profile, isTest); } debug("Created database helper for profile: " + profile);