Merge "Allow plugins to contribute a value to the change ETag computation"
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index b918404..6d1c223 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -4531,7 +4531,8 @@
             ListChangesOption.MESSAGES,
             ListChangesOption.SUBMITTABLE,
             ListChangesOption.WEB_LINKS,
-            ListChangesOption.SKIP_MERGEABLE);
+            ListChangesOption.SKIP_MERGEABLE,
+            ListChangesOption.SKIP_DIFFSTAT);
 
     PushOneCommit.Result change = createChange();
     int number = gApi.changes().id(change.getChangeId()).get(options)._number;
diff --git a/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior.html b/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior.html
index fc8428f..4252e6e 100644
--- a/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior.html
+++ b/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior.html
@@ -97,6 +97,12 @@
 
       // Skip mergeability data.
       SKIP_MERGEABLE: 22,
+
+      /**
+      * Skip diffstat computation that compute the insertions field (number of lines inserted) and
+      * deletions field (number of lines deleted)
+      */
+      SKIP_DIFFSTAT: 23,
     },
 
     listChangesOptionsToHex(...args) {
diff --git a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
index f247156..97e9bdc 100644
--- a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
+++ b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
@@ -87,10 +87,12 @@
     STARTUP_DIFF_VIEW_DISPLAYED: 'StartupDiffViewDisplayed',
     STARTUP_FILE_LIST_DISPLAYED: 'StartupFileListDisplayed',
     WEB_COMPONENTS_READY: 'WebComponentsReady',
+    METRICS_PLUGIN_LOADED: 'MetricsPluginLoaded',
   };
 
   const STARTUP_TIMERS = {};
   STARTUP_TIMERS[TIMER.PLUGINS_LOADED] = 0;
+  STARTUP_TIMERS[TIMER.METRICS_PLUGIN_LOADED] = 0;
   STARTUP_TIMERS[TIMER.STARTUP_CHANGE_DISPLAYED] = 0;
   STARTUP_TIMERS[TIMER.STARTUP_CHANGE_LOAD_FULL] = 0;
   STARTUP_TIMERS[TIMER.STARTUP_DASHBOARD_DISPLAYED] = 0;
@@ -174,8 +176,13 @@
         !this._baselines.hasOwnProperty(TIMER.PLUGINS_LOADED);
     },
 
+    _isMetricsPluginLoaded() {
+      return this._arePluginsLoaded() || this._baselines &&
+        !this._baselines.hasOwnProperty(TIMER.METRICS_PLUGIN_LOADED);
+    },
+
     reporter(...args) {
-      const report = (this._arePluginsLoaded() && !pending.length) ?
+      const report = (this._isMetricsPluginLoaded() && !pending.length) ?
         this.defaultReporter : this.cachingReporter;
       report.apply(this, args);
     },
@@ -223,7 +230,7 @@
       if (type === ERROR.TYPE && category === ERROR.CATEGORY) {
         console.error(eventValue.error || eventName);
       }
-      if (this._arePluginsLoaded()) {
+      if (this._isMetricsPluginLoaded()) {
         if (pending.length) {
           for (const args of pending.splice(0)) {
             this.reporter(...args);
@@ -326,6 +333,12 @@
       this.reporter(EXTENSION.TYPE, EXTENSION.DETECTED, name);
     },
 
+    pluginLoaded(name) {
+      if (name.startsWith('metrics-')) {
+        this.timeEnd(TIMER.METRICS_PLUGIN_LOADED);
+      }
+    },
+
     pluginsLoaded(pluginsList) {
       this.timeEnd(TIMER.PLUGINS_LOADED);
       this.reporter(
@@ -346,8 +359,8 @@
     timeEnd(name) {
       if (!this._baselines.hasOwnProperty(name)) { return; }
       const baseTime = this._baselines[name];
-      this._reportTiming(name, this.now() - baseTime);
       delete this._baselines[name];
+      this._reportTiming(name, this.now() - baseTime);
 
       // Finalize the interval. Either from a registered start mark or
       // the navigation start time (if baseTime is 0).
diff --git a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html
index f7d2f62..f505311 100644
--- a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html
+++ b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html
@@ -266,7 +266,7 @@
         sandbox.stub(element, 'now').returns(42);
         element.pluginsLoaded();
         assert.isTrue(element.defaultReporter.calledWithExactly(
-            'timing-report', 'UI Latency', 'PluginsLoaded', 42, undefined
+            'timing-report', 'UI Latency', 'PluginsLoaded', 42
         ));
       });
 
@@ -287,6 +287,11 @@
         assert.isTrue(element.defaultReporter.called);
       });
 
+      test('reports if metrics plugin xyz is loaded', () => {
+        element.pluginLoaded('metrics-xyz');
+        assert.isTrue(element.defaultReporter.called);
+      });
+
       test('reports cached events preserving order', () => {
         element.time('foo');
         element.time('bar');
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
index e422b7e..fff2e33 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
@@ -673,6 +673,7 @@
       delete _pluginsPending[name];
       _pluginsInstalled.push(name);
       Gerrit._setPluginsCount(_pluginsPendingCount - 1);
+      getReporting().pluginLoaded(name);
       console.log(`Plugin ${name} installed.`);
     }
   };
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index dc671b1..3937424 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -1344,6 +1344,7 @@
         this.ListChangesOption.SUBMITTABLE,
         this.ListChangesOption.WEB_LINKS,
         this.ListChangesOption.SKIP_MERGEABLE,
+        this.ListChangesOption.SKIP_DIFFSTAT,
       ];
       return this.getConfig(false).then(config => {
         if (config.receive && config.receive.enable_signed_push) {
@@ -1365,7 +1366,8 @@
       const optionsHex = this.listChangesOptionsToHex(
           this.ListChangesOption.ALL_COMMITS,
           this.ListChangesOption.ALL_REVISIONS,
-          this.ListChangesOption.SKIP_MERGEABLE
+          this.ListChangesOption.SKIP_MERGEABLE,
+          this.ListChangesOption.SKIP_DIFFSTAT
       );
       return this._getChangeDetail(changeNum, optionsHex, opt_errFn,
           opt_cancelCondition);