Bug 1080232 - Multiplexing count.(with reviews) r=mcomella draft
authorShubham <shubham2892@gmail.com>
Sat, 22 Oct 2016 19:53:43 -0400
changeset 428311 739c33cd71826b90a7e388c246e69748b5e34f93
parent 428310 60dd82380d43a2b681f50842238f829204486290
child 534715 8c1aba2c2f6dbfac593652259cf8321f1dbae671
push id33289
push userbmo:shubham2892@gmail.com
push dateSat, 22 Oct 2016 23:55:18 +0000
reviewersmcomella
bugs1080232
milestone52.0a1
Bug 1080232 - Multiplexing count.(with reviews) r=mcomella MozReview-Commit-ID: CklXYsVgENI
mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.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/db/LocalBrowserDB.java
mobile/android/base/java/org/mozilla/gecko/db/StubBrowserDB.java
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserContract.java
@@ -309,16 +309,18 @@ public class BrowserContract {
         private Combined() {}
 
         public static final String VIEW_NAME = "combined";
 
         public static final String VIEW_WITH_FAVICONS = "combined_with_favicons";
 
         public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "combined");
 
+        public static final Uri COUNTS_URI = Uri.withAppendedPath(AUTHORITY_URI, "counts");
+
         public static final String BOOKMARK_ID = "bookmark_id";
         public static final String HISTORY_ID = "history_id";
 
         public static final String REMOTE_VISITS_COUNT = "remoteVisitCount";
         public static final String REMOTE_DATE_LAST_VISITED = "remoteDateLastVisited";
 
         public static final String LOCAL_VISITS_COUNT = "localVisitCount";
         public static final String LOCAL_DATE_LAST_VISITED = "localDateLastVisited";
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserDB.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserDB.java
@@ -52,16 +52,18 @@ public abstract class BrowserDB {
 
     /**
      * Invalidate cached data.
      */
     public abstract void invalidate();
 
     public abstract int getCount(ContentResolver cr, String database);
 
+    public abstract Cursor getAllCounts(ContentResolver cr);
+
     /**
      * @return a cursor representing the contents of the DB filtered according to the arguments.
      * Can return <code>null</code>. <code>CursorLoader</code> will handle this correctly.
      */
     public abstract Cursor filter(ContentResolver cr, CharSequence constraint,
                                   int limit, EnumSet<BrowserDB.FilterFlags> flags);
 
     /**
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserProvider.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserProvider.java
@@ -133,16 +133,18 @@ public class BrowserProvider extends Sha
     static final int VISITS = 1100;
 
     static final int METADATA = 1200;
 
     static final int HIGHLIGHTS = 1300;
 
     static final int ACTIVITY_STREAM_BLOCKLIST = 1400;
 
+    static final int COUNTS = 1500;
+
     static final String DEFAULT_BOOKMARKS_SORT_ORDER = Bookmarks.TYPE
             + " ASC, " + Bookmarks.POSITION + " ASC, " + Bookmarks._ID
             + " ASC";
 
     static final String DEFAULT_HISTORY_SORT_ORDER = History.DATE_LAST_VISITED + " DESC";
     static final String DEFAULT_VISITS_SORT_ORDER = Visits.DATE_VISITED + " DESC";
 
     static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
@@ -191,16 +193,18 @@ public class BrowserProvider extends Sha
         map.put(Bookmarks.IS_DELETED, Bookmarks.IS_DELETED);
         BOOKMARKS_PROJECTION_MAP = Collections.unmodifiableMap(map);
 
         // History
         URI_MATCHER.addURI(BrowserContract.AUTHORITY, "history", HISTORY);
         URI_MATCHER.addURI(BrowserContract.AUTHORITY, "history/#", HISTORY_ID);
         URI_MATCHER.addURI(BrowserContract.AUTHORITY, "history/old", HISTORY_OLD);
 
+        URI_MATCHER.addURI(BrowserContract.AUTHORITY, "counts", COUNTS);
+
         map = new HashMap<String, String>();
         map.put(History._ID, History._ID);
         map.put(History.TITLE, History.TITLE);
         map.put(History.URL, History.URL);
         map.put(History.FAVICON, History.FAVICON);
         map.put(History.FAVICON_ID, History.FAVICON_ID);
         map.put(History.FAVICON_URL, History.FAVICON_URL);
         map.put(History.VISITS, History.VISITS);
@@ -1262,18 +1266,41 @@ public class BrowserProvider extends Sha
         // we handle that separately, i.e. before retrieving a readable connection.
         if (match == TOPSITES) {
             if (uri.getBooleanQueryParameter(BrowserContract.PARAM_TOPSITES_DISABLE_PINNED, false)) {
                 return getPlainTopSites(uri);
             } else {
                 return getTopSites(uri);
             }
         }
-
         SQLiteDatabase db = getReadableDatabase(uri);
+        if (match == COUNTS) {
+            String history_table;
+            String bookmark_table;
+            final boolean isFavIconsInProjection = hasFaviconsInProjection(projection);
+            if (isFavIconsInProjection) {
+                history_table = VIEW_HISTORY_WITH_FAVICONS;
+            } else {
+                history_table = TABLE_HISTORY;
+            }
+            if (isFavIconsInProjection) {
+                bookmark_table = VIEW_BOOKMARKS_WITH_FAVICONS;
+            } else if (selection != null && selection.contains(Bookmarks.ANNOTATION_KEY)) {
+                bookmark_table = VIEW_BOOKMARKS_WITH_ANNOTATIONS;
+            } else {
+                bookmark_table = TABLE_BOOKMARKS;
+            }
+            final String query = "SELECT " +
+                    "(SELECT COUNT(" + History._ID + ") FROM " + history_table +
+                    " WHERE " + History.VISITS + " > 0) AS history, " +
+                    "(SELECT COUNT(" + Bookmarks._ID + ") FROM " + bookmark_table +
+                    " WHERE " + Bookmarks.TYPE + " = " + Bookmarks.TYPE_BOOKMARK +
+                    ") AS bookmarks;";
+            return db.rawQuery(query, null);
+        }
 
         SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
         String limit = uri.getQueryParameter(BrowserContract.PARAM_LIMIT);
         String groupBy = null;
 
         switch (match) {
             case BOOKMARKS_FOLDER_ID:
             case BOOKMARKS_ID:
--- a/mobile/android/base/java/org/mozilla/gecko/db/LocalBrowserDB.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/LocalBrowserDB.java
@@ -115,16 +115,17 @@ public class LocalBrowserDB extends Brow
     private final Uri mCombinedUriWithProfile;
     private final Uri mUpdateHistoryUriWithProfile;
     private final Uri mFaviconsUriWithProfile;
     private final Uri mThumbnailsUriWithProfile;
     private final Uri mTopSitesUriWithProfile;
     private final Uri mHighlightsUriWithProfile;
     private final Uri mSearchHistoryUri;
     private final Uri mActivityStreamBlockedUriWithProfile;
+    private final Uri mAllCountsUriWithProfile;
 
     private LocalSearches searches;
     private LocalTabsAccessor tabsAccessor;
     private LocalURLMetadata urlMetadata;
     private LocalUrlAnnotations urlAnnotations;
 
     private static final String[] DEFAULT_BOOKMARK_COLUMNS =
             new String[] { Bookmarks._ID,
@@ -143,16 +144,17 @@ public class LocalBrowserDB extends Brow
         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);
         mHighlightsUriWithProfile = DBUtils.appendProfile(profile, Highlights.CONTENT_URI);
         mThumbnailsUriWithProfile = DBUtils.appendProfile(profile, Thumbnails.CONTENT_URI);
         mActivityStreamBlockedUriWithProfile = DBUtils.appendProfile(profile, ActivityStreamBlocklist.CONTENT_URI);
+        mAllCountsUriWithProfile = DBUtils.appendProfile(profile, Combined.COUNTS_URI);
 
         mSearchHistoryUri = BrowserContract.SearchHistory.CONTENT_URI;
 
         mUpdateHistoryUriWithProfile =
                 mHistoryUriWithProfile.buildUpon()
                                       .appendQueryParameter(BrowserContract.PARAM_INCREMENT_VISITS, "true")
                                       .appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true")
                                       .build();
@@ -630,16 +632,20 @@ public class LocalBrowserDB extends Brow
                 cursor.close();
             }
         }
 
         debug("Got count " + count + " for " + database);
         return count;
     }
 
+    public Cursor getAllCounts(ContentResolver cr) {
+        return cr.query(mAllCountsUriWithProfile, null, null, null, null);
+    }
+
     @Override
     @RobocopTarget
     public Cursor filter(ContentResolver cr, CharSequence constraint, int limit,
                          EnumSet<FilterFlags> flags) {
         String selection = "";
         String[] selectionArgs = null;
 
         if (flags.contains(FilterFlags.EXCLUDE_PINNED_SITES)) {
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/db/StubBrowserDB.java
@@ -0,0 +1,391 @@
+/* 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.db;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.json.JSONObject;
+import org.mozilla.gecko.annotation.RobocopTarget;
+import org.mozilla.gecko.distribution.Distribution;
+import org.mozilla.gecko.favicons.decoders.LoadFaviconResult;
+import org.mozilla.gecko.Tab;
+import org.mozilla.gecko.feeds.subscriptions.FeedSubscription;
+
+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.graphics.drawable.BitmapDrawable;
+
+class StubSearches implements Searches {
+    public StubSearches() {
+    }
+
+    public void insert(ContentResolver cr, String query) {
+    }
+}
+
+class StubURLMetadata implements URLMetadata {
+    public StubURLMetadata() {
+    }
+
+    public Map<String, Object> fromJSON(JSONObject obj) {
+        return new HashMap<String, Object>();
+    }
+
+    public Map<String, Map<String, Object>> getForURLs(final ContentResolver cr,
+                                                       final Collection<String> urls,
+                                                       final List<String> columns) {
+        return new HashMap<String, Map<String, Object>>();
+    }
+
+    public void save(final ContentResolver cr, final Map<String, Object> data) {
+    }
+}
+
+class StubTabsAccessor implements TabsAccessor {
+    public StubTabsAccessor() {
+    }
+
+    @Override
+    public List<RemoteClient> getClientsWithoutTabsByRecencyFromCursor(Cursor cursor) {
+        return new ArrayList<>();
+    }
+
+    @Override
+    public List<RemoteClient> getClientsFromCursor(final Cursor cursor) {
+        return new ArrayList<RemoteClient>();
+    }
+
+    @Override
+    public Cursor getRemoteClientsByRecencyCursor(Context context) {
+        return null;
+    }
+
+    public Cursor getRemoteTabsCursor(Context context) {
+        return null;
+    }
+
+    public Cursor getRemoteTabsCursor(Context context, int limit) {
+        return null;
+    }
+
+    public void getTabs(final Context context, final OnQueryTabsCompleteListener listener) {
+        listener.onQueryTabsComplete(new ArrayList<RemoteClient>());
+    }
+    public void getTabs(final Context context, final int limit, final OnQueryTabsCompleteListener listener) {
+        listener.onQueryTabsComplete(new ArrayList<RemoteClient>());
+    }
+
+    public synchronized void persistLocalTabs(final ContentResolver cr, final Iterable<Tab> tabs) { }
+}
+
+class StubUrlAnnotations implements UrlAnnotations {
+    @Override
+    public void insertAnnotation(ContentResolver cr, String url, String key, String value) {}
+
+    @Override
+    public Cursor getScreenshots(ContentResolver cr) { return null; }
+
+    @Override
+    public void insertScreenshot(ContentResolver cr, String pageUrl, final String screenshotLocation) {}
+
+    @Override
+    public Cursor getFeedSubscriptions(ContentResolver cr) { return null; }
+
+    @Override
+    public Cursor getWebsitesWithFeedUrl(ContentResolver cr) { return null; }
+
+    @Override
+    public void deleteFeedUrl(ContentResolver cr, String websiteUrl) {}
+
+    @Override
+    public boolean hasWebsiteForFeedUrl(ContentResolver cr, String feedUrl) { return false; }
+
+    @Override
+    public void deleteFeedSubscription(ContentResolver cr, FeedSubscription subscription) {}
+
+    @Override
+    public void updateFeedSubscription(ContentResolver cr, FeedSubscription subscription) {}
+
+    @Override
+    public boolean hasFeedSubscription(ContentResolver cr, String feedUrl) { return false; }
+
+    @Override
+    public void insertFeedSubscription(ContentResolver cr, FeedSubscription subscription) {}
+
+    @Override
+    public boolean hasFeedUrlForWebsite(ContentResolver cr, String websiteUrl) { return false; }
+
+    @Override
+    public void insertFeedUrl(ContentResolver cr, String originUrl, String feedUrl) {}
+
+    @Override
+    public void insertReaderViewUrl(ContentResolver cr, String pageURL) {}
+
+    @Override
+    public void deleteReaderViewUrl(ContentResolver cr, String pageURL) {}
+
+    @Override
+    public boolean hasAcceptedOrDeclinedHomeScreenShortcut(ContentResolver cr, String url) { return false; }
+
+    @Override
+    public void insertHomeScreenShortcut(ContentResolver cr, String url, boolean hasCreatedShortCut) {}
+
+    @Override
+    public int getAnnotationCount(ContentResolver cr, BrowserContract.UrlAnnotations.Key key) {
+        return 0;
+    }
+}
+
+/*
+ * This base implementation just stubs all methods. For the
+ * real implementations, see LocalBrowserDB.java.
+ */
+public class StubBrowserDB implements BrowserDB {
+    private final StubSearches searches = new StubSearches();
+    private final StubTabsAccessor tabsAccessor = new StubTabsAccessor();
+    private final StubURLMetadata urlMetadata = new StubURLMetadata();
+    private final StubUrlAnnotations urlAnnotations = new StubUrlAnnotations();
+    private SuggestedSites suggestedSites = null;
+
+    @Override
+    public Searches getSearches() {
+        return searches;
+    }
+
+    @Override
+    public TabsAccessor getTabsAccessor() {
+        return tabsAccessor;
+    }
+
+    @Override
+    public URLMetadata getURLMetadata() {
+        return urlMetadata;
+    }
+
+    @Override
+    public UrlAnnotations getUrlAnnotations() {
+        return urlAnnotations;
+    }
+
+    protected static final Integer FAVICON_ID_NOT_FOUND = Integer.MIN_VALUE;
+
+    public StubBrowserDB(String profile) {
+    }
+
+    public void invalidate() { }
+
+    public int addDefaultBookmarks(Context context, ContentResolver cr, final int offset) {
+        return 0;
+    }
+
+    public int addDistributionBookmarks(ContentResolver cr, Distribution distribution, int offset) {
+        return 0;
+    }
+
+    public int getCount(ContentResolver cr, String database) {
+        return 0;
+    }
+
+    @Override
+    public Cursor getAllCounts(ContentResolver cr) {
+        return null;
+    }
+
+    @RobocopTarget
+    public Cursor filter(ContentResolver cr, CharSequence constraint, int limit,
+                         EnumSet<BrowserDB.FilterFlags> flags) {
+        return null;
+    }
+
+    public void updateVisitedHistory(ContentResolver cr, String uri) {
+    }
+
+    public void updateHistoryTitle(ContentResolver cr, String uri, String title) {
+    }
+
+    @RobocopTarget
+    public Cursor getAllVisitedHistory(ContentResolver cr) {
+        return null;
+    }
+
+    public Cursor getRecentHistory(ContentResolver cr, int limit) {
+        return null;
+    }
+
+    @Override
+    public Cursor getHistoryForURL(ContentResolver cr, String uri) {
+        return null;
+    }
+
+    @Override
+    public Cursor getRecentHistoryBetweenTime(ContentResolver cr, int limit, long time, long end) {
+        return null;
+    }
+
+    @Override
+    public long getPrePathLastVisitedTimeMilliseconds(ContentResolver cr, String prePath) { return 0; }
+
+    public void expireHistory(ContentResolver cr, BrowserContract.ExpirePriority priority) {
+    }
+
+    @RobocopTarget
+    public void removeHistoryEntry(ContentResolver cr, String url) {
+    }
+
+    public void clearHistory(ContentResolver cr, boolean clearSearchHistory) {
+    }
+
+    @RobocopTarget
+    public Cursor getBookmarksInFolder(ContentResolver cr, long folderId) {
+        return null;
+    }
+
+    public int getBookmarkCountForFolder(ContentResolver cr, long folderId) { return 0; }
+
+    @RobocopTarget
+    public boolean isBookmark(ContentResolver cr, String uri) {
+        return false;
+    }
+
+    public String getUrlForKeyword(ContentResolver cr, String keyword) {
+        return null;
+    }
+
+    protected void bumpParents(ContentResolver cr, String param, String value) {
+    }
+
+    @RobocopTarget
+    public boolean addBookmark(ContentResolver cr, String title, String uri) {
+        return false;
+    }
+
+    @RobocopTarget
+    public void removeBookmarksWithURL(ContentResolver cr, String uri) {
+    }
+
+    public void registerBookmarkObserver(ContentResolver cr, ContentObserver observer) {
+    }
+
+    @RobocopTarget
+    public void updateBookmark(ContentResolver cr, int id, String uri, String title, String keyword) {
+    }
+
+    public LoadFaviconResult getFaviconForUrl(ContentResolver cr, String faviconURL) {
+        return null;
+    }
+
+    public String getFaviconURLFromPageURL(ContentResolver cr, String uri) {
+        return null;
+    }
+
+    public void updateFaviconForUrl(ContentResolver cr, String pageUri,
+                                    byte[] encodedFavicon, String faviconUri) {
+    }
+
+    public boolean hideSuggestedSite(String url) {
+        return false;
+    }
+
+    public void updateThumbnailForUrl(ContentResolver cr, String uri,
+                                      BitmapDrawable thumbnail) {
+    }
+
+    @RobocopTarget
+    public byte[] getThumbnailForUrl(ContentResolver cr, String uri) {
+        return null;
+    }
+
+    public Cursor getThumbnailsForUrls(ContentResolver cr, List<String> urls) {
+        return null;
+    }
+
+    @RobocopTarget
+    public void removeThumbnails(ContentResolver cr) {
+    }
+
+    public void updateHistoryInBatch(ContentResolver cr,
+                                     Collection<ContentProviderOperation> operations,
+                                     String url, String title,
+                                     long date, int visits) {
+    }
+
+    public void updateBookmarkInBatch(ContentResolver cr,
+                                      Collection<ContentProviderOperation> operations,
+                                      String url, String title, String guid,
+                                      long parent, long added,
+                                      long modified, long position,
+                                      String keyword, int type) {
+    }
+
+    public void updateFaviconInBatch(ContentResolver cr,
+                                     Collection<ContentProviderOperation> operations,
+                                     String url, String faviconUrl,
+                                     String faviconGuid, byte[] data) {
+    }
+
+    public void pinSite(ContentResolver cr, String url, String title, int position) {
+    }
+
+    public void unpinSite(ContentResolver cr, int position) {
+    }
+
+    @RobocopTarget
+    public Cursor getBookmarkForUrl(ContentResolver cr, String url) {
+        return null;
+    }
+
+    @Override
+    public Cursor getBookmarksForPartialUrl(ContentResolver cr, String partialUrl) {
+        return null;
+    }
+
+    @Override
+    public boolean hasBookmarkWithGuid(ContentResolver cr, String guid) {
+        return false;
+    }
+
+    public void setSuggestedSites(SuggestedSites suggestedSites) {
+        this.suggestedSites = suggestedSites;
+    }
+
+    public SuggestedSites getSuggestedSites() {
+        return suggestedSites;
+    }
+
+    public boolean hasSuggestedImageUrl(String url) {
+        return false;
+    }
+
+    public String getSuggestedImageUrlForUrl(String url) {
+        return null;
+    }
+
+    public int getSuggestedBackgroundColorForUrl(String url) {
+        return 0;
+    }
+
+    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);
+            }
+        };
+    }
+}