Bug 1291384 - Part 2: Inline BrowserDB factory into GeckoApplication. r?jchen draft
authorNick Alexander <nalexander@mozilla.com>
Thu, 04 Aug 2016 09:35:33 -0700
changeset 396851 38e83c32e6d88830fa159b54fe8434ab6b1a6e83
parent 396850 787bcdad70c9fc34197198683ecb2535500f0374
child 527313 2cedc1001cc7878cf94ce805c153bf90ff431144
push id25134
push usernalexander@mozilla.com
push dateThu, 04 Aug 2016 19:33:53 +0000
reviewersjchen
bugs1291384
milestone51.0a1
Bug 1291384 - Part 2: Inline BrowserDB factory into GeckoApplication. r?jchen These two patches will be folded together for landing. MozReview-Commit-ID: FRHk2aaDm8I
mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
mobile/android/base/java/org/mozilla/gecko/db/BrowserProvider.java
mobile/android/base/java/org/mozilla/gecko/delegates/ScreenshotDelegate.java
mobile/android/base/java/org/mozilla/gecko/favicons/Favicons.java
mobile/android/base/java/org/mozilla/gecko/favicons/LoadFaviconTask.java
mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
mobile/android/base/java/org/mozilla/gecko/home/BookmarkFolderView.java
mobile/android/base/java/org/mozilla/gecko/home/BookmarksPanel.java
mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryPanel.java
mobile/android/base/java/org/mozilla/gecko/home/SearchLoader.java
mobile/android/base/java/org/mozilla/gecko/home/TopSitesPanel.java
mobile/android/base/java/org/mozilla/gecko/overlays/service/sharemethods/SendTab.java
mobile/android/base/java/org/mozilla/gecko/promotion/AddToHomeScreenPromotion.java
mobile/android/base/java/org/mozilla/gecko/promotion/HomeScreenPrompt.java
mobile/android/base/java/org/mozilla/gecko/push/PushService.java
mobile/android/base/java/org/mozilla/gecko/reader/ReadingListHelper.java
mobile/android/base/java/org/mozilla/gecko/reader/SavedReaderViewHelper.java
mobile/android/base/java/org/mozilla/gecko/widget/ActivityChooserModel.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoProfile.java
mobile/android/tests/background/junit3/src/org/mozilla/gecko/background/db/TestTopSites.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/DatabaseHelper.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserProvider.java
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
@@ -9,30 +9,32 @@ import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.os.SystemClock;
 import android.util.Log;
 
 import com.squareup.leakcanary.LeakCanary;
 import com.squareup.leakcanary.RefWatcher;
 
+import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.LocalBrowserDB;
 import org.mozilla.gecko.dlc.DownloadContentService;
 import org.mozilla.gecko.home.HomePanelsManager;
 import org.mozilla.gecko.lwt.LightweightTheme;
 import org.mozilla.gecko.mdns.MulticastDNSManager;
 import org.mozilla.gecko.notifications.NotificationHelper;
 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;
@@ -157,34 +159,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.
@@ -217,9 +201,24 @@ 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) {
+        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/db/BrowserProvider.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserProvider.java
@@ -7,16 +7,17 @@ package org.mozilla.gecko.db;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.mozilla.gecko.AboutPages;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.db.BrowserContract.Bookmarks;
 import org.mozilla.gecko.db.BrowserContract.Combined;
 import org.mozilla.gecko.db.BrowserContract.FaviconColumns;
 import org.mozilla.gecko.db.BrowserContract.Favicons;
 import org.mozilla.gecko.db.BrowserContract.History;
 import org.mozilla.gecko.db.BrowserContract.Visits;
--- a/mobile/android/base/java/org/mozilla/gecko/delegates/ScreenshotDelegate.java
+++ b/mobile/android/base/java/org/mozilla/gecko/delegates/ScreenshotDelegate.java
@@ -7,16 +7,17 @@ package org.mozilla.gecko.delegates;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.support.design.widget.Snackbar;
 import android.util.Log;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.BrowserApp;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.ScreenshotObserver;
 import org.mozilla.gecko.SnackbarBuilder;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
--- a/mobile/android/base/java/org/mozilla/gecko/favicons/Favicons.java
+++ b/mobile/android/base/java/org/mozilla/gecko/favicons/Favicons.java
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.favicons;
 
 import android.graphics.drawable.Drawable;
 import org.mozilla.gecko.AboutPages;
 import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.URLMetadataTable;
 import org.mozilla.gecko.favicons.cache.FaviconCache;
 import org.mozilla.gecko.util.GeckoJarReader;
--- a/mobile/android/base/java/org/mozilla/gecko/favicons/LoadFaviconTask.java
+++ b/mobile/android/base/java/org/mozilla/gecko/favicons/LoadFaviconTask.java
@@ -8,16 +8,17 @@ import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.text.TextUtils;
 import android.util.Log;
 import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.distribution.PartnerBookmarksProviderProxy;
 import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
 import org.mozilla.gecko.favicons.decoders.LoadFaviconResult;
 import org.mozilla.gecko.util.GeckoJarReader;
 import org.mozilla.gecko.util.IOUtils;
 import org.mozilla.gecko.util.ProxySelector;
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
@@ -12,16 +12,17 @@ import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.support.annotation.Nullable;
 import android.support.v4.net.ConnectivityManagerCompat;
 import android.util.Log;
 
 import com.keepsafe.switchboard.SwitchBoard;
 
 import org.mozilla.gecko.AppConstants;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.feeds.action.FeedAction;
 import org.mozilla.gecko.feeds.action.CheckForUpdatesAction;
 import org.mozilla.gecko.feeds.action.EnrollSubscriptionsAction;
 import org.mozilla.gecko.feeds.action.SetupAlarmsAction;
 import org.mozilla.gecko.feeds.action.SubscribeToFeedAction;
--- a/mobile/android/base/java/org/mozilla/gecko/home/BookmarkFolderView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/BookmarkFolderView.java
@@ -1,15 +1,16 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.home;
 
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.util.UIAsyncTask;
 
 import android.content.Context;
--- a/mobile/android/base/java/org/mozilla/gecko/home/BookmarksPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/BookmarksPanel.java
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.home;
 
 import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserContract.Bookmarks;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.distribution.PartnerBookmarksProviderProxy;
 import org.mozilla.gecko.home.BookmarksListAdapter.FolderInfo;
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryPanel.java
@@ -33,16 +33,17 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.TextView;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.RemoteClientsDialogFragment;
 import org.mozilla.gecko.fxa.FirefoxAccounts;
 import org.mozilla.gecko.fxa.FxAccountConstants;
 import org.mozilla.gecko.fxa.SyncStatusListener;
 import org.mozilla.gecko.home.CombinedHistoryPanel.OnPanelLevelChangeListener.PanelLevel;
 import org.mozilla.gecko.restrictions.Restrictions;
--- a/mobile/android/base/java/org/mozilla/gecko/home/SearchLoader.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/SearchLoader.java
@@ -2,16 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.home;
 
 import java.util.EnumSet;
 
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.db.BrowserDB.FilterFlags;
 
 import android.content.Context;
 import android.database.Cursor;
 import android.os.Bundle;
 import android.os.SystemClock;
--- a/mobile/android/base/java/org/mozilla/gecko/home/TopSitesPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/TopSitesPanel.java
@@ -11,16 +11,17 @@ import static org.mozilla.gecko.db.URLMe
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.db.BrowserContract.Thumbnails;
 import org.mozilla.gecko.db.BrowserContract.TopSites;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.favicons.Favicons;
--- a/mobile/android/base/java/org/mozilla/gecko/overlays/service/sharemethods/SendTab.java
+++ b/mobile/android/base/java/org/mozilla/gecko/overlays/service/sharemethods/SendTab.java
@@ -10,16 +10,17 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.database.Cursor;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
 
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.RemoteClient;
 import org.mozilla.gecko.db.TabsAccessor;
 import org.mozilla.gecko.fxa.FxAccountConstants;
 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
 import org.mozilla.gecko.fxa.login.State;
 import org.mozilla.gecko.overlays.OverlayConstants;
--- a/mobile/android/base/java/org/mozilla/gecko/promotion/AddToHomeScreenPromotion.java
+++ b/mobile/android/base/java/org/mozilla/gecko/promotion/AddToHomeScreenPromotion.java
@@ -13,16 +13,17 @@ import android.support.annotation.CallSu
 import android.util.Log;
 
 import com.keepsafe.switchboard.SwitchBoard;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.AboutPages;
 import org.mozilla.gecko.BrowserApp;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.UrlAnnotations;
 import org.mozilla.gecko.delegates.TabsTrayVisibilityAwareDelegate;
 import org.mozilla.gecko.Experiments;
--- a/mobile/android/base/java/org/mozilla/gecko/promotion/HomeScreenPrompt.java
+++ b/mobile/android/base/java/org/mozilla/gecko/promotion/HomeScreenPrompt.java
@@ -15,16 +15,17 @@ import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Bundle;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 
 import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.Locales;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.db.UrlAnnotations;
 import org.mozilla.gecko.favicons.Favicons;
 import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
--- a/mobile/android/base/java/org/mozilla/gecko/push/PushService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/push/PushService.java
@@ -10,16 +10,17 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.util.Log;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.GeckoService;
 import org.mozilla.gecko.GeckoThread;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.annotation.ReflectionTarget;
 import org.mozilla.gecko.gcm.GcmTokenClient;
 import org.mozilla.gecko.push.autopush.AutopushClientException;
--- a/mobile/android/base/java/org/mozilla/gecko/reader/ReadingListHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/reader/ReadingListHelper.java
@@ -5,16 +5,17 @@
 package org.mozilla.gecko.reader;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import org.mozilla.gecko.AboutPages;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.favicons.Favicons;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.NativeEventListener;
 import org.mozilla.gecko.util.NativeJSObject;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.util.UIAsyncTask;
--- a/mobile/android/base/java/org/mozilla/gecko/reader/SavedReaderViewHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/reader/SavedReaderViewHelper.java
@@ -6,16 +6,17 @@
 package org.mozilla.gecko.reader;
 
 import android.content.Context;
 import android.support.annotation.NonNull;
 import android.util.Log;
 
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.db.UrlAnnotations;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.Iterator;
--- a/mobile/android/base/java/org/mozilla/gecko/widget/ActivityChooserModel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/ActivityChooserModel.java
@@ -19,16 +19,17 @@
  */
 //package android.widget;
 package org.mozilla.gecko.widget;
 
 // Mozilla: New import
 import android.accounts.Account;
 import android.content.pm.PackageManager;
 
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.TabsAccessor;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.fxa.FirefoxAccounts;
 import org.mozilla.gecko.fxa.SyncStatusListener;
 import org.mozilla.gecko.overlays.ui.ShareDialog;
 import org.mozilla.gecko.R;
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoProfile.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoProfile.java
@@ -14,19 +14,17 @@ 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.LocalBrowserDB;
-import org.mozilla.gecko.db.StubBrowserDB;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.gecko.firstrun.FirstrunAnimationContainer;
 import org.mozilla.gecko.preferences.DistroSharedPrefsImport;
 import org.mozilla.gecko.util.FileUtils;
 import org.mozilla.gecko.util.INIParser;
 import org.mozilla.gecko.util.INISection;
 import org.mozilla.gecko.util.IntentUtils;
 
@@ -84,18 +82,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;
 
@@ -156,17 +152,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;
         }
@@ -180,41 +176,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.
@@ -249,17 +224,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);
         }
 
@@ -329,39 +304,31 @@ 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);
-    }
-
-    @RobocopTarget
-    public BrowserDB getDB() {
-        return mDB;
     }
 
     private void setDir(File dir) {
         if (dir != null && dir.exists() && dir.isDirectory()) {
             synchronized (this) {
                 mProfileDir = dir;
                 mInGuestMode = null;
             }
--- a/mobile/android/tests/background/junit3/src/org/mozilla/gecko/background/db/TestTopSites.java
+++ b/mobile/android/tests/background/junit3/src/org/mozilla/gecko/background/db/TestTopSites.java
@@ -1,14 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 package org.mozilla.gecko.background.db;
 
 
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserContract.Combined;
 import org.mozilla.gecko.db.SuggestedSites;
 import org.mozilla.gecko.sync.setup.Constants;
 
 import android.app.Activity;
 import android.content.ContentResolver;
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/DatabaseHelper.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/DatabaseHelper.java
@@ -7,16 +7,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tests;
 
 import java.util.ArrayList;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.Assert;
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.db.BrowserDB;
 
 import android.app.Activity;
 import android.content.ContentResolver;
 import android.database.Cursor;
 import android.net.Uri;
 
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserProvider.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserProvider.java
@@ -7,16 +7,17 @@ package org.mozilla.gecko.tests;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
 
+import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserContract.UrlAnnotations.SyncStatus;
 import org.mozilla.gecko.db.URLMetadata;
 import org.mozilla.gecko.db.URLMetadataTable;
 
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderResult;
 import android.content.ContentUris;