mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 13:25:37 +00:00
Bug 731491 - Rework GeckoProvider. r=rnewman
--HG-- rename : mobile/android/base/db/GeckoProvider.java => mobile/android/base/db/PerProfileContentProvider.java
This commit is contained in:
parent
074c62ae8d
commit
37c3facdcc
@ -172,7 +172,7 @@ FENNEC_JAVA_FILES = \
|
||||
db/BrowserContract.java \
|
||||
db/BrowserProvider.java \
|
||||
db/FormHistoryProvider.java \
|
||||
db/GeckoProvider.java \
|
||||
db/PerProfileContentProvider.java \
|
||||
db/PasswordsProvider.java \
|
||||
db/TabsProvider.java \
|
||||
gfx/Axis.java \
|
||||
|
@ -20,7 +20,7 @@ import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
public class FormHistoryProvider extends GeckoProvider {
|
||||
public class FormHistoryProvider extends PerProfileContentProvider {
|
||||
static final String TABLE_FORM_HISTORY = "moz_formhistory";
|
||||
static final String TABLE_DELETED_FORM_HISTORY = "moz_deleted_formhistory";
|
||||
|
||||
@ -29,8 +29,6 @@ public class FormHistoryProvider extends GeckoProvider {
|
||||
|
||||
private static final UriMatcher URI_MATCHER;
|
||||
|
||||
private static HashMap<String, String> FORM_HISTORY_PROJECTION_MAP;
|
||||
private static HashMap<String, String> DELETED_FORM_HISTORY_PROJECTION_MAP;
|
||||
|
||||
// This should be kept in sync with the db version in toolkit/components/satchel/nsFormHistory.js
|
||||
private static int DB_VERSION = 4;
|
||||
@ -39,23 +37,19 @@ public class FormHistoryProvider extends GeckoProvider {
|
||||
private static final String WHERE_GUID_IS_NULL = BrowserContract.DeletedFormHistory.GUID + " IS NULL";
|
||||
private static final String WHERE_GUID_IS_VALUE = BrowserContract.DeletedFormHistory.GUID + " = ?";
|
||||
|
||||
private static final String LOG_TAG = "FormHistoryProvider";
|
||||
|
||||
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);
|
||||
FORM_HISTORY_PROJECTION_MAP = new HashMap<String, String>();
|
||||
DELETED_FORM_HISTORY_PROJECTION_MAP = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
setLogTag("FormHistoryProvider");
|
||||
setDBName(DB_FILENAME);
|
||||
setDBVersion(DB_VERSION);
|
||||
|
||||
return super.onCreate();
|
||||
public FormHistoryProvider() {
|
||||
super(LOG_TAG);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
final int match = URI_MATCHER.match(uri);
|
||||
@ -93,8 +87,9 @@ public class FormHistoryProvider extends GeckoProvider {
|
||||
|
||||
@Override
|
||||
public String getSortOrder(Uri uri, String aRequested) {
|
||||
if (!TextUtils.isEmpty(aRequested))
|
||||
if (!TextUtils.isEmpty(aRequested)) {
|
||||
return aRequested;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -152,4 +147,14 @@ public class FormHistoryProvider extends GeckoProvider {
|
||||
|
||||
@Override
|
||||
public void onPostQuery(Cursor cursor, Uri uri, SQLiteBridge db) { }
|
||||
|
||||
@Override
|
||||
protected String getDBName(){
|
||||
return DB_FILENAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDBVersion(){
|
||||
return DB_VERSION;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
public class PasswordsProvider extends GeckoProvider {
|
||||
public class PasswordsProvider extends PerProfileContentProvider {
|
||||
static final String TABLE_PASSWORDS = "moz_logins";
|
||||
static final String TABLE_DELETED_PASSWORDS = "moz_deleted_logins";
|
||||
|
||||
@ -43,10 +43,11 @@ public class PasswordsProvider extends GeckoProvider {
|
||||
// this should be kept in sync with the version in toolkit/components/passwordmgr/storage-mozStorage.js
|
||||
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 + " = ?";
|
||||
|
||||
private static final String LOG_TAG = "GeckPasswordsProvider";
|
||||
|
||||
static {
|
||||
URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
|
||||
@ -78,12 +79,18 @@ public class PasswordsProvider extends GeckoProvider {
|
||||
System.loadLibrary("mozglue");
|
||||
}
|
||||
|
||||
public PasswordsProvider() {
|
||||
super(LOG_TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
setLogTag("GeckoPasswordsProvider");
|
||||
setDBName(DB_FILENAME);
|
||||
setDBVersion(DB_VERSION);
|
||||
return super.onCreate();
|
||||
protected String getDBName(){
|
||||
return DB_FILENAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDBVersion(){
|
||||
return DB_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -119,8 +126,9 @@ public class PasswordsProvider extends GeckoProvider {
|
||||
|
||||
@Override
|
||||
public String getSortOrder(Uri uri, String aRequested) {
|
||||
if (!TextUtils.isEmpty(aRequested))
|
||||
if (!TextUtils.isEmpty(aRequested)) {
|
||||
return aRequested;
|
||||
}
|
||||
|
||||
final int match = URI_MATCHER.match(uri);
|
||||
switch (match) {
|
||||
@ -206,7 +214,7 @@ public class PasswordsProvider extends GeckoProvider {
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Log.e(getLogTag(), "Error in NSSBridge");
|
||||
Log.e(LOG_TAG, "Error in NSSBridge");
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
return result;
|
||||
|
@ -34,31 +34,31 @@ import android.util.Log;
|
||||
* public abstract void initGecko();
|
||||
*/
|
||||
|
||||
public abstract class GeckoProvider extends ContentProvider {
|
||||
private String mLogTag = "GeckoPasswordsProvider";
|
||||
private String mDBName = "";
|
||||
private int mDBVersion = 0;
|
||||
public abstract class PerProfileContentProvider extends ContentProvider {
|
||||
private HashMap<String, SQLiteBridge> mDatabasePerProfile;
|
||||
protected Context mContext = null;
|
||||
private final String mLogTag;
|
||||
|
||||
protected PerProfileContentProvider(String logTag) {
|
||||
mLogTag = logTag;
|
||||
}
|
||||
|
||||
@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) { }
|
||||
}
|
||||
if (mDatabasePerProfile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mDatabasePerProfile = null;
|
||||
synchronized (this) {
|
||||
for (SQLiteBridge bridge : mDatabasePerProfile.values()){
|
||||
if (bridge != null) {
|
||||
try {
|
||||
bridge.close();
|
||||
} catch (Exception ex) { }
|
||||
}
|
||||
}
|
||||
mDatabasePerProfile = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -66,29 +66,6 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
protected void setLogTag(String aLogTag) {
|
||||
mLogTag = aLogTag;
|
||||
}
|
||||
|
||||
protected String getLogTag() {
|
||||
return mLogTag;
|
||||
}
|
||||
|
||||
protected void setDBName(String aDBName) {
|
||||
mDBName = aDBName;
|
||||
}
|
||||
|
||||
protected String getDBName() {
|
||||
return mDBName;
|
||||
}
|
||||
|
||||
protected void setDBVersion(int aVersion) {
|
||||
mDBVersion = aVersion;
|
||||
}
|
||||
|
||||
protected int getDBVersion() {
|
||||
return mDBVersion;
|
||||
}
|
||||
|
||||
private SQLiteBridge getDB(Context context, final String databasePath) {
|
||||
SQLiteBridge bridge = null;
|
||||
@ -100,11 +77,12 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
GeckoLoader.loadNSSLibs(context, resourcePath);
|
||||
bridge = SQLiteBridge.openDatabase(databasePath, null, 0);
|
||||
int version = bridge.getVersion();
|
||||
dbNeedsSetup = version != mDBVersion;
|
||||
dbNeedsSetup = version != getDBVersion();
|
||||
} catch (SQLiteBridgeException ex) {
|
||||
// close the database
|
||||
if (bridge != null)
|
||||
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
|
||||
@ -126,53 +104,110 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
bridge = null;
|
||||
initGecko();
|
||||
}
|
||||
if (bridge != null)
|
||||
mDatabasePerProfile.put(databasePath, bridge);
|
||||
|
||||
return bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute path of a database file depending on the specified profile and dbName.
|
||||
* @param profile
|
||||
* the profile whose dbPath must be returned
|
||||
* @param dbName
|
||||
* the name of the db file whose absolute path must be returned
|
||||
* @return the absolute path of the db file or <code>null</code> if it was not possible to retrieve a valid path
|
||||
*
|
||||
*/
|
||||
private String getDatabasePathForProfile(String profile, String dbName) {
|
||||
// Depends on the vagaries of GeckoProfile.get, so null check for safety.
|
||||
File profileDir = GeckoProfile.get(mContext, profile).getDir();
|
||||
if (profileDir == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String databasePath = new File(profileDir, dbName).getAbsolutePath();
|
||||
return databasePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a SQLiteBridge object according to the specified profile id and to the name of db related to the
|
||||
* current provider instance.
|
||||
* @param profile
|
||||
* the id of the profile to be used to retrieve the related SQLiteBridge
|
||||
* @return the <code>SQLiteBridge</code> related to the specified profile id or <code>null</code> if it was
|
||||
* not possible to retrieve a valid SQLiteBridge
|
||||
*/
|
||||
private SQLiteBridge getDatabaseForProfile(String profile) {
|
||||
if (TextUtils.isEmpty(profile)) {
|
||||
profile = GeckoProfile.get(mContext).getName();
|
||||
Log.d(mLogTag, "No profile provided, using '" + profile + "'");
|
||||
}
|
||||
|
||||
final String dbName = getDBName();
|
||||
String mapKey = profile + "/" + dbName;
|
||||
|
||||
SQLiteBridge db = null;
|
||||
synchronized (this) {
|
||||
String dbPath = getDatabasePathForProfile(profile);
|
||||
db = mDatabasePerProfile.get(dbPath);
|
||||
if (db == null) {
|
||||
db = getDB(mContext, dbPath);
|
||||
}
|
||||
}
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
private SQLiteBridge getDatabaseForPath(String profilePath) {
|
||||
SQLiteBridge db = null;
|
||||
synchronized (this) {
|
||||
db = mDatabasePerProfile.get(profilePath);
|
||||
if (db == null) {
|
||||
File profileDir = new File(profilePath, mDBName);
|
||||
db = getDB(mContext, profileDir.getPath());
|
||||
db = mDatabasePerProfile.get(mapKey);
|
||||
if (db != null) {
|
||||
return db;
|
||||
}
|
||||
final String dbPath = getDatabasePathForProfile(profile, dbName);
|
||||
if (dbPath == null) {
|
||||
Log.e(mLogTag, "Failed to get a valid db path for profile '" + profile + "'' dbName '" + dbName + "'");
|
||||
return null;
|
||||
}
|
||||
db = getDB(mContext, dbPath);
|
||||
if (db != null) {
|
||||
mDatabasePerProfile.put(mapKey, db);
|
||||
}
|
||||
}
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
private String getDatabasePathForProfile(String profile) {
|
||||
File profileDir = GeckoProfile.get(mContext, profile).getDir();
|
||||
if (profileDir == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String databasePath = new File(profileDir, mDBName).getAbsolutePath();
|
||||
return databasePath;
|
||||
/**
|
||||
* Returns a SQLiteBridge object according to the specified profile path and to the name of db related to the
|
||||
* current provider instance.
|
||||
* @param profilePath
|
||||
* the profilePath to be used to retrieve the related SQLiteBridge
|
||||
* @return the <code>SQLiteBridge</code> related to the specified profile path or <code>null</code> if it was
|
||||
* not possible to retrieve a valid <code>SQLiteBridge</code>
|
||||
*/
|
||||
private SQLiteBridge getDatabaseForProfilePath(String profilePath) {
|
||||
File profileDir = new File(profilePath, getDBName());
|
||||
final String dbPath = profileDir.getPath();
|
||||
return getDatabaseForDBPath(dbPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a SQLiteBridge object according to the specified file path.
|
||||
* @param dbPath
|
||||
* the path of the file to be used to retrieve the related SQLiteBridge
|
||||
* @return the <code>SQLiteBridge</code> related to the specified file path or <code>null</code> if it was
|
||||
* not possible to retrieve a valid <code>SQLiteBridge</code>
|
||||
*
|
||||
*/
|
||||
private SQLiteBridge getDatabaseForDBPath(String dbPath) {
|
||||
SQLiteBridge db = null;
|
||||
synchronized (this) {
|
||||
db = mDatabasePerProfile.get(dbPath);
|
||||
if (db != null) {
|
||||
return db;
|
||||
}
|
||||
db = getDB(mContext, dbPath);
|
||||
if (db != null) {
|
||||
mDatabasePerProfile.put(dbPath, db);
|
||||
}
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a SQLiteBridge object to be used to perform operations on the given <code>Uri</code>.
|
||||
* @param uri
|
||||
* the <code>Uri</code> to be used to retrieve the related SQLiteBridge
|
||||
* @return a <code>SQLiteBridge</code> object to be used on the given uri or <code>null</code> if it was
|
||||
* not possible to retrieve a valid <code>SQLiteBridge</code>
|
||||
*
|
||||
*/
|
||||
private SQLiteBridge getDatabase(Uri uri) {
|
||||
String profile = null;
|
||||
String profilePath = null;
|
||||
@ -181,8 +216,9 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
profilePath = uri.getQueryParameter(BrowserContract.PARAM_PROFILE_PATH);
|
||||
|
||||
// Testing will specify the absolute profile path
|
||||
if (profilePath != null)
|
||||
return getDatabaseForPath(profilePath);
|
||||
if (profilePath != null) {
|
||||
return getDatabaseForProfilePath(profilePath);
|
||||
}
|
||||
return getDatabaseForProfile(profile);
|
||||
}
|
||||
|
||||
@ -204,8 +240,9 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
int deleted = 0;
|
||||
final SQLiteBridge db = getDatabase(uri);
|
||||
if (db == null)
|
||||
if (db == null) {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
try {
|
||||
deleted = db.delete(getTable(uri), selection, selectionArgs);
|
||||
@ -225,8 +262,9 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
// 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)
|
||||
if (db == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
setupDefaults(uri, values);
|
||||
|
||||
@ -262,8 +300,9 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
// 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)
|
||||
if (db == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long id = -1;
|
||||
int rowsAdded = 0;
|
||||
@ -287,8 +326,9 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
if (rowsAdded > 0)
|
||||
if (rowsAdded > 0) {
|
||||
mContext.getContentResolver().notifyChange(uri, null);
|
||||
}
|
||||
|
||||
return rowsAdded;
|
||||
}
|
||||
@ -302,8 +342,9 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
// 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)
|
||||
if (db == null) {
|
||||
return updated;
|
||||
}
|
||||
|
||||
onPreUpdate(values, uri, db);
|
||||
|
||||
@ -326,8 +367,9 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
// 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)
|
||||
if (db == null) {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
sortOrder = getSortOrder(uri, sortOrder);
|
||||
|
||||
@ -342,17 +384,21 @@ public abstract class GeckoProvider extends ContentProvider {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
public abstract String getTable(Uri uri);
|
||||
protected abstract String getDBName();
|
||||
|
||||
public abstract String getSortOrder(Uri uri, String aRequested);
|
||||
protected abstract int getDBVersion();
|
||||
|
||||
public abstract void setupDefaults(Uri uri, ContentValues values);
|
||||
protected abstract String getTable(Uri uri);
|
||||
|
||||
public abstract void initGecko();
|
||||
protected abstract String getSortOrder(Uri uri, String aRequested);
|
||||
|
||||
public abstract void onPreInsert(ContentValues values, Uri uri, SQLiteBridge db);
|
||||
protected abstract void setupDefaults(Uri uri, ContentValues values);
|
||||
|
||||
public abstract void onPreUpdate(ContentValues values, Uri uri, SQLiteBridge db);
|
||||
protected abstract void initGecko();
|
||||
|
||||
public abstract void onPostQuery(Cursor cursor, Uri uri, SQLiteBridge db);
|
||||
protected abstract void onPreInsert(ContentValues values, Uri uri, SQLiteBridge db);
|
||||
|
||||
protected abstract void onPreUpdate(ContentValues values, Uri uri, SQLiteBridge db);
|
||||
|
||||
protected abstract void onPostQuery(Cursor cursor, Uri uri, SQLiteBridge db);
|
||||
}
|
Loading…
Reference in New Issue
Block a user