Bug 1258470 - Part 11b: Inline BrowserDB factory into GeckoApplication.
MozReview-Commit-ID: FRHk2aaDm8I
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
@@ -23,16 +23,17 @@ import org.mozilla.gecko.home.HomePanels
import org.mozilla.gecko.lwt.LightweightTheme;
import org.mozilla.gecko.mdns.MulticastDNSManager;
import org.mozilla.gecko.util.Clipboard;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.ThreadUtils;
import java.io.File;
import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
public class GeckoApplication extends Application
implements ContextGetter {
private static final String LOG_TAG = "GeckoApplication";
private static volatile GeckoApplication instance;
private boolean mInBackground;
@@ -152,34 +153,16 @@ public class GeckoApplication extends Ap
DownloadsIntegration.init();
HomePanelsManager.getInstance().init(context);
// This getInstance call will force initialization of the NotificationHelper, but does nothing with the result
NotificationHelper.getInstance(context).init();
MulticastDNSManager.getInstance(context).init();
- // Make sure that all browser-ish applications default to the real LocalBrowserDB.
- // GeckoView consumers use their own Application class, so this doesn't affect them.
- //
- // We need to do this before any access to the profile; it controls
- // which database class is used.
- //
- // As such, this needs to occur before the GeckoView in GeckoApp is inflated -- i.e., in the
- // GeckoApp constructor or earlier -- because GeckoView implicitly accesses the profile. This is earlier!
- GeckoProfile.setBrowserDBFactory(new BrowserDB.Factory() {
- @Override
- public BrowserDB get(String profileName, File profileDir) {
- // Note that we don't use the profile directory -- we
- // send operations to the ContentProvider, which does
- // its own thing.
- return new LocalBrowserDB(profileName);
- }
- });
-
GeckoService.register();
super.onCreate();
}
public void onDelayedStartup() {
if (AppConstants.MOZ_ANDROID_GCM) {
// TODO: only run in main process.
@@ -213,13 +196,23 @@ public class GeckoApplication extends Ap
public LightweightTheme getLightweightTheme() {
return mLightweightTheme;
}
public void prepareLightweightTheme() {
mLightweightTheme = new LightweightTheme(this);
}
+ private static final ConcurrentHashMap<String, BrowserDB> sDBCache =
+ new ConcurrentHashMap<>(/* capacity */ 4, /* load factor */ 0.75f, /* concurrency */ 2);
+
@RobocopTarget
public static BrowserDB getDB(GeckoProfile profile) {
- return profile.getDB();
+ final String profileName = profile.getName();
+ BrowserDB db = sDBCache.get(profileName);
+ if (db != null) {
+ return db;
+ }
+ db = new LocalBrowserDB(profileName);
+ sDBCache.put(profileName, db);
+ return db;
}
}
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoProfile.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoProfile.java
@@ -13,18 +13,16 @@ import android.text.TextUtils;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.GeckoProfileDirectories.NoMozillaDirectoryException;
import org.mozilla.gecko.GeckoProfileDirectories.NoSuchProfileException;
import org.mozilla.gecko.annotation.RobocopTarget;
-import org.mozilla.gecko.db.BrowserDB;
-import org.mozilla.gecko.db.StubBrowserDB;
import org.mozilla.gecko.util.FileUtils;
import org.mozilla.gecko.util.INIParser;
import org.mozilla.gecko.util.INISection;
import org.mozilla.gecko.util.IntentUtils;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
@@ -81,18 +79,16 @@ public final class GeckoProfile {
new ConcurrentHashMap<String, GeckoProfile>(
/* capacity */ 4, /* load factor */ 0.75f, /* concurrency */ 2);
private static String sDefaultProfileName;
private final String mName;
private final File mMozillaDir;
private final Context mApplicationContext;
- private final BrowserDB mDB;
-
/**
* Access to this member should be synchronized to avoid
* races during creation -- particularly between getDir and GeckoView#init.
*
* Not final because this is lazily computed.
*/
private File mProfileDir;
@@ -153,17 +149,17 @@ public final class GeckoProfile {
} catch (final NoMozillaDirectoryException e) {
// If this failed, we're screwed.
Log.wtf(LOGTAG, "Unable to get default profile name.", e);
throw new RuntimeException(e);
}
}
public static GeckoProfile get(Context context) {
- return get(context, null, null, null);
+ return get(context, null, (File) null);
}
public static GeckoProfile get(Context context, String profileName) {
if (profileName != null) {
GeckoProfile profile = sProfileCache.get(profileName);
if (profile != null)
return profile;
}
@@ -177,41 +173,20 @@ public final class GeckoProfile {
dir = new File(profilePath);
if (!dir.exists() || !dir.isDirectory()) {
Log.w(LOGTAG, "requested profile directory missing: " + profilePath);
}
}
return get(context, profileName, dir);
}
- // Extension hook.
- private static volatile BrowserDB.Factory sDBFactory;
- public static void setBrowserDBFactory(BrowserDB.Factory factory) {
- sDBFactory = factory;
- }
-
+ // Note that the profile cache respects only the profile name!
+ // If the directory changes, the returned GeckoProfile instance will be mutated.
@RobocopTarget
public static GeckoProfile get(Context context, String profileName, File profileDir) {
- if (sDBFactory == null) {
- // We do this so that GeckoView consumers don't need to know anything about BrowserDB.
- // It's a bit of a broken abstraction, but very tightly coupled, so we work around it
- // for now. We can't just have GeckoView set this, because then it would collide in
- // Fennec's use of GeckoView.
- // We should never see this in Fennec itself, because GeckoApplication sets the factory
- // in onCreate.
- Log.d(LOGTAG, "Defaulting to StubBrowserDB.");
- sDBFactory = StubBrowserDB.getFactory();
- }
- return GeckoProfile.get(context, profileName, profileDir, sDBFactory);
- }
-
- // Note that the profile cache respects only the profile name!
- // If the directory changes, the returned GeckoProfile instance will be mutated.
- // If the factory differs, it will be *ignored*.
- public static GeckoProfile get(Context context, String profileName, File profileDir, BrowserDB.Factory dbFactory) {
if (context == null) {
throw new IllegalArgumentException("context must be non-null");
}
// Null name? | Null dir? | Returned profile
// ------------------------------------------
// Yes | Yes | Active profile or default profile.
// No | Yes | Profile with specified name at default dir.
@@ -246,17 +221,17 @@ public final class GeckoProfile {
final boolean init = profileDir != null && profileDir.mkdirs();
// Actually try to look up the profile.
GeckoProfile profile = sProfileCache.get(profileName);
GeckoProfile newProfile = null;
if (profile == null) {
try {
- newProfile = new GeckoProfile(context, profileName, profileDir, dbFactory);
+ newProfile = new GeckoProfile(context, profileName, profileDir);
} catch (NoMozillaDirectoryException e) {
// We're unable to do anything sane here.
throw new RuntimeException(e);
}
profile = sProfileCache.putIfAbsent(profileName, newProfile);
}
@@ -326,53 +301,45 @@ public final class GeckoProfile {
try {
return profileDir.getCanonicalPath().equals(getGuestDir(context).getCanonicalPath());
} catch (final IOException e) {
return false;
}
}
- private GeckoProfile(Context context, String profileName, File profileDir, BrowserDB.Factory dbFactory) throws NoMozillaDirectoryException {
+ private GeckoProfile(Context context, String profileName, File profileDir) throws NoMozillaDirectoryException {
if (profileName == null) {
throw new IllegalArgumentException("Unable to create GeckoProfile for empty profile name.");
} else if (CUSTOM_PROFILE.equals(profileName) && profileDir == null) {
throw new IllegalArgumentException("Custom profile must have a directory");
}
mApplicationContext = context.getApplicationContext();
mName = profileName;
mMozillaDir = GeckoProfileDirectories.getMozillaDirectory(context);
mProfileDir = profileDir;
if (profileDir != null && !profileDir.isDirectory()) {
throw new IllegalArgumentException("Profile directory must exist if specified.");
}
-
- // N.B., mProfileDir can be null at this point.
- mDB = dbFactory.get(profileName, mProfileDir);
}
public static boolean shouldUse(final Context context) {
return GeckoSharedPrefs.forApp(context).getBoolean(GUEST_MODE_PREF, false);
}
public static void enter(final Context context) {
GeckoSharedPrefs.forApp(context).edit().putBoolean(GUEST_MODE_PREF, true).commit();
}
public static void leave(final Context context) {
GeckoSharedPrefs.forApp(context).edit().putBoolean(GUEST_MODE_PREF, false).commit();
}
- @RobocopTarget
- public BrowserDB getDB() {
- return mDB;
- }
-
private void setDir(File dir) {
if (dir != null && dir.exists() && dir.isDirectory()) {
synchronized (this) {
mProfileDir = dir;
mInGuestMode = null;
}
}
}