Bug 760956 - Part 5: use BrowserProvider TopSites query instead of TopSitesCursorWrapper r=rnewman
authorAndrzej Hunt <ahunt@mozilla.com>
Thu, 25 Feb 2016 16:54:50 -0800
changeset 286233 86d110d3d0eb17bfbaa3f8d4a7287466621ad710
parent 286232 613f1eb88443821b3a7c3787d14e1f0238e4a4d0
child 286234 94b25f1233ddb1df2975a39e02ee8637846ba25b
push id72696
push usercbook@mozilla.com
push dateTue, 01 Mar 2016 14:25:42 +0000
treeherdermozilla-inbound@0f47155c48a1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrnewman
bugs760956
milestone47.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 760956 - Part 5: use BrowserProvider TopSites query instead of TopSitesCursorWrapper r=rnewman This means we now have only one open cursor for the topsites query, instead of 2 real cursors (and one MatrixCursor). We still need a MergeCursor and MatrixCursor to supply blank tiles, this will disappear as soon as the user has sufficient history items to fill the suggested sites grid. MozReview-Commit-ID: LnJaSMIDM2O
mobile/android/base/java/org/mozilla/gecko/db/BrowserDB.java
mobile/android/base/java/org/mozilla/gecko/db/LocalBrowserDB.java
mobile/android/base/java/org/mozilla/gecko/db/StubBrowserDB.java
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserDB.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserDB.java
@@ -76,19 +76,20 @@ public interface BrowserDB {
      * @return a cursor over top sites (high-ranking bookmarks and history).
      * Can return <code>null</code>.
      */
     public abstract Cursor getTopSites(ContentResolver cr, int limit);
 
     /**
      * @return a cursor over top sites (high-ranking bookmarks and history).
      * Can return <code>null</code>.
-     * Returns no more than <code>maxLimit</code> results.
+     * Returns no more than <code>limit</code> results.
+     * Suggested sites will be limited to being within the first <code>suggestedRangeLimit</code> results.
      */
-    public abstract Cursor getTopSites(ContentResolver cr, int minLimit, int maxLimit);
+    public abstract Cursor getTopSites(ContentResolver cr, int suggestedRangeLimit, int limit);
 
     public abstract void updateVisitedHistory(ContentResolver cr, String uri);
 
     public abstract void updateHistoryTitle(ContentResolver cr, String uri, String title);
 
     /**
      * Can return <code>null</code>.
      */
--- a/mobile/android/base/java/org/mozilla/gecko/db/LocalBrowserDB.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/LocalBrowserDB.java
@@ -27,32 +27,35 @@ import org.mozilla.gecko.annotation.Robo
 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.ExpirePriority;
 import org.mozilla.gecko.db.BrowserContract.Favicons;
 import org.mozilla.gecko.db.BrowserContract.History;
 import org.mozilla.gecko.db.BrowserContract.SyncColumns;
 import org.mozilla.gecko.db.BrowserContract.Thumbnails;
+import org.mozilla.gecko.db.BrowserContract.TopSites;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
 import org.mozilla.gecko.favicons.decoders.LoadFaviconResult;
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.Restrictions;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.util.GeckoJarReader;
 import org.mozilla.gecko.util.StringUtils;
 
 import android.content.ContentProviderOperation;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.database.CursorWrapper;
+import android.database.MatrixCursor;
+import android.database.MergeCursor;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.drawable.BitmapDrawable;
 import android.net.Uri;
 import android.text.TextUtils;
 import android.util.Log;
 import org.mozilla.gecko.util.IOUtils;
 
@@ -90,16 +93,17 @@ public class LocalBrowserDB implements B
     private final Uri mBookmarksUriWithProfile;
     private final Uri mParentsUriWithProfile;
     private final Uri mHistoryUriWithProfile;
     private final Uri mHistoryExpireUriWithProfile;
     private final Uri mCombinedUriWithProfile;
     private final Uri mUpdateHistoryUriWithProfile;
     private final Uri mFaviconsUriWithProfile;
     private final Uri mThumbnailsUriWithProfile;
+    private final Uri mTopSitesUriWithProfile;
     private final Uri mSearchHistoryUri;
 
     private LocalSearches searches;
     private LocalTabsAccessor tabsAccessor;
     private LocalURLMetadata urlMetadata;
     private LocalReadingListAccessor readingListAccessor;
     private LocalUrlAnnotations urlAnnotations;
 
@@ -116,16 +120,17 @@ public class LocalBrowserDB implements B
         mFolderIdMap = new HashMap<String, Long>();
 
         mBookmarksUriWithProfile = DBUtils.appendProfile(profile, Bookmarks.CONTENT_URI);
         mParentsUriWithProfile = DBUtils.appendProfile(profile, Bookmarks.PARENTS_CONTENT_URI);
         mHistoryUriWithProfile = DBUtils.appendProfile(profile, History.CONTENT_URI);
         mHistoryExpireUriWithProfile = DBUtils.appendProfile(profile, History.CONTENT_OLD_URI);
         mCombinedUriWithProfile = DBUtils.appendProfile(profile, Combined.CONTENT_URI);
         mFaviconsUriWithProfile = DBUtils.appendProfile(profile, Favicons.CONTENT_URI);
+        mTopSitesUriWithProfile = DBUtils.appendProfile(profile, TopSites.CONTENT_URI);
         mThumbnailsUriWithProfile = DBUtils.appendProfile(profile, Thumbnails.CONTENT_URI);
 
         mSearchHistoryUri = BrowserContract.SearchHistory.CONTENT_URI;
 
         mUpdateHistoryUriWithProfile =
                 mHistoryUriWithProfile.buildUpon()
                                       .appendQueryParameter(BrowserContract.PARAM_INCREMENT_VISITS, "true")
                                       .appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true")
@@ -1682,32 +1687,54 @@ public class LocalBrowserDB implements B
                 url = StringUtils.decodeUserEnteredUrl(url);
             }
 
             urls.add(url);
         } while (c.moveToNext());
     }
 
     @Override
-    public Cursor getTopSites(ContentResolver cr, int minLimit, int maxLimit) {
-        // Note this is not a single query anymore, but actually returns a mixture
-        // of two queries, one for topSites and one for pinned sites.
-        Cursor pinnedSites = getPinnedSites(cr, minLimit);
-
-        int pinnedCount = pinnedSites.getCount();
-        Cursor topSites = getTopSites(cr, maxLimit - pinnedCount);
-        int topCount = topSites.getCount();
+    public Cursor getTopSites(ContentResolver cr, int suggestedRangeLimit, int limit) {
+        final Uri uri = mTopSitesUriWithProfile.buildUpon()
+                .appendQueryParameter(BrowserContract.PARAM_LIMIT,
+                        String.valueOf(limit))
+                .appendQueryParameter(BrowserContract.PARAM_SUGGESTEDSITES_LIMIT,
+                        String.valueOf(suggestedRangeLimit))
+                .build();
 
-        Cursor suggestedSites = null;
-        if (mSuggestedSites != null) {
-            final int count = minLimit - pinnedCount - topCount;
-            if (count > 0) {
-                final List<String> excludeUrls = new ArrayList<String>(pinnedCount + topCount);
-                appendUrlsFromCursor(excludeUrls, pinnedSites);
-                appendUrlsFromCursor(excludeUrls, topSites);
+        Cursor topSitesCursor = cr.query(uri,
+                                         new String[] { Combined._ID,
+                                                 Combined.URL,
+                                                 Combined.TITLE,
+                                                 Combined.BOOKMARK_ID,
+                                                 Combined.HISTORY_ID },
+                                         null,
+                                         null,
+                                         null);
 
-                suggestedSites = mSuggestedSites.get(count, excludeUrls);
-            }
+        // It's possible that we will retrieve fewer sites than are required to fill the top-sites panel - in this case
+        // we need to add "blank" tiles. It's much easier to add these here (as opposed to SQL), since we don't care
+        // about their ordering (they go after all the other sites), but we do care about their number (and calculating
+        // that inside out topsites SQL query would be difficult given the other processing we're already doing there).
+        final int blanksRequired = suggestedRangeLimit - topSitesCursor.getCount();
+
+        if (blanksRequired < 0) {
+            return topSitesCursor;
         }
 
-        return new TopSitesCursorWrapper(pinnedSites, topSites, suggestedSites, minLimit);
+        MatrixCursor blanksCursor = new MatrixCursor(new String[] {
+                Bookmarks._ID,
+                Bookmarks.URL,
+                Bookmarks.TITLE,
+                Bookmarks.TYPE});
+
+        for (int i = 0; i < blanksRequired; i++) {
+            final MatrixCursor.RowBuilder rb = blanksCursor.newRow();
+            rb.add(-1);
+            rb.add("");
+            rb.add("");
+            rb.add(TopSites.TYPE_BLANK);
+        }
+
+        return new MergeCursor(new Cursor[] {topSitesCursor, blanksCursor});
+
     }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/db/StubBrowserDB.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/StubBrowserDB.java
@@ -389,17 +389,17 @@ public class StubBrowserDB implements Br
     public String getSuggestedImageUrlForUrl(String url) {
         return null;
     }
 
     public int getSuggestedBackgroundColorForUrl(String url) {
         return 0;
     }
 
-    public Cursor getTopSites(ContentResolver cr, int minLimit, int maxLimit) {
+    public Cursor getTopSites(ContentResolver cr, int suggestedRangeLimit, int limit) {
         return null;
     }
 
     public static Factory getFactory() {
         return new Factory() {
             @Override
             public BrowserDB get(String profileName, File profileDir) {
                 return new StubBrowserDB(profileName);