Bug 1293790 - Pre: implement AS topsites access r?grisha draft
authorAndrzej Hunt <ahunt@mozilla.com>
Tue, 23 Aug 2016 14:04:01 -0700
changeset 404593 e57802d851654abe72e209ad7be23e29e1630d85
parent 404592 6c291ec12a340befa9c128b76984e9186a3e8a68
child 404594 eb9dd7e2404e633b4d0801bf4d0e49ff8910d078
push id27256
push userahunt@mozilla.com
push dateTue, 23 Aug 2016 21:38:12 +0000
reviewersgrisha
bugs1293790
milestone51.0a1
Bug 1293790 - Pre: implement AS topsites access r?grisha MozReview-Commit-ID: 1z30naErciE
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
toolkit/components/telemetry/Histograms.json
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserDB.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserDB.java
@@ -16,16 +16,17 @@ import org.mozilla.gecko.distribution.Di
 import org.mozilla.gecko.favicons.decoders.LoadFaviconResult;
 
 import android.content.ContentProviderOperation;
 import android.content.ContentResolver;
 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>.
  *
  * GeckoProfile itself will construct an appropriate subclass using
  * a factory that the containing application can set with
@@ -74,16 +75,18 @@ public interface BrowserDB {
     /**
      * @return a cursor over top sites (high-ranking bookmarks and history).
      * Can return <code>null</code>.
      * 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 suggestedRangeLimit, int limit);
 
+    public abstract CursorLoader getActivityStreamTopSites(Context context, 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>.
      */
     public abstract Cursor getAllVisitedHistory(ContentResolver cr);
--- a/mobile/android/base/java/org/mozilla/gecko/db/LocalBrowserDB.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/LocalBrowserDB.java
@@ -19,16 +19,17 @@ import java.util.List;
 import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.AppConstants;
+import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.annotation.RobocopTarget;
 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;
@@ -50,19 +51,21 @@ import android.content.Context;
 import android.database.ContentObserver;
 import android.database.Cursor;
 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.os.SystemClock;
 import android.support.annotation.CheckResult;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.v4.content.CursorLoader;
 import android.text.TextUtils;
 import android.util.Log;
 import org.mozilla.gecko.util.IOUtils;
 
 import static org.mozilla.gecko.util.IOUtils.ConsumedInputStream;
 import static org.mozilla.gecko.favicons.LoadFaviconTask.DEFAULT_FAVICON_BUFFER_SIZE;
 
 public class LocalBrowserDB implements BrowserDB {
@@ -93,16 +96,18 @@ public class LocalBrowserDB implements B
 
     private volatile SuggestedSites mSuggestedSites;
 
     // Constants used when importing history data from legacy browser.
     public static String HISTORY_VISITS_DATE = "date";
     public static String HISTORY_VISITS_COUNT = "visits";
     public static String HISTORY_VISITS_URL = "url";
 
+    private static final String TELEMETRY_HISTOGRAM_ACITIVITY_STREAM_TOPSITES = "FENNEC_ACTIVITY_STREAM_TOPSITES_LOADER_TIME_MS";
+
     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;
@@ -1820,16 +1825,65 @@ public class LocalBrowserDB implements B
             if (StringUtils.isUserEnteredUrl(url)) {
                 url = StringUtils.decodeUserEnteredUrl(url);
             }
 
             urls.add(url);
         } while (c.moveToNext());
     }
 
+
+    /**
+     * Internal CursorLoader that extends the framework CursorLoader in order to measure
+     * performance for telemetry purposes.
+     */
+    private static final class TelemetrisedCursorLoader extends CursorLoader {
+        final String mHistogramName;
+
+        public TelemetrisedCursorLoader(Context context, Uri uri, String[] projection, String selection,
+                                        String[] selectionArgs, String sortOrder,
+                                        final String histogramName) {
+            super(context, uri, projection, selection, selectionArgs, sortOrder);
+            mHistogramName = histogramName;
+        }
+
+        @Override
+        public Cursor loadInBackground() {
+            final long start = SystemClock.uptimeMillis();
+
+            final Cursor cursor = super.loadInBackground();
+
+            final long end = SystemClock.uptimeMillis();
+            final long took = end - start;
+
+            Telemetry.addToHistogram(mHistogramName, (int) Math.min(took, Integer.MAX_VALUE));
+            return cursor;
+        }
+    }
+
+    public CursorLoader getActivityStreamTopSites(Context context, int limit) {
+        final Uri uri = mTopSitesUriWithProfile.buildUpon()
+                .appendQueryParameter(BrowserContract.PARAM_LIMIT,
+                        String.valueOf(limit))
+                .appendQueryParameter(BrowserContract.PARAM_TOPSITES_DISABLE_PINNED, Boolean.TRUE.toString())
+                .build();
+
+        return new TelemetrisedCursorLoader(context,
+                uri,
+                new String[]{ Combined._ID,
+                        Combined.URL,
+                        Combined.TITLE,
+                        Combined.BOOKMARK_ID,
+                        Combined.HISTORY_ID },
+                null,
+                null,
+                null,
+                TELEMETRY_HISTOGRAM_ACITIVITY_STREAM_TOPSITES);
+    }
+
     @Override
     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();
--- a/mobile/android/base/java/org/mozilla/gecko/db/StubBrowserDB.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/StubBrowserDB.java
@@ -21,16 +21,17 @@ import org.mozilla.gecko.feeds.subscript
 
 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;
+import android.support.v4.content.CursorLoader;
 
 class StubSearches implements Searches {
     public StubSearches() {
     }
 
     public void insert(ContentResolver cr, String query) {
     }
 }
@@ -370,16 +371,20 @@ public class StubBrowserDB implements Br
     public int getSuggestedBackgroundColorForUrl(String url) {
         return 0;
     }
 
     public Cursor getTopSites(ContentResolver cr, int suggestedRangeLimit, int limit) {
         return null;
     }
 
+    public CursorLoader getActivityStreamTopSites(Context context, int limit) {
+        return null;
+    }
+
     public static Factory getFactory() {
         return new Factory() {
             @Override
             public BrowserDB get(String profileName, File profileDir) {
                 return new StubBrowserDB(profileName);
             }
         };
     }
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -5614,16 +5614,27 @@
     "expires_in_version": "never",
     "kind": "exponential",
     "low": 10,
     "high": 20000,
     "n_buckets": 20,
     "description": "Time for the home screen Top Sites query to return with no filter set (ms)",
     "cpp_guard": "ANDROID"
   },
+  "FENNEC_ACTIVITY_STREAM_TOPSITES_LOADER_TIME_MS": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "low": 10,
+    "high": 20000,
+    "n_buckets": 20,
+    "description": "Time for the Activity Stream home screen Top Sites query to return (ms)",
+    "alert_emails": ["mobile-frontend@mozilla.com"],
+    "bug_numbers": [1293790],
+    "cpp_guard": "ANDROID"
+  },
   "FENNEC_HOMEPANELS_CUSTOM": {
     "expires_in_version": "54",
     "kind": "boolean",
     "bug_numbers": [1245368],
     "description": "Whether the user has customized their homepanels",
     "cpp_guard": "ANDROID"
   },
   "FENNEC_WAS_KILLED": {