Bug 1243585 - Create CorePingBuilder in BrowserApp. r=sebastian draft
authorMichael Comella <michael.l.comella@gmail.com>
Thu, 28 Apr 2016 16:01:15 -0700
changeset 357491 a063bd635779c5c0ad50865e74d880f6cd314fa3
parent 357490 95f945572b1ca48ca7c79ab535f2491e1bee81b8
child 357492 63b671fab5f79659a9a0f10ed5df0fee0b880fb2
push id16806
push usermichael.l.comella@gmail.com
push dateFri, 29 Apr 2016 00:52:31 +0000
reviewerssebastian
bugs1243585
milestone49.0a1
Bug 1243585 - Create CorePingBuilder in BrowserApp. r=sebastian Note: this is the first commit expected to compile. MozReview-Commit-ID: Fc8uRkJAXgB
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -72,18 +72,19 @@ import org.mozilla.gecko.search.SearchEn
 import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository;
 import org.mozilla.gecko.tabqueue.TabQueueHelper;
 import org.mozilla.gecko.tabqueue.TabQueuePrompt;
 import org.mozilla.gecko.tabs.TabHistoryController;
 import org.mozilla.gecko.tabs.TabHistoryController.OnShowTabHistory;
 import org.mozilla.gecko.tabs.TabHistoryFragment;
 import org.mozilla.gecko.tabs.TabHistoryPage;
 import org.mozilla.gecko.tabs.TabsPanel;
-import org.mozilla.gecko.telemetry.TelemetryConstants;
+import org.mozilla.gecko.telemetry.TelemetryDispatcher;
 import org.mozilla.gecko.telemetry.TelemetryUploadService;
+import org.mozilla.gecko.telemetry.core.TelemetryCorePingBuilder;
 import org.mozilla.gecko.toolbar.AutocompleteHandler;
 import org.mozilla.gecko.toolbar.BrowserToolbar;
 import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
 import org.mozilla.gecko.toolbar.ToolbarProgressView;
 import org.mozilla.gecko.trackingprotection.TrackingProtectionPrompt;
 import org.mozilla.gecko.updater.UpdateServiceHelper;
 import org.mozilla.gecko.util.ActivityUtils;
 import org.mozilla.gecko.util.Clipboard;
@@ -308,16 +309,18 @@ public class BrowserApp extends GeckoApp
     private final List<BrowserAppDelegate> delegates = Collections.unmodifiableList(Arrays.asList(
             (BrowserAppDelegate) new AddToHomeScreenPromotion(),
             (BrowserAppDelegate) new ScreenshotDelegate()
     ));
 
     @NonNull
     private SearchEngineManager searchEngineManager; // Contains reference to Context - DO NOT LEAK!
 
+    private TelemetryDispatcher mTelemetryDispatcher;
+
     @Override
     public View onCreateView(final String name, final Context context, final AttributeSet attrs) {
         final View view;
         if (BrowserToolbar.class.getName().equals(name)) {
             view = BrowserToolbar.create(context, attrs);
         } else if (TabsPanel.TabsLayout.class.getName().equals(name)) {
             view = TabsPanel.createTabsLayout(context, attrs);
         } else {
@@ -748,33 +751,36 @@ public class BrowserApp extends GeckoApp
             "Menu:Add",
             "Menu:Remove",
             "Sanitize:ClearHistory",
             "Sanitize:ClearSyncedTabs",
             "Settings:Show",
             "Telemetry:Gather",
             "Updater:Launch");
 
+        final GeckoProfile profile = getProfile();
+
         // We want to upload the telemetry core ping as soon after startup as possible. It relies on the
         // Distribution being initialized. If you move this initialization, ensure it plays well with telemetry.
         final Distribution distribution = Distribution.init(this);
-        distribution.addOnDistributionReadyCallback(new DistributionStoreCallback(this, getProfile().getName()));
+        distribution.addOnDistributionReadyCallback(new DistributionStoreCallback(this, profile.getName()));
 
         searchEngineManager = new SearchEngineManager(this, distribution);
+        mTelemetryDispatcher = new TelemetryDispatcher(profile.getDir().getAbsolutePath());
 
         // Init suggested sites engine in BrowserDB.
         final SuggestedSites suggestedSites = new SuggestedSites(appContext, distribution);
-        final BrowserDB db = getProfile().getDB();
+        final BrowserDB db = profile.getDB();
         db.setSuggestedSites(suggestedSites);
 
         JavaAddonManager.getInstance().init(appContext);
         mSharedPreferencesHelper = new SharedPreferencesHelper(appContext);
         mOrderedBroadcastHelper = new OrderedBroadcastHelper(appContext);
-        mReadingListHelper = new ReadingListHelper(appContext, getProfile());
-        mAccountsHelper = new AccountsHelper(appContext, getProfile());
+        mReadingListHelper = new ReadingListHelper(appContext, profile);
+        mAccountsHelper = new AccountsHelper(appContext, profile);
 
         final AdjustHelperInterface adjustHelper = AdjustConstants.getAdjustHelper();
         adjustHelper.onCreate(this, AdjustConstants.MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN);
 
         // Adjust stores enabled state so this is only necessary because users may have set
         // their data preferences before this feature was implemented and we need to respect
         // those before upload can occur in Adjust.onResume.
         final SharedPreferences prefs = GeckoSharedPrefs.forApp(this);
@@ -1143,17 +1149,17 @@ public class BrowserApp extends GeckoApp
 
         // We don't upload in onCreate because that's only called when the Activity needs to be instantiated
         // and it's possible the system will never free the Activity from memory.
         //
         // We don't upload in onResume/onPause because that will be called each time the Activity is obscured,
         // including by our own Activities/dialogs, and there is no reason to upload each time we're unobscured.
         //
         // So we're left with onStart/onStop.
-        searchEngineManager.getEngine(new UploadTelemetryCallback(BrowserApp.this));
+        searchEngineManager.getEngine(new UploadTelemetryCorePingCallback(BrowserApp.this));
 
         for (final BrowserAppDelegate delegate : delegates) {
             delegate.onStart(this);
         }
     }
 
     @Override
     public void onStop() {
@@ -4067,67 +4073,71 @@ public class BrowserApp extends GeckoApp
 
         mActionBarFlipper.showPrevious();
 
         // Only slide the urlbar out if it was hidden when the action mode started
         // Don't animate hiding it so that there's no flash as we switch back to url mode
         mDynamicToolbar.setTemporarilyVisible(false, VisibilityTransition.IMMEDIATE);
     }
 
-    @WorkerThread // synchronous SharedPrefs write.
-    private static void uploadTelemetry(final Context context, final GeckoProfile profile,
-            final org.mozilla.gecko.search.SearchEngine defaultEngine) {
-        if (!TelemetryUploadService.isUploadEnabledByProfileConfig(context, profile)) {
-            return;
-        }
-
-        final SharedPreferences sharedPrefs = GeckoSharedPrefs.forProfileName(context, profile.getName());
-        final int seq = sharedPrefs.getInt(TelemetryConstants.PREF_SEQ_COUNT, 1);
-
-        // We store synchronously before sending the Intent to ensure this sequence number will not be re-used.
-        sharedPrefs.edit().putInt(TelemetryConstants.PREF_SEQ_COUNT, seq + 1).commit();
-
-        final Intent i = new Intent(TelemetryUploadService.ACTION_UPLOAD_CORE);
-        i.setClass(context, TelemetryUploadService.class);
-        i.putExtra(TelemetryUploadService.EXTRA_DEFAULT_SEARCH_ENGINE, (defaultEngine == null) ? null : defaultEngine.getIdentifier());
-        i.putExtra(TelemetryUploadService.EXTRA_DOC_ID, UUID.randomUUID().toString());
-        i.putExtra(TelemetryUploadService.EXTRA_PROFILE_NAME, profile.getName());
-        i.putExtra(TelemetryUploadService.EXTRA_PROFILE_PATH, profile.getDir().getAbsolutePath());
-        i.putExtra(TelemetryUploadService.EXTRA_SEQ, seq);
-        context.startService(i);
-    }
-
-    private static class UploadTelemetryCallback implements SearchEngineManager.SearchEngineCallback {
+    private static class UploadTelemetryCorePingCallback implements SearchEngineManager.SearchEngineCallback {
         private final WeakReference<BrowserApp> activityWeakReference;
 
-        public UploadTelemetryCallback(final BrowserApp activity) {
+        public UploadTelemetryCorePingCallback(final BrowserApp activity) {
             this.activityWeakReference = new WeakReference<>(activity);
         }
 
         // May be called from any thread.
         @Override
         public void execute(final org.mozilla.gecko.search.SearchEngine engine) {
             // Don't waste resources queueing to the background thread if we don't have a reference.
             if (this.activityWeakReference.get() == null) {
                 return;
             }
 
             // The containing method can be called from onStart: queue this work so that
             // the first launch of the activity doesn't trigger profile init too early.
             //
-            // Additionally, uploadTelemetry must be called from a worker thread.
+            // Additionally, getAndIncrementSequenceNumberSync must be called from a worker thread.
             ThreadUtils.postToBackgroundThread(new Runnable() {
                 @WorkerThread
                 @Override
                 public void run() {
                     final BrowserApp activity = activityWeakReference.get();
                     if (activity == null) {
                         return;
                     }
-                    uploadTelemetry(activity, activity.getProfile(), engine);
+
+                    final GeckoProfile profile = activity.getProfile();
+                    if (!TelemetryUploadService.isUploadEnabledByProfileConfig(activity, profile)) {
+                        Log.d(LOGTAG, "Core ping upload disabled by profile config. Returning.");
+                        return;
+                    }
+
+                    final String clientID;
+                    try {
+                        clientID = profile.getClientId();
+                    } catch (final IOException e) {
+                        Log.w(LOGTAG, "Unable to get client ID to generate core ping: " + e);
+                        return;
+                    }
+
+                    // Each profile can have different telemetry data so we intentionally grab the shared prefs for the profile.
+                    final SharedPreferences sharedPrefs = GeckoSharedPrefs.forProfileName(activity, profile.getName());
+                    final TelemetryCorePingBuilder pingBuilder = new TelemetryCorePingBuilder(activity, TelemetryCorePingBuilder.getServer(sharedPrefs))
+                            .setClientID(clientID)
+                            .setDefaultSearchEngine(TelemetryCorePingBuilder.getEngineIdentifier(engine))
+                            .setProfileCreationDate(TelemetryCorePingBuilder.getProfileCreationDate(activity, profile))
+                            .setSequenceNumber(TelemetryCorePingBuilder.getAndIncrementSequenceNumberSync(sharedPrefs));
+                    final String distributionId = sharedPrefs.getString(DistributionStoreCallback.PREF_DISTRIBUTION_ID, null);
+                    if (distributionId != null) {
+                        pingBuilder.setOptDistributionID(distributionId);
+                    }
+
+                    activity.mTelemetryDispatcher.queuePingForUpload(activity, pingBuilder);
                 }
             });
         }
     }
 
     public static interface TabStripInterface {
         public void refresh();
         void setOnTabChangedListener(OnTabAddedOrRemovedListener listener);