Add UMA for Grid overlays opened source

Backend CL: https://crrev.com/c/2410069

Bug: chromium:1047356
Change-Id: I42d4b9e933d6d136b6b6f6da5d312cb25d8eff08
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2410229
Reviewed-by: Changhao Han <[email protected]>
Reviewed-by: Mathias Bynens <[email protected]>
Reviewed-by: Alex Rudenko <[email protected]>
Commit-Queue: Changhao Han <[email protected]>
diff --git a/front_end/devtools_compatibility.js b/front_end/devtools_compatibility.js
index 9ec8b5a..53ace68 100644
--- a/front_end/devtools_compatibility.js
+++ b/front_end/devtools_compatibility.js
@@ -357,7 +357,10 @@
 
   /**
    * Enum for recordPerformanceHistogram
-   * Warning: There are three definitions of this enum in the DevTools code base, keep them in sync.
+   * Warning: There are two other definitions of this enum in the DevTools code
+   * base, keep them in sync:
+   * front_end/extern.js
+   * front_end/host/InspectorFrontendHostAPI.js
    * @readonly
    * @enum {string}
    */
@@ -379,6 +382,7 @@
     ExperimentEnabled: 'DevTools.ExperimentEnabled',
     ExperimentDisabled: 'DevTools.ExperimentDisabled',
     ComputedStyleGrouping: 'DevTools.ComputedStyleGrouping',
+    GridOverlayOpenedFrom: 'DevTools.GridOverlayOpenedFrom',
   };
 
   /**
diff --git a/front_end/elements/ElementsTreeElement.js b/front_end/elements/ElementsTreeElement.js
index f20a1a9..c335d4f 100644
--- a/front_end/elements/ElementsTreeElement.js
+++ b/front_end/elements/ElementsTreeElement.js
@@ -1970,7 +1970,8 @@
       gridAdorner.classList.add('grid');
       const onClick = /** @type {!EventListener} */ (() => {
         if (gridAdorner.isActive()) {
-          node.domModel().overlayModel().highlightGridInPersistentOverlay(nodeId);
+          node.domModel().overlayModel().highlightGridInPersistentOverlay(
+              nodeId, Host.UserMetrics.GridOverlayOpener.Adorner);
         } else {
           node.domModel().overlayModel().hideGridInPersistentOverlay(nodeId);
         }
diff --git a/front_end/elements/LayoutSidebarPane.js b/front_end/elements/LayoutSidebarPane.js
index a6bb941..6f71ca0 100644
--- a/front_end/elements/LayoutSidebarPane.js
+++ b/front_end/elements/LayoutSidebarPane.js
@@ -6,6 +6,7 @@
 // TODO(crbug.com/1011811): Enable TypeScript compiler checks
 
 import * as Common from '../common/common.js';
+import * as Host from '../host/host.js';
 import * as SDK from '../sdk/sdk.js';
 import * as UI from '../ui/ui.js';
 
@@ -32,7 +33,8 @@
       },
       toggle: value => {
         if (value) {
-          node.domModel().overlayModel().highlightGridInPersistentOverlay(node.id);
+          node.domModel().overlayModel().highlightGridInPersistentOverlay(
+              node.id, Host.UserMetrics.GridOverlayOpener.LayoutPane);
         } else {
           node.domModel().overlayModel().hideGridInPersistentOverlay(node.id);
         }
diff --git a/front_end/externs.js b/front_end/externs.js
index ab71805..bf7d593 100644
--- a/front_end/externs.js
+++ b/front_end/externs.js
@@ -1440,7 +1440,10 @@
 
 /**
  * Enum for recordEnumeratedHistogram
- * Warning: There are three definitions of this enum in the DevTools code base, keep them in sync.
+ * Warning: There are two other definitions of this enum in the DevTools code
+ * base, keep them in sync:
+ * front_end/devtools_compatibility.js
+ * front_end/host/InspectorFrontendHostAPI.js
  * @readonly
  * @enum {string}
  */
@@ -1462,6 +1465,7 @@
   ExperimentEnabled: 'DevTools.ExperimentEnabled',
   ExperimentDisabled: 'DevTools.ExperimentDisabled',
   ComputedStyleGrouping: 'DevTools.ComputedStyleGrouping',
+  GridOverlayOpenedFrom: 'DevTools.GridOverlayOpenedFrom',
 };
 
 /**
diff --git a/front_end/host/InspectorFrontendHostAPI.js b/front_end/host/InspectorFrontendHostAPI.js
index 27422c1..c04cd7b 100644
--- a/front_end/host/InspectorFrontendHostAPI.js
+++ b/front_end/host/InspectorFrontendHostAPI.js
@@ -403,7 +403,10 @@
 
 /**
  * Enum for recordPerformanceHistogram
- * Warning: There are three definitions of this enum in the DevTools code base, keep them in sync.
+ * Warning: There are two other definitions of this enum in the DevTools code
+ * base, keep them in sync:
+ * front_end/extern.js
+ * front_end/devtools_compatibility.js
  * @readonly
  * @enum {string}
  */
@@ -425,4 +428,5 @@
   ExperimentEnabled: 'DevTools.ExperimentEnabled',
   ExperimentDisabled: 'DevTools.ExperimentDisabled',
   ComputedStyleGrouping: 'DevTools.ComputedStyleGrouping',
+  GridOverlayOpenedFrom: 'DevTools.GridOverlayOpenedFrom',
 };
diff --git a/front_end/host/UserMetrics.js b/front_end/host/UserMetrics.js
index 5e63b71..f75d2f2 100644
--- a/front_end/host/UserMetrics.js
+++ b/front_end/host/UserMetrics.js
@@ -301,6 +301,16 @@
     InspectorFrontendHostInstance.recordEnumeratedHistogram(EnumeratedHistogram.ComputedStyleGrouping, code, size);
     Common.EventTarget.fireEvent(EnumeratedHistogram.ComputedStyleGrouping, {value: code});
   }
+
+  /**
+   * @param {!GridOverlayOpener} gridOverlayOpener
+   */
+  gridOverlayOpenedFrom(gridOverlayOpener) {
+    const size = Object.keys(GridOverlayOpener).length + 1;
+    InspectorFrontendHostInstance.recordEnumeratedHistogram(
+        EnumeratedHistogram.GridOverlayOpenedFrom, gridOverlayOpener, size);
+    Common.EventTarget.fireEvent(EnumeratedHistogram.GridOverlayOpenedFrom, {value: gridOverlayOpener});
+  }
 }
 
 // Codes below are used to collect UMA histograms in the Chromium port.
@@ -637,3 +647,9 @@
   ContentSecurityPolicyDirective: 6,
   ContentSecurityPolicyElement: 7
 };
+
+/** @enum {number} */
+export const GridOverlayOpener = {
+  Adorner: 0,
+  LayoutPane: 1,
+};
diff --git a/front_end/sdk/OverlayModel.js b/front_end/sdk/OverlayModel.js
index 61e79ee..7398a9a 100644
--- a/front_end/sdk/OverlayModel.js
+++ b/front_end/sdk/OverlayModel.js
@@ -345,12 +345,14 @@
 
   /**
    * @param {number} nodeId
+   * @param {!Host.UserMetrics.GridOverlayOpener} gridOverlayOpener
    */
-  highlightGridInPersistentOverlay(nodeId) {
+  highlightGridInPersistentOverlay(nodeId, gridOverlayOpener) {
     if (!this._persistentGridHighlighter) {
       return;
     }
     this._persistentGridHighlighter.highlightInOverlay(nodeId);
+    Host.userMetrics.gridOverlayOpenedFrom(gridOverlayOpener);
     this.dispatchEventToListeners(Events.PersistentGridOverlayStateChanged, {nodeId, enabled: true});
   }
 
diff --git a/test/e2e/host/user-metrics_test.ts b/test/e2e/host/user-metrics_test.ts
index 74dc75f..a5d8808 100644
--- a/test/e2e/host/user-metrics_test.ts
+++ b/test/e2e/host/user-metrics_test.ts
@@ -8,7 +8,7 @@
 import {$, click, enableExperiment, getBrowserAndPages, goToResource, platform, reloadDevTools, waitFor} from '../../shared/helper.js';
 import {describe, it} from '../../shared/mocha-extensions.js';
 import {navigateToCssOverviewTab} from '../helpers/css-overview-helpers.js';
-import {navigateToSidePane, toggleGroupComputedProperties} from '../helpers/elements-helpers.js';
+import {expandSelectedNodeRecursively, INACTIVE_GRID_ADORNER_SELECTOR, navigateToSidePane, openLayoutPane, toggleElementCheckboxInLayoutPane, toggleGroupComputedProperties, waitForContentOfSelectedElementsNode, waitForElementsStyleSection} from '../helpers/elements-helpers.js';
 import {clickToggleButton, selectDualScreen, startEmulationWithDualScreenFlag} from '../helpers/emulation-helpers.js';
 import {closeSecurityTab, navigateToSecurityTab} from '../helpers/security-helpers.js';
 import {openPanelViaMoreTools, openSettingsTab} from '../helpers/settings-helpers.js';
@@ -47,6 +47,7 @@
     __computedStyleGrouping: (evt: Event) => void;
     __issuesPanelIssueExpanded: (evt: Event) => void;
     __issuesPanelResourceOpened: (evt: Event) => void;
+    __gridOverlayOpenedFrom: (evt: Event) => void;
     Host: {
       UserMetrics: UserMetrics; userMetrics: {actionTaken(name: number): void; colorFixed(threshold: string): void;}
     };
@@ -130,6 +131,11 @@
       window.__caughtEvents.push({name: 'DevTools.IssuesPanelResourceOpened', value: customEvt.detail.value});
     };
 
+    window.__gridOverlayOpenedFrom = (evt: Event) => {
+      const customEvt = evt as CustomEvent;
+      window.__caughtEvents.push({name: 'DevTools.GridOverlayOpenedFrom', value: customEvt.detail.value});
+    };
+
     window.__caughtEvents = [];
     window.__beginCatchEvents = () => {
       window.addEventListener('DevTools.PanelShown', window.__panelShown);
@@ -147,6 +153,7 @@
       window.addEventListener('DevTools.ComputedStyleGrouping', window.__computedStyleGrouping);
       window.addEventListener('DevTools.IssuesPanelIssueExpanded', window.__issuesPanelIssueExpanded);
       window.addEventListener('DevTools.IssuesPanelResourceOpened', window.__issuesPanelResourceOpened);
+      window.addEventListener('DevTools.GridOverlayOpenedFrom', window.__gridOverlayOpenedFrom);
     };
 
     window.__endCatchEvents = () => {
@@ -165,6 +172,7 @@
       window.removeEventListener('DevTools.ComputedStyleGrouping', window.__computedStyleGrouping);
       window.removeEventListener('DevTools.IssuesPanelIssueExpanded', window.__issuesPanelIssueExpanded);
       window.removeEventListener('DevTools.IssuesPanelResourceOpened', window.__issuesPanelResourceOpened);
+      window.removeEventListener('DevTools.GridOverlayOpenedFrom', window.__gridOverlayOpenedFrom);
     };
 
     window.__beginCatchEvents();
@@ -621,7 +629,6 @@
   });
 });
 
-
 describe('User Metrics for Issue Panel', () => {
   beforeEach(async () => {
     await openPanelViaMoreTools('Issues');
@@ -648,3 +655,45 @@
     await endCatchEvents(frontend);
   });
 });
+
+describe('User Metrics for Grid Overlay', () => {
+  beforeEach(async () => {
+    await goToResource('elements/adornment.html');
+    await enableExperiment('cssGridFeatures');
+
+    const {frontend} = getBrowserAndPages();
+    await beginCatchEvents(frontend);
+
+    await waitForElementsStyleSection();
+    await waitForContentOfSelectedElementsNode('<body>\u200B');
+    await expandSelectedNodeRecursively();
+  });
+
+  it('dispatch events when opening Grid overlay from adorner', async () => {
+    await click(INACTIVE_GRID_ADORNER_SELECTOR);
+
+    await assertEventsHaveBeenFired([
+      {
+        name: 'DevTools.GridOverlayOpenedFrom',
+        value: 0,  // adorner
+      },
+    ]);
+  });
+
+  it('dispatch events when opening Grid overlay from Layout pane', async () => {
+    await openLayoutPane();
+    await toggleElementCheckboxInLayoutPane();
+
+    await assertEventsHaveBeenFired([
+      {
+        name: 'DevTools.GridOverlayOpenedFrom',
+        value: 1,  // layout pane
+      },
+    ]);
+  });
+
+  afterEach(async () => {
+    const {frontend} = getBrowserAndPages();
+    await endCatchEvents(frontend);
+  });
+});