Bug 1291384 - 2. Convert GeckoProfile.getDB calls to BrowserDB.from calls; r=nalexander
authorJim Chen <nchen@mozilla.com>
Wed, 14 Sep 2016 12:46:50 -0400
changeset 355257 61e6762b20d0fa6f64b61e9ee2fe4adaa9417a20
parent 355256 46f54a6f6aeae31a43ffe2a384aa26e2c56f778a
child 355258 88a175eed324e053a3ab25bf0bf1704c026a2a6b
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1291384
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1291384 - 2. Convert GeckoProfile.getDB calls to BrowserDB.from calls; r=nalexander Mass convert GeckoProfile.getDB() calls to BrowserDB.from() calls, whether using Context or GeckoProfile.
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
mobile/android/base/java/org/mozilla/gecko/EditBookmarkDialog.java
mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
mobile/android/base/java/org/mozilla/gecko/GlobalHistory.java
mobile/android/base/java/org/mozilla/gecko/MemoryMonitor.java
mobile/android/base/java/org/mozilla/gecko/Tab.java
mobile/android/base/java/org/mozilla/gecko/Tabs.java
mobile/android/base/java/org/mozilla/gecko/db/BrowserDB.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/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/HomeFragment.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/home/activitystream/ActivityStream.java
mobile/android/base/java/org/mozilla/gecko/icons/loader/LegacyLoader.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/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/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -722,17 +722,17 @@ public class BrowserApp extends GeckoApp
         final Distribution distribution = Distribution.init(getApplicationContext());
         distribution.addOnDistributionReadyCallback(
                 new DistributionStoreCallback(getApplicationContext(), profile.getName()));
 
         mSearchEngineManager = new SearchEngineManager(this, distribution);
 
         // Init suggested sites engine in BrowserDB.
         final SuggestedSites suggestedSites = new SuggestedSites(appContext, distribution);
-        final BrowserDB db = profile.getDB();
+        final BrowserDB db = BrowserDB.from(profile);
         db.setSuggestedSites(suggestedSites);
 
         JavaAddonManager.getInstance().init(appContext);
         mSharedPreferencesHelper = new SharedPreferencesHelper(appContext);
         mReadingListHelper = new ReadingListHelper(appContext, profile);
         mAccountsHelper = new AccountsHelper(appContext, profile);
 
         initAdjustSDK(this, isInAutomation, mTelemetryCorePingDelegate);
@@ -1501,17 +1501,17 @@ public class BrowserApp extends GeckoApp
     public void onDoorHangerHide() {
         final Animator alphaAnimator = ObjectAnimator.ofFloat(mDoorhangerOverlay, "alpha", 0);
         alphaAnimator.setDuration(200);
 
         alphaAnimator.start();
     }
 
     private void handleClearHistory(final boolean clearSearchHistory) {
-        final BrowserDB db = getProfile().getDB();
+        final BrowserDB db = BrowserDB.from(getProfile());
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 db.clearHistory(getContentResolver(), clearSearchHistory);
             }
         });
     }
 
@@ -1786,17 +1786,17 @@ public class BrowserApp extends GeckoApp
                 // Don't use a transition to settings if we're on a device where that
                 // would look bad.
                 if (HardwareUtils.IS_KINDLE_DEVICE) {
                     overridePendingTransition(0, 0);
                 }
                 break;
 
             case "Telemetry:Gather":
-                final BrowserDB db = getProfile().getDB();
+                final BrowserDB db = BrowserDB.from(getProfile());
                 final ContentResolver cr = getContentResolver();
                 Telemetry.addToHistogram("PLACES_PAGES_COUNT", db.getCount(cr, "history"));
                 Telemetry.addToHistogram("FENNEC_BOOKMARKS_COUNT", db.getCount(cr, "bookmarks"));
                 Telemetry.addToHistogram("BROWSER_IS_USER_DEFAULT", (isDefaultBrowser(Intent.ACTION_VIEW) ? 1 : 0));
                 Telemetry.addToHistogram("FENNEC_CUSTOM_HOMEPAGE", (TextUtils.isEmpty(getHomepage()) ? 0 : 1));
                 final SharedPreferences prefs = GeckoSharedPrefs.forProfile(getContext());
                 final boolean hasCustomHomepanels =
                         prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY) || prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY_OLD);
@@ -2499,17 +2499,17 @@ public class BrowserApp extends GeckoApp
         if (!StringUtils.isSearchQuery(url, true)) {
             Tabs.getInstance().loadUrl(url, Tabs.LOADURL_USER_ENTERED);
             Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.ACTIONBAR, "user");
             return;
         }
 
         // Otherwise, check for a bookmark keyword.
         final SharedPreferences sharedPrefs = GeckoSharedPrefs.forProfile(this);
-        final BrowserDB db = getProfile().getDB();
+        final BrowserDB db = BrowserDB.from(getProfile());
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 final String keyword;
                 final String keywordSearch;
 
                 final int index = url.indexOf(" ");
                 if (index == -1) {
@@ -2574,17 +2574,17 @@ public class BrowserApp extends GeckoApp
         }
 
         final GeckoProfile profile = getProfile();
         // Don't bother storing search queries in guest mode
         if (profile.inGuestMode()) {
             return;
         }
 
-        final BrowserDB db = profile.getDB();
+        final BrowserDB db = BrowserDB.from(profile);
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 db.getSearches().insert(getContentResolver(), query);
             }
         });
     }
 
--- a/mobile/android/base/java/org/mozilla/gecko/EditBookmarkDialog.java
+++ b/mobile/android/base/java/org/mozilla/gecko/EditBookmarkDialog.java
@@ -137,17 +137,17 @@ public class EditBookmarkDialog {
      *
      * @param url The url of the bookmark to edit. The dialog will look up other information like the id,
      *            current title, or keywords associated with this url. If the url isn't bookmarked, the
      *            dialog will fail silently. If the url is bookmarked multiple times, this will only show
      *            information about the first it finds.
      */
     public void show(final String url) {
         final ContentResolver cr = mContext.getContentResolver();
-        final BrowserDB db = GeckoProfile.get(mContext).getDB();
+        final BrowserDB db = BrowserDB.from(mContext);
         (new UIAsyncTask.WithoutParams<Bookmark>(ThreadUtils.getBackgroundHandler()) {
             @Override
             public Bookmark doInBackground() {
                 final Cursor cursor = db.getBookmarkForUrl(cr, url);
                 if (cursor == null) {
                     return null;
                 }
 
@@ -196,17 +196,17 @@ public class EditBookmarkDialog {
 
         final EditText nameText = ((EditText) editView.findViewById(R.id.edit_bookmark_name));
         final EditText locationText = ((EditText) editView.findViewById(R.id.edit_bookmark_location));
         final EditText keywordText = ((EditText) editView.findViewById(R.id.edit_bookmark_keyword));
         nameText.setText(title);
         locationText.setText(url);
         keywordText.setText(keyword);
 
-        final BrowserDB db = GeckoProfile.get(mContext).getDB();
+        final BrowserDB db = BrowserDB.from(mContext);
         editPrompt.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int whichButton) {
                 (new UIAsyncTask.WithoutParams<Void>(ThreadUtils.getBackgroundHandler()) {
                     @Override
                     public Void doInBackground() {
                         String newUrl = locationText.getText().toString().trim();
                         String newKeyword = keywordText.getText().toString().trim();
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -608,17 +608,17 @@ public abstract class GeckoApp
                               final EventCallback callback) {
         if ("Accessibility:Ready".equals(event)) {
             GeckoAccessibility.updateAccessibilitySettings(this);
 
         } else if ("Bookmark:Insert".equals(event)) {
             final String url = message.getString("url");
             final String title = message.getString("title");
             final Context context = this;
-            final BrowserDB db = getProfile().getDB();
+            final BrowserDB db = BrowserDB.from(getProfile());
             ThreadUtils.postToBackgroundThread(new Runnable() {
                 @Override
                 public void run() {
                     final boolean bookmarkAdded = db.addBookmark(getContentResolver(), title, url);
                     final int resId = bookmarkAdded ? R.string.bookmark_added : R.string.bookmark_already_added;
                     ThreadUtils.postToUiThread(new Runnable() {
                         @Override
                         public void run() {
@@ -1936,17 +1936,17 @@ public abstract class GeckoApp
 
         // Do not allow duplicate items.
         intent.putExtra("duplicate", false);
 
         intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
         getApplicationContext().sendBroadcast(intent);
 
         // Remember interaction
-        final UrlAnnotations urlAnnotations = GeckoProfile.get(getApplicationContext()).getDB().getUrlAnnotations();
+        final UrlAnnotations urlAnnotations = BrowserDB.from(getApplicationContext()).getUrlAnnotations();
         urlAnnotations.insertHomeScreenShortcut(getContentResolver(), aURI, true);
     }
 
     private void processAlertCallback(SafeIntent intent) {
         String alertName = "";
         String alertCookie = "";
         Uri data = intent.getData();
         if (data != null) {
@@ -2827,29 +2827,29 @@ public abstract class GeckoApp
     @Override
     public void checkUriVisited(String uri) {
         GlobalHistory.getInstance().checkUriVisited(uri);
     }
 
     @Override
     public void markUriVisited(final String uri) {
         final Context context = getApplicationContext();
-        final BrowserDB db = GeckoProfile.get(context).getDB();
+        final BrowserDB db = BrowserDB.from(context);
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 GlobalHistory.getInstance().add(context, db, uri);
             }
         });
     }
 
     @Override
     public void setUriTitle(final String uri, final String title) {
         final Context context = getApplicationContext();
-        final BrowserDB db = GeckoProfile.get(context).getDB();
+        final BrowserDB db = BrowserDB.from(context);
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 GlobalHistory.getInstance().update(context.getContentResolver(), db, uri, title);
             }
         });
     }
 
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
@@ -117,17 +117,17 @@ public class GeckoApplication extends Ap
             // Notify Gecko that we are pausing; the cache service will be
             // shutdown, closing the disk cache cleanly. If the android
             // low memory killer subsequently kills us, the disk cache will
             // be left in a consistent state, avoiding costly cleanup and
             // re-creation.
             GeckoThread.onPause();
             mPausedGecko = true;
 
-            final BrowserDB db = GeckoProfile.get(this).getDB();
+            final BrowserDB db = BrowserDB.from(this);
             ThreadUtils.postToBackgroundThread(new Runnable() {
                 @Override
                 public void run() {
                     db.expireHistory(getContentResolver(), BrowserContract.ExpirePriority.NORMAL);
                 }
             });
         }
         GeckoNetworkManager.getInstance().stop();
--- a/mobile/android/base/java/org/mozilla/gecko/GlobalHistory.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GlobalHistory.java
@@ -48,17 +48,17 @@ class GlobalHistory {
     boolean mProcessing; // = false             // whether or not the runnable is queued/working
 
     private class NotifierRunnable implements Runnable {
         private final ContentResolver mContentResolver;
         private final BrowserDB mDB;
 
         public NotifierRunnable(final Context context) {
             mContentResolver = context.getContentResolver();
-            mDB = GeckoProfile.get(context).getDB();
+            mDB = BrowserDB.from(context);
         }
 
         @Override
         public void run() {
             Set<String> visitedSet = mVisitedCache.get();
             if (visitedSet == null) {
                 // The cache was wiped. Repopulate it.
                 Log.w(LOGTAG, "Rebuilding visited link set...");
--- a/mobile/android/base/java/org/mozilla/gecko/MemoryMonitor.java
+++ b/mobile/android/base/java/org/mozilla/gecko/MemoryMonitor.java
@@ -248,17 +248,17 @@ class MemoryMonitor extends BroadcastRec
             // Since this may be called while Fennec is in the background, we don't want to risk accidentally
             // using the wrong context. If the profile we get is a guest profile, use the default profile instead.
             GeckoProfile profile = GeckoProfile.get(mContext);
             if (profile.inGuestMode()) {
                 // If it was the guest profile, switch to the default one.
                 profile = GeckoProfile.get(mContext, GeckoProfile.DEFAULT_PROFILE);
             }
 
-            mDB = profile.getDB();
+            mDB = BrowserDB.from(profile);
         }
 
         @Override
         public void run() {
             // this might get run right on startup, if so wait 10 seconds and try again
             if (!GeckoThread.isRunning()) {
                 ThreadUtils.getBackgroundHandler().postDelayed(this, 10000);
                 return;
--- a/mobile/android/base/java/org/mozilla/gecko/Tab.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tab.java
@@ -119,17 +119,17 @@ public class Tab {
         CERT_ERROR,  // Pages with certificate problems
         BLOCKED,     // Pages blocked for phishing or malware warnings
         NET_ERROR,   // All other types of error
         NONE         // Non error pages
     }
 
     public Tab(Context context, int id, String url, boolean external, int parentId, String title) {
         mAppContext = context.getApplicationContext();
-        mDB = GeckoProfile.get(context).getDB();
+        mDB = BrowserDB.from(context);
         mId = id;
         mUrl = url;
         mBaseDomain = "";
         mUserRequested = "";
         mExternal = external;
         mParentId = parentId;
         mTitle = title == null ? "" : title;
         mSiteIdentity = new SiteIdentity();
--- a/mobile/android/base/java/org/mozilla/gecko/Tabs.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tabs.java
@@ -84,17 +84,17 @@ public class Tabs implements GeckoEventL
 
     private static class PersistTabsRunnable implements Runnable {
         private final BrowserDB db;
         private final Context context;
         private final Iterable<Tab> tabs;
 
         public PersistTabsRunnable(final Context context, Iterable<Tab> tabsInOrder) {
             this.context = context;
-            this.db = GeckoProfile.get(context).getDB();
+            this.db = BrowserDB.from(context);
             this.tabs = tabsInOrder;
         }
 
         @Override
         public void run() {
             try {
                 db.getTabsAccessor().persistLocalTabs(context.getContentResolver(), tabs);
             } catch (SQLiteException e) {
@@ -152,17 +152,17 @@ public class Tabs implements GeckoEventL
         };
 
         // The listener will run on the background thread (see 2nd argument).
         mAccountManager.addOnAccountsUpdatedListener(mAccountListener, ThreadUtils.getBackgroundHandler(), false);
 
         if (mBookmarksContentObserver != null) {
             // It's safe to use the db here since we aren't doing any I/O.
             final GeckoProfile profile = GeckoProfile.get(context);
-            profile.getDB().registerBookmarkObserver(getContentResolver(), mBookmarksContentObserver);
+            BrowserDB.from(profile).registerBookmarkObserver(getContentResolver(), mBookmarksContentObserver);
         }
     }
 
     /**
      * Gets the tab count corresponding to the private state of the selected
      * tab.
      *
      * If the selected tab is a non-private tab, this will return the number of
@@ -202,17 +202,17 @@ public class Tabs implements GeckoEventL
                     for (Tab tab : mOrder) {
                         tab.updateBookmark();
                     }
                 }
             };
 
             // It's safe to use the db here since we aren't doing any I/O.
             final GeckoProfile profile = GeckoProfile.get(mAppContext);
-            profile.getDB().registerBookmarkObserver(getContentResolver(), mBookmarksContentObserver);
+            BrowserDB.from(profile).registerBookmarkObserver(getContentResolver(), mBookmarksContentObserver);
         }
     }
 
     private Tab addTab(int id, String url, boolean external, int parentId, String title, boolean isPrivate, int tabIndex) {
         final Tab tab = isPrivate ? new PrivateTab(mAppContext, id, url, external, parentId, title) :
                                     new Tab(mAppContext, id, url, external, parentId, title);
         synchronized (this) {
             lazyRegisterBookmarkObserver();
@@ -574,17 +574,17 @@ public class Tabs implements GeckoEventL
             }
 
         } catch (Exception e) {
             Log.w(LOGTAG, "handleMessage threw for " + event, e);
         }
     }
 
     public void refreshThumbnails() {
-        final BrowserDB db = GeckoProfile.get(mAppContext).getDB();
+        final BrowserDB db = BrowserDB.from(mAppContext);
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 for (final Tab tab : mOrder) {
                     if (tab.getThumbnail() == null) {
                         tab.loadThumbnailFromDB(db);
                     }
                 }
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserDB.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserDB.java
@@ -21,17 +21,17 @@ import android.content.Context;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.graphics.drawable.BitmapDrawable;
 import android.support.v4.content.CursorLoader;
 
 /**
  * Interface for interactions with all databases. If you want an instance
  * that implements this, you should go through GeckoProfile. E.g.,
- * <code>GeckoProfile.get(context).getDB()</code>.
+ * <code>BrowserDB.from(context)</code>.
  */
 public abstract class BrowserDB {
     public static enum FilterFlags {
         EXCLUDE_PINNED_SITES
     }
 
     public abstract Searches getSearches();
     public abstract TabsAccessor getTabsAccessor();
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserProvider.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserProvider.java
@@ -853,17 +853,18 @@ public class BrowserProvider extends Sha
         c.setNotificationUri(getContext().getContentResolver(),
                 BrowserContract.AUTHORITY_URI);
 
         if (c.getCount() == limit) {
             return c;
         }
 
         // If we don't have enough data: get suggested sites too
-        final SuggestedSites suggestedSites = GeckoProfile.get(getContext(), uri.getQueryParameter(BrowserContract.PARAM_PROFILE)).getDB().getSuggestedSites();
+        final SuggestedSites suggestedSites = BrowserDB.from(GeckoProfile.get(
+                getContext(), uri.getQueryParameter(BrowserContract.PARAM_PROFILE))).getSuggestedSites();
 
         final Cursor suggestedSitesCursor = suggestedSites.get(limit - c.getCount());
 
         return new MergeCursor(new Cursor[]{
                 c,
                 suggestedSitesCursor
         });
     }
@@ -942,17 +943,18 @@ public class BrowserProvider extends Sha
                 "(" + Combined.URL + " NOT LIKE ?)";
 
         final String[] ignoreForTopSitesArgs = new String[] {
                 AboutPages.URL_FILTER
         };
 
         // Stuff the suggested sites into SQL: this allows us to filter pinned and topsites out of the suggested
         // sites list as part of the final query (as opposed to walking cursors in java)
-        final SuggestedSites suggestedSites = GeckoProfile.get(getContext(), uri.getQueryParameter(BrowserContract.PARAM_PROFILE)).getDB().getSuggestedSites();
+        final SuggestedSites suggestedSites = BrowserDB.from(GeckoProfile.get(
+                getContext(), uri.getQueryParameter(BrowserContract.PARAM_PROFILE))).getSuggestedSites();
 
         StringBuilder suggestedSitesBuilder = new StringBuilder();
         // We could access the underlying data here, however SuggestedSites also performs filtering on the suggested
         // sites list, which means we'd need to process the lists within SuggestedSites in any case. If we're doing
         // that processing, there is little real between us using a MatrixCursor, or a Map (or List) instead of the
         // MatrixCursor.
         final Cursor suggestedSitesCursor = suggestedSites.get(suggestedGridLimit);
 
--- a/mobile/android/base/java/org/mozilla/gecko/delegates/ScreenshotDelegate.java
+++ b/mobile/android/base/java/org/mozilla/gecko/delegates/ScreenshotDelegate.java
@@ -15,16 +15,17 @@ import org.mozilla.gecko.BrowserApp;
 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;
+import org.mozilla.gecko.db.BrowserDB;
 
 import java.lang.ref.WeakReference;
 
 /**
  * Delegate for observing screenshots being taken.
  */
 public class ScreenshotDelegate extends BrowserAppDelegateWithReference implements ScreenshotObserver.OnScreenshotListener {
     private static final String LOGTAG = "GeckoScreenshotDelegate";
@@ -53,17 +54,17 @@ public class ScreenshotDelegate extends 
             return;
         }
 
         final Activity activity = getBrowserApp();
         if (activity == null) {
             return;
         }
 
-        GeckoProfile.get(activity).getDB().getUrlAnnotations().insertScreenshot(
+        BrowserDB.from(activity).getUrlAnnotations().insertScreenshot(
                 activity.getContentResolver(), selectedTab.getURL(), screenshotPath);
 
         SnackbarBuilder.builder(activity)
                 .message(R.string.screenshot_added_to_bookmarks)
                 .duration(Snackbar.LENGTH_SHORT)
                 .buildAndShow();
     }
 
--- a/mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/feeds/FeedService.java
@@ -59,17 +59,17 @@ public class FeedService extends IntentS
     }
 
     private BrowserDB browserDB;
 
     @Override
     public void onCreate() {
         super.onCreate();
 
-        browserDB = GeckoProfile.get(this).getDB();
+        browserDB = BrowserDB.from(this);
     }
 
     @Override
     protected void onHandleIntent(Intent intent) {
         try {
             if (intent == null) {
                 return;
             }
--- a/mobile/android/base/java/org/mozilla/gecko/home/BookmarkFolderView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/BookmarkFolderView.java
@@ -102,17 +102,17 @@ public class BookmarkFolderView extends 
         @Override
         protected Integer doInBackground() {
             final TextView textView = mTextViewReference.get();
 
             if (textView == null) {
                 return null;
             }
 
-            final BrowserDB db = GeckoProfile.get(textView.getContext()).getDB();
+            final BrowserDB db = BrowserDB.from(textView.getContext());
             return db.getBookmarkCountForFolder(textView.getContext().getContentResolver(), mFolderID);
         }
 
         @Override
         protected void onPostExecute(Integer count) {
             final TextView textView = mTextViewReference.get();
 
             if (textView == null) {
--- a/mobile/android/base/java/org/mozilla/gecko/home/BookmarksPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/BookmarksPanel.java
@@ -216,17 +216,17 @@ public class BookmarksPanel extends Home
                  new FolderInfo(Bookmarks.FIXED_ROOT_ID, context.getResources().getString(R.string.bookmarks_title)),
                  RefreshType.CHILD);
         }
 
         public BookmarksLoader(Context context, FolderInfo folderInfo, RefreshType refreshType) {
             super(context);
             mFolderInfo = folderInfo;
             mRefreshType = refreshType;
-            mDB = GeckoProfile.get(context).getDB();
+            mDB = BrowserDB.from(context);
         }
 
         @Override
         public Cursor loadCursor() {
             final boolean isRootFolder = mFolderInfo.id == BrowserContract.Bookmarks.FIXED_ROOT_ID;
 
             final ContentResolver contentResolver = getContext().getContentResolver();
 
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryPanel.java
@@ -291,44 +291,44 @@ public class CombinedHistoryPanel extend
 
         public RemoteTabsCursorLoader(Context context) {
             super(context);
             mProfile = GeckoProfile.get(context);
         }
 
         @Override
         public Cursor loadCursor() {
-            return mProfile.getDB().getTabsAccessor().getRemoteTabsCursor(getContext());
+            return BrowserDB.from(mProfile).getTabsAccessor().getRemoteTabsCursor(getContext());
         }
     }
 
     private static class HistoryCursorLoader extends SimpleCursorLoader {
         // Max number of history results
         public static final int HISTORY_LIMIT = 100;
         private final BrowserDB mDB;
 
         public HistoryCursorLoader(Context context) {
             super(context);
-            mDB = GeckoProfile.get(context).getDB();
+            mDB = BrowserDB.from(context);
         }
 
         @Override
         public Cursor loadCursor() {
             final ContentResolver cr = getContext().getContentResolver();
             return mDB.getRecentHistory(cr, HISTORY_LIMIT);
         }
     }
 
     private class CursorLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
         private BrowserDB mDB;    // Pseudo-final: set in onCreateLoader.
 
         @Override
         public Loader<Cursor> onCreateLoader(int id, Bundle args) {
             if (mDB == null) {
-                mDB = GeckoProfile.get(getActivity()).getDB();
+                mDB = BrowserDB.from(getActivity());
             }
 
             switch (id) {
                 case LOADER_ID_HISTORY:
                     return new HistoryCursorLoader(getContext());
                 case LOADER_ID_REMOTE:
                     return new RemoteTabsCursorLoader(getContext());
                 default:
--- a/mobile/android/base/java/org/mozilla/gecko/home/HomeFragment.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/HomeFragment.java
@@ -393,17 +393,17 @@ public abstract class HomeFragment exten
          */
         public RemoveItemByUrlTask(Context context, String url, RemoveItemType type, int position) {
             super(ThreadUtils.getBackgroundHandler());
 
             mContext = context;
             mUrl = url;
             mType = type;
             mPosition = position;
-            mDB = GeckoProfile.get(context).getDB();
+            mDB = BrowserDB.from(context);
         }
 
         @Override
         public Void doInBackground() {
             ContentResolver cr = mContext.getContentResolver();
 
             if (mPosition > -1) {
                 mDB.unpinSite(cr, mPosition);
--- a/mobile/android/base/java/org/mozilla/gecko/home/SearchLoader.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/SearchLoader.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.EnumSet;
 
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.BrowserDB.FilterFlags;
 
 import android.content.Context;
 import android.database.Cursor;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.support.v4.app.LoaderManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
@@ -93,17 +94,17 @@ class SearchLoader {
             mSearchTerm = searchTerm;
             mFlags = flags;
             mProfile = GeckoProfile.get(context);
         }
 
         @Override
         public Cursor loadCursor() {
             final long start = SystemClock.uptimeMillis();
-            final Cursor cursor = mProfile.getDB().filter(getContext().getContentResolver(), mSearchTerm, SEARCH_LIMIT, mFlags);
+            final Cursor cursor = BrowserDB.from(mProfile).filter(getContext().getContentResolver(), mSearchTerm, SEARCH_LIMIT, mFlags);
             final long end = SystemClock.uptimeMillis();
             final long took = end - start;
             Telemetry.addToHistogram(TELEMETRY_HISTOGRAM_LOAD_CURSOR, (int) Math.min(took, Integer.MAX_VALUE));
             return cursor;
         }
 
         public String getSearchTerm() {
             return mSearchTerm;
--- a/mobile/android/base/java/org/mozilla/gecko/home/TopSitesPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/TopSitesPanel.java
@@ -371,17 +371,17 @@ public class TopSitesPanel extends HomeF
 
         if (!(menuInfo instanceof TopSitesGridContextMenuInfo)) {
             return false;
         }
 
         TopSitesGridContextMenuInfo info = (TopSitesGridContextMenuInfo) menuInfo;
 
         final int itemId = item.getItemId();
-        final BrowserDB db = GeckoProfile.get(getActivity()).getDB();
+        final BrowserDB db = BrowserDB.from(getActivity());
 
         if (itemId == R.id.top_sites_pin) {
             final String url = info.url;
             final String title = info.title;
             final int position = info.position;
             final Context context = getActivity().getApplicationContext();
 
             ThreadUtils.postToBackgroundThread(new Runnable() {
@@ -460,17 +460,17 @@ public class TopSitesPanel extends HomeF
                 dialog.show(manager, TAG_PIN_SITE);
             }
         }
 
         @Override
         public void onSiteSelected(final String url, final String title) {
             final int position = mPosition;
             final Context context = getActivity().getApplicationContext();
-            final BrowserDB db = GeckoProfile.get(getActivity()).getDB();
+            final BrowserDB db = BrowserDB.from(getActivity());
             ThreadUtils.postToBackgroundThread(new Runnable() {
                 @Override
                 public void run() {
                     db.pinSite(context.getContentResolver(), url, title, position);
                 }
             });
         }
     }
@@ -494,17 +494,17 @@ public class TopSitesPanel extends HomeF
         private static final int SEARCH_LIMIT = 30;
         private static final String TELEMETRY_HISTOGRAM_LOAD_CURSOR = "FENNEC_TOPSITES_LOADER_TIME_MS";
         private final BrowserDB mDB;
         private final int mMaxGridEntries;
 
         public TopSitesLoader(Context context) {
             super(context);
             mMaxGridEntries = context.getResources().getInteger(R.integer.number_of_top_sites);
-            mDB = GeckoProfile.get(context).getDB();
+            mDB = BrowserDB.from(context);
         }
 
         @Override
         public Cursor loadCursor() {
             final long start = SystemClock.uptimeMillis();
             final Cursor cursor = mDB.getTopSites(getContext().getContentResolver(), mMaxGridEntries, SEARCH_LIMIT);
             final long end = SystemClock.uptimeMillis();
             final long took = end - start;
@@ -559,17 +559,17 @@ public class TopSitesPanel extends HomeF
     public class TopSitesGridAdapter extends CursorAdapter {
         private final BrowserDB mDB;
         // Cache to store the thumbnails.
         // Ensure that this is only accessed from the UI thread.
         private Map<String, ThumbnailInfo> mThumbnailInfos;
 
         public TopSitesGridAdapter(Context context, Cursor cursor) {
             super(context, cursor, 0);
-            mDB = GeckoProfile.get(context).getDB();
+            mDB = BrowserDB.from(context);
         }
 
         @Override
         public int getCount() {
             return Math.min(mMaxGridEntries, super.getCount());
         }
 
         @Override
@@ -706,17 +706,17 @@ public class TopSitesPanel extends HomeF
             final ArrayList<String> urls = new ArrayList<String>();
             int i = 1;
             do {
                 final String url = c.getString(col);
 
                 // Only try to fetch thumbnails for non-empty URLs that
                 // don't have an associated suggested image URL.
                 final GeckoProfile profile = GeckoProfile.get(getActivity());
-                if (TextUtils.isEmpty(url) || profile.getDB().hasSuggestedImageUrl(url)) {
+                if (TextUtils.isEmpty(url) || BrowserDB.from(profile).hasSuggestedImageUrl(url)) {
                     continue;
                 }
 
                 urls.add(url);
             } while (i++ < mMaxGridEntries && c.moveToNext());
 
             if (urls.isEmpty()) {
                 // Short-circuit empty results to the UI.
@@ -793,17 +793,17 @@ public class TopSitesPanel extends HomeF
             tempColumns.add(TILE_IMAGE_URL_COLUMN);
             tempColumns.add(TILE_COLOR_COLUMN);
             COLUMNS = Collections.unmodifiableList(tempColumns);
         }
 
         public ThumbnailsLoader(Context context, ArrayList<String> urls) {
             super(context);
             mUrls = urls;
-            mDB = GeckoProfile.get(context).getDB();
+            mDB = BrowserDB.from(context);
         }
 
         @Override
         public Map<String, ThumbnailInfo> loadInBackground() {
             final Map<String, ThumbnailInfo> thumbnails = new HashMap<String, ThumbnailInfo>();
             if (mUrls == null || mUrls.size() == 0) {
                 return thumbnails;
             }
--- a/mobile/android/base/java/org/mozilla/gecko/home/activitystream/ActivityStream.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/activitystream/ActivityStream.java
@@ -11,16 +11,17 @@ import android.support.v4.app.LoaderMana
 import android.support.v4.content.Loader;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.util.AttributeSet;
 import android.widget.FrameLayout;
 
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.home.HomePager;
 import org.mozilla.gecko.home.SimpleCursorLoader;
 import org.mozilla.gecko.home.activitystream.topsites.TopSitesPagerAdapter;
 
 public class ActivityStream extends FrameLayout {
     private final StreamRecyclerAdapter adapter;
 
     private static final int LOADER_ID_HIGHLIGHTS = 0;
@@ -54,24 +55,22 @@ public class ActivityStream extends Fram
     public void unload() {
         adapter.swapHighlightsCursor(null);
         adapter.swapTopSitesCursor(null);
     }
 
     private class CursorLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
         @Override
         public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+            final Context context = getContext();
             if (id == LOADER_ID_HIGHLIGHTS) {
-                final Context context = getContext();
-                return GeckoProfile.get(context)
-                        .getDB()
-                        .getHighlights(context, 10);
+                return BrowserDB.from(context).getHighlights(context, 10);
             } else if (id == LOADER_ID_TOPSITES) {
-                return GeckoProfile.get(getContext()).getDB().getActivityStreamTopSites(getContext(),
-                        TopSitesPagerAdapter.TOTAL_ITEMS);
+                return BrowserDB.from(context).getActivityStreamTopSites(
+                        context, TopSitesPagerAdapter.TOTAL_ITEMS);
             } else {
                 throw new IllegalArgumentException("Can't handle loader id " + id);
             }
         }
 
         @Override
         public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
             if (loader.getId() == LOADER_ID_HIGHLIGHTS) {
--- a/mobile/android/base/java/org/mozilla/gecko/icons/loader/LegacyLoader.java
+++ b/mobile/android/base/java/org/mozilla/gecko/icons/loader/LegacyLoader.java
@@ -49,17 +49,17 @@ public class LegacyLoader implements Ico
         }
 
         return IconResponse.create(bitmap);
     }
 
     /* package-private */ Bitmap loadBitmapFromDatabase(IconRequest request) {
         final Context context = request.getContext();
         final ContentResolver contentResolver = context.getContentResolver();
-        final BrowserDB db = GeckoProfile.get(context).getDB();
+        final BrowserDB db = BrowserDB.from(context);
 
         // We ask the database for the favicon URL and ignore the icon URL in the request object:
         // As we are not updating the database anymore the icon might be stored under a different URL.
         final String legacyFaviconUrl = db.getFaviconURLFromPageURL(contentResolver, request.getPageUrl());
         if (legacyFaviconUrl == null) {
             // No URL -> Nothing to load.
             return null;
         }
--- 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
@@ -233,17 +233,17 @@ public class SendTab extends ShareMethod
      * @return A collection of unique remote clients sorted by most recently used.
      */
     protected Collection<RemoteClient> getOtherClients(final TabSender sender) {
         if (sender == null) {
             Log.w(LOGTAG, "No tab sender when fetching other client IDs.");
             return Collections.emptyList();
         }
 
-        final BrowserDB browserDB = GeckoProfile.get(context).getDB();
+        final BrowserDB browserDB = BrowserDB.from(context);
         final TabsAccessor tabsAccessor = browserDB.getTabsAccessor();
         final Cursor remoteTabsCursor = tabsAccessor.getRemoteClientsByRecencyCursor(context);
         try {
             if (remoteTabsCursor.getCount() == 0) {
                 return Collections.emptyList();
             }
             return tabsAccessor.getClientsWithoutTabsByRecencyFromCursor(remoteTabsCursor);
         } finally {
--- a/mobile/android/base/java/org/mozilla/gecko/promotion/AddToHomeScreenPromotion.java
+++ b/mobile/android/base/java/org/mozilla/gecko/promotion/AddToHomeScreenPromotion.java
@@ -204,23 +204,23 @@ public class AddToHomeScreenPromotion ex
             // Let's not ask again for this url - We do not want to be annoying.
             return false;
         }
 
         return true;
     }
 
     protected boolean hasAcceptedOrDeclinedHomeScreenShortcut(Context context, String url) {
-        final UrlAnnotations urlAnnotations = GeckoProfile.get(context).getDB().getUrlAnnotations();
+        final UrlAnnotations urlAnnotations = BrowserDB.from(context).getUrlAnnotations();
         return urlAnnotations.hasAcceptedOrDeclinedHomeScreenShortcut(context.getContentResolver(), url);
     }
 
     protected URLHistory getHistoryForURL(Context context, String url) {
         final GeckoProfile profile = GeckoProfile.get(context);
-        final BrowserDB browserDB = profile.getDB();
+        final BrowserDB browserDB = BrowserDB.from(profile);
 
         Cursor cursor = null;
         try {
             cursor = browserDB.getHistoryForURL(context.getContentResolver(), url);
 
             if (cursor.moveToFirst()) {
                 return new URLHistory(
                     cursor.getInt(cursor.getColumnIndex(BrowserContract.History.VISITS)),
--- a/mobile/android/base/java/org/mozilla/gecko/promotion/HomeScreenPrompt.java
+++ b/mobile/android/base/java/org/mozilla/gecko/promotion/HomeScreenPrompt.java
@@ -19,16 +19,17 @@ import android.widget.ImageView;
 import android.widget.TextView;
 
 import org.mozilla.gecko.GeckoAppShell;
 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.BrowserDB;
 import org.mozilla.gecko.db.UrlAnnotations;
 import org.mozilla.gecko.icons.IconCallback;
 import org.mozilla.gecko.icons.IconResponse;
 import org.mozilla.gecko.icons.Icons;
 import org.mozilla.gecko.Experiments;
 import org.mozilla.gecko.util.ThreadUtils;
 
 /**
@@ -170,17 +171,17 @@ public class HomeScreenPrompt extends Lo
 
     /**
      * Remember that the user rejected creating a home screen shortcut for this URL.
      */
     private void rememberRejection() {
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
-                final UrlAnnotations urlAnnotations = GeckoProfile.get(HomeScreenPrompt.this).getDB().getUrlAnnotations();
+                final UrlAnnotations urlAnnotations = BrowserDB.from(HomeScreenPrompt.this).getUrlAnnotations();
                 urlAnnotations.insertHomeScreenShortcut(getContentResolver(), url, false);
             }
         });
     }
 
     private void slideOut() {
         if (isAnimating) {
             return;
--- a/mobile/android/base/java/org/mozilla/gecko/push/PushService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/push/PushService.java
@@ -16,16 +16,17 @@ import org.json.JSONObject;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
 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.db.BrowserDB;
 import org.mozilla.gecko.fxa.FxAccountPushHandler;
 import org.mozilla.gecko.gcm.GcmTokenClient;
 import org.mozilla.gecko.push.autopush.AutopushClientException;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import java.io.File;
@@ -399,17 +400,17 @@ public class PushService implements Bund
                     return;
                 }
                 final String prePath = message.getString("prePath");
                 if (prePath == null) {
                     callback.sendError("prePath must not be null in " + event);
                     return;
                 }
                 // We're on a background thread, so we can be synchronous.
-                final long millis = geckoProfile.getDB().getPrePathLastVisitedTimeMilliseconds(
+                final long millis = BrowserDB.from(geckoProfile).getPrePathLastVisitedTimeMilliseconds(
                         context.getContentResolver(), prePath);
                 callback.sendSuccess(millis);
                 return;
             }
         } catch (GcmTokenClient.NeedsGooglePlayServicesException e) {
             // TODO: improve this.  Can we find a point where the user is *definitely* interacting
             // with the WebPush?  Perhaps we can show a dialog when interacting with the Push
             // permissions, and then be more aggressive showing this notification when we have
--- a/mobile/android/base/java/org/mozilla/gecko/reader/ReadingListHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/reader/ReadingListHelper.java
@@ -28,17 +28,17 @@ import java.util.concurrent.ExecutionExc
 public final class ReadingListHelper implements NativeEventListener {
     private static final String LOGTAG = "GeckoReadingListHelper";
 
     protected final Context context;
     private final BrowserDB db;
 
     public ReadingListHelper(Context context, GeckoProfile profile) {
         this.context = context;
-        this.db = profile.getDB();
+        this.db = BrowserDB.from(profile);
 
         EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener) this,
             "Reader:FaviconRequest", "Reader:AddedToCache");
     }
 
     public void uninit() {
         EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener) this,
             "Reader:FaviconRequest", "Reader:AddedToCache");
--- a/mobile/android/base/java/org/mozilla/gecko/reader/SavedReaderViewHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/reader/SavedReaderViewHelper.java
@@ -8,16 +8,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.GeckoProfile;
 import org.mozilla.gecko.annotation.RobocopTarget;
+import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.UrlAnnotations;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.Iterator;
 
 /**
@@ -140,33 +141,33 @@ public class SavedReaderViewHelper {
             Log.w(LOG_TAG, "Item insertion failed:", e);
             // This should never happen, absent any errors in our own implementation
             throw new IllegalStateException("Failure inserting into SavedReaderViewHelper json");
         }
 
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
-                UrlAnnotations annotations = GeckoProfile.get(mContext).getDB().getUrlAnnotations();
+                UrlAnnotations annotations = BrowserDB.from(mContext).getUrlAnnotations();
                 annotations.insertReaderViewUrl(mContext.getContentResolver(), pageURL);
 
                 commit();
             }
         });
     }
 
     protected synchronized void remove(@NonNull final String pageURL) {
         assertItemsLoaded();
 
         mItems.remove(pageURL);
 
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
-                UrlAnnotations annotations = GeckoProfile.get(mContext).getDB().getUrlAnnotations();
+                UrlAnnotations annotations = BrowserDB.from(mContext).getUrlAnnotations();
                 annotations.deleteReaderViewUrl(mContext.getContentResolver(), pageURL);
 
                 commit();
             }
         });
     }
 
     @RobocopTarget
--- a/mobile/android/base/java/org/mozilla/gecko/widget/ActivityChooserModel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/ActivityChooserModel.java
@@ -1308,17 +1308,17 @@ public class ActivityChooserModel extend
      */
     private boolean hasOtherSyncClients() {
         // ClientsDatabaseAccessor returns stale data (bug 1145896) so we work around this by
         // checking if we have accounts set up - if not, we can't have any clients.
         if (!FirefoxAccounts.firefoxAccountsExist(mContext)) {
             return false;
         }
 
-        final BrowserDB browserDB = GeckoProfile.get(mContext).getDB();
+        final BrowserDB browserDB = BrowserDB.from(mContext);
         final TabsAccessor tabsAccessor = browserDB.getTabsAccessor();
         final Cursor remoteClientsCursor = tabsAccessor
                 .getRemoteClientsByRecencyCursor(mContext);
         if (remoteClientsCursor == null) {
             return false;
         }
 
         try {
--- 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,16 +1,17 @@
 /* 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.GeckoProfile;
 import org.mozilla.gecko.db.BrowserContract;
+import org.mozilla.gecko.db.BrowserDB;
 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;
 import android.content.Context;
 import android.database.Cursor;
@@ -32,22 +33,22 @@ public class TestTopSites extends Activi
     }
 
     @Override
     public void setUp() {
         mContext = getInstrumentation().getTargetContext();
         mSuggestedSites = new SuggestedSites(mContext);
 
         // By default we're using StubBrowserDB which has no suggested sites available.
-        GeckoProfile.get(mContext, Constants.DEFAULT_PROFILE).getDB().setSuggestedSites(mSuggestedSites);
+        BrowserDB.from(GeckoProfile.get(mContext, Constants.DEFAULT_PROFILE)).setSuggestedSites(mSuggestedSites);
     }
 
     @Override
     public void tearDown() {
-        GeckoProfile.get(mContext, Constants.DEFAULT_PROFILE).getDB().setSuggestedSites(null);
+        BrowserDB.from(GeckoProfile.get(mContext, Constants.DEFAULT_PROFILE)).setSuggestedSites(null);
     }
 
     public void testGetTopSites() {
         final int SUGGESTED_LIMIT = 6;
         final int TOTAL_LIMIT = 50;
 
         ContentResolver cr = mContext.getContentResolver();
 
--- 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
@@ -160,11 +160,11 @@ class DatabaseHelper {
 
             return browserData;
         } finally {
             cursor.close();
         }
     }
 
     protected BrowserDB getProfileDB() {
-        return GeckoProfile.get(mActivity).getDB();
+        return BrowserDB.from(mActivity);
     }
 }
--- 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
@@ -9,16 +9,17 @@ 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.db.BrowserContract;
 import org.mozilla.gecko.db.BrowserContract.UrlAnnotations.SyncStatus;
+import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.URLMetadata;
 import org.mozilla.gecko.db.URLMetadataTable;
 
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderResult;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.OperationApplicationException;
@@ -1486,17 +1487,17 @@ public class testBrowserProvider extends
         }
 
         private void testInsertionViaUrlAnnotations() throws Exception {
             final String url = "http://hello.org";
             final String key = "toTheUniverse";
             final String value = "42a";
             final long timeBeforeCreation = System.currentTimeMillis();
 
-            getTestProfile().getDB().getUrlAnnotations().insertAnnotation(mResolver, url, key, value);
+            BrowserDB.from(getTestProfile()).getUrlAnnotations().insertAnnotation(mResolver, url, key, value);
 
             final Cursor c = getUrlAnnotationByUrl(url);
             try {
                 mAsserter.is(c.moveToFirst(), true, "Inserted url annotation found");
                 assertKeyValueSync(c, key, value);
                 mAsserter.is(true, c.getLong(c.getColumnIndex(BrowserContract.UrlAnnotations.DATE_CREATED)) >= timeBeforeCreation,
                         "Inserted url annotation has date created greater than or equal to time saved before insertion");
                 mAsserter.is(true, c.getLong(c.getColumnIndex(BrowserContract.UrlAnnotations.DATE_MODIFIED)) >= timeBeforeCreation,
@@ -1554,17 +1555,17 @@ public class testBrowserProvider extends
             final String touchIcon = "http://hello.org/touchIcon.png";
 
             final Map<String, Object> data = new HashMap<>();
             data.put(URLMetadataTable.URL_COLUMN, url2);
             data.put(URLMetadataTable.TILE_IMAGE_URL_COLUMN, tileImage);
             data.put(URLMetadataTable.TILE_COLOR_COLUMN, tileColor);
             data.put(URLMetadataTable.TOUCH_ICON_COLUMN, touchIcon);
 
-            getTestProfile().getDB().getURLMetadata().save(mResolver, data);
+            BrowserDB.from(getTestProfile()).getURLMetadata().save(mResolver, data);
 
             final Cursor c = getUrlMetadataByUrl(url2);
             try {
                 mAsserter.is(c.moveToFirst(), true, "URL metadata inserted via UrlMetadata not found");
             } finally {
                 c.close();
             }
         }
@@ -1572,17 +1573,17 @@ public class testBrowserProvider extends
         private void testRetrievalViaUrlMetadata() {
             // LocalURLMetadata has some caching of results: we need to test that this caching
             // doesn't prevent us from accessing data that might not have been loaded into the cache.
             // We do this by first doing queries with a subset of data, then later querying additional
             // data for a given URL. E.g. even if the first query results in only the requested
             // column being cached, the subsequent query should still retrieve all requested columns.
             // (In this case the URL may be cached but without all data, we need to make sure that
             // this state is correctly handled.)
-            URLMetadata metadata = getTestProfile().getDB().getURLMetadata();
+            URLMetadata metadata = BrowserDB.from(getTestProfile()).getURLMetadata();
 
             Map<String, Map<String, Object>> results;
             Map<String, Object> urlData;
 
             // 1: retrieve just touch Icons for URL 1
             results = metadata.getForURLs(mResolver,
                     Collections.singletonList(url1),
                     Collections.singletonList(URLMetadataTable.TOUCH_ICON_COLUMN));