Bug 1456291: Avoid loading the blocklist service before UI is interactive. r=Gijs
authorKris Maglione <maglione.k@gmail.com>
Mon, 23 Apr 2018 15:03:00 -0700
changeset 468740 1fa2a1d2d41e69c953e0b307e46b885271cd6091
parent 468739 6bb7337970f19723f9ba34a682b4682c53863e5a
child 468741 af2ff7d301a7b481423a8ec172f92c8bbacaf285
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1456291
milestone61.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 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
@@ -508,17 +508,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({
@@ -623,33 +623,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),
     };
@@ -747,22 +751,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"],
@@ -799,25 +808,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}
       };
     }