Bug 1456291: Avoid loading the blocklist service before UI is interactive. r?Gijs draft
authorKris Maglione <maglione.k@gmail.com>
Mon, 23 Apr 2018 15:03:00 -0700
changeset 786865 3e77d7c8c22a9fcb1430051c83a43ebd3b90bc0a
parent 786864 d50ca8f2a0d9bfe41703fff0b48a5973f8c434a0
push id107589
push usermaglione.k@gmail.com
push dateMon, 23 Apr 2018 23:29:42 +0000
reviewersGijs
bugs1456291
milestone61.0a1
Bug 1456291: Avoid loading the blocklist service before UI is interactive. r?Gijs The TelemetryEnvironment initialization process currently forces a load and initialization of the blocklist service only to check its isLoaded flag. This adds measurable overhead to startup, and without those checks, the service would not be initialized until after first paint. We should defer even checking whether the blocklist is loaded until after startup has finished. MozReview-Commit-ID: 73c4o5oVqze
toolkit/components/telemetry/TelemetryEnvironment.jsm
--- a/toolkit/components/telemetry/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm
@@ -507,17 +507,17 @@ EnvironmentAddonBuilder.prototype = {
         () => this._shutdownBlocker());
     } catch (err) {
       return Promise.reject(err);
     }
 
     this._pendingTask = (async () => {
       try {
         // Gather initial addons details
-        await this._updateAddons();
+        await this._updateAddons(true);
 
         if (!this._environment._addonsAreFull) {
           // The addon database has not been loaded, so listen for the event
           // triggered by the AddonManager when it is loaded so we can
           // immediately gather full data at that time.
           await new Promise(resolve => {
             const ADDON_LOAD_NOTIFICATION = "xpi-database-loaded";
             Services.obs.addObserver({
@@ -622,33 +622,37 @@ EnvironmentAddonBuilder.prototype = {
   },
 
   /**
    * Collect the addon data for the environment.
    *
    * This should only be called from _pendingTask; otherwise we risk
    * running this during addon manager shutdown.
    *
+   * @param {boolean} [atStartup]
+   *        True if this is the first check we're performing at startup. In that
+   *        situation, we defer some more expensive initialization.
+   *
    * @returns Promise<Object> This returns a Promise resolved with a status object with the following members:
    *   changed - Whether the environment changed.
    *   oldEnvironment - Only set if a change occured, contains the environment data before the change.
    */
-  async _updateAddons() {
+  async _updateAddons(atStartup) {
     this._environment._log.trace("_updateAddons");
     let personaId = null;
     let theme = LightweightThemeManager.currentTheme;
     if (theme) {
       personaId = theme.id;
     }
 
     let addons = {
       activeAddons: await this._getActiveAddons(),
       theme: await this._getActiveTheme(),
-      activePlugins: this._getActivePlugins(),
-      activeGMPlugins: await this._getActiveGMPlugins(),
+      activePlugins: this._getActivePlugins(atStartup),
+      activeGMPlugins: await this._getActiveGMPlugins(atStartup),
       activeExperiment: {},
       persona: personaId,
     };
 
     let result = {
       changed: !this._environment._currentEnvironment.addons ||
                !ObjectUtils.deepEqual(addons, this._environment._currentEnvironment.addons),
     };
@@ -746,22 +750,27 @@ EnvironmentAddonBuilder.prototype = {
       };
     }
 
     return activeTheme;
   },
 
   /**
    * Get the plugins data in object form.
+   *
+   * @param {boolean} [atStartup]
+   *        True if this is the first check we're performing at startup. In that
+   *        situation, we defer some more expensive initialization.
+   *
    * @return Object containing the plugins data.
    */
-  _getActivePlugins() {
+  _getActivePlugins(atStartup) {
     // If we haven't yet loaded the blocklist, pass back dummy data for now,
     // and add an observer to update this data as soon as we get it.
-    if (!Services.blocklist.isLoaded) {
+    if (atStartup || !Services.blocklist.isLoaded) {
       if (!this._blocklistObserverAdded) {
         Services.obs.addObserver(this, BLOCKLIST_LOADED_TOPIC);
         this._blocklistObserverAdded = true;
       }
       return [{
         name: "dummy", version: "0.1", description: "Blocklist unavailable",
         blocklisted: false, disabled: true, clicktoplay: false,
         mimeTypes: ["text/there.is.only.blocklist"],
@@ -798,25 +807,30 @@ EnvironmentAddonBuilder.prototype = {
       }
     }
 
     return activePlugins;
   },
 
   /**
    * Get the GMPlugins data in object form.
+   *
+   * @param {boolean} [atStartup]
+   *        True if this is the first check we're performing at startup. In that
+   *        situation, we defer some more expensive initialization.
+   *
    * @return Object containing the GMPlugins data.
    *
    * This should only be called from _pendingTask; otherwise we risk
    * running this during addon manager shutdown.
    */
-  async _getActiveGMPlugins() {
+  async _getActiveGMPlugins(atStartup) {
     // If we haven't yet loaded the blocklist, pass back dummy data for now,
     // and add an observer to update this data as soon as we get it.
-    if (!Services.blocklist.isLoaded) {
+    if (atStartup || !Services.blocklist.isLoaded) {
       if (!this._blocklistObserverAdded) {
         Services.obs.addObserver(this, BLOCKLIST_LOADED_TOPIC);
         this._blocklistObserverAdded = true;
       }
       return {
         "dummy-gmp": {version: "0.1", userDisabled: false, applyBackgroundUpdates: true}
       };
     }