Bug 1536834 - Remove leftover csscoverage code; r=jdescottes
authorPatrick Brosset <pbrosset@mozilla.com>
Wed, 20 Mar 2019 16:06:59 +0000
changeset 465241 f4343e34b8feb81cc31b537a9c1fce846cb2c344
parent 465240 d96f98f974e087224e0a1ef9be67e2fc63397d8b
child 465242 6d1442f6c07b258f67674867ce13a2d3412fd3f7
push id35735
push usershindli@mozilla.com
push dateThu, 21 Mar 2019 04:34:45 +0000
treeherdermozilla-central@ac0cd1a710f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes
bugs1536834
milestone68.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 1536834 - Remove leftover csscoverage code; r=jdescottes Differential Revision: https://phabricator.services.mozilla.com/D24191
devtools/client/debugger/new/src/client/firefox/types.js
devtools/client/locales/en-US/styleeditor.properties
devtools/client/styleeditor/StyleEditorUI.jsm
devtools/client/styleeditor/StyleSheetEditor.jsm
devtools/client/styleeditor/index.xul
devtools/client/themes/styleeditor.css
devtools/server/actors/csscoverage.js
devtools/server/actors/moz.build
devtools/server/actors/utils/actor-registry.js
devtools/shared/fronts/csscoverage.js
devtools/shared/fronts/moz.build
devtools/shared/locales/en-US/csscoverage.dtd
devtools/shared/locales/en-US/csscoverage.properties
devtools/shared/specs/csscoverage.js
devtools/shared/specs/index.js
devtools/shared/specs/moz.build
--- a/devtools/client/debugger/new/src/client/firefox/types.js
+++ b/devtools/client/debugger/new/src/client/firefox/types.js
@@ -154,17 +154,16 @@ export type FramesResponse = {
   from: ActorId
 };
 
 export type TabPayload = {
   actor: ActorId,
   animationsActor: ActorId,
   consoleActor: ActorId,
   cssPropertiesActor: ActorId,
-  cssUsageActor: ActorId,
   directorManagerActor: ActorId,
   emulationActor: ActorId,
   eventLoopLagActor: ActorId,
   framerateActor: ActorId,
   inspectorActor: ActorId,
   memoryActor: ActorId,
   monitorActor: ActorId,
   outerWindowID: number,
--- a/devtools/client/locales/en-US/styleeditor.properties
+++ b/devtools/client/locales/en-US/styleeditor.properties
@@ -27,20 +27,16 @@ newStyleSheet=New style sheet #%S
 ruleCount.label=#1 rule.;#1 rules.
 
 # LOCALIZATION NOTE  (error-load): This is shown when loading fails.
 error-load=Style sheet could not be loaded.
 
 # LOCALIZATION NOTE  (error-save): This is shown when saving fails.
 error-save=Style sheet could not be saved.
 
-# LOCALIZATION NOTE  (error-compressed): This is shown when we can't show
-# coverage information because the css source is compressed.
-error-compressed=Can’t show coverage information for compressed stylesheets
-
 # LOCALIZATION NOTE  (importStyleSheet.title): This is the file picker title,
 # when you import a style sheet into the Style Editor.
 importStyleSheet.title=Import style sheet
 
 # LOCALIZATION NOTE  (importStyleSheet.filter): This is the *.css filter title
 importStyleSheet.filter=CSS files
 
 # LOCALIZATION NOTE  (saveStyleSheet.title): This is the file picker title,
--- a/devtools/client/styleeditor/StyleEditorUI.jsm
+++ b/devtools/client/styleeditor/StyleEditorUI.jsm
@@ -644,40 +644,16 @@ StyleEditorUI.prototype = {
             const inputElement =
                 details.querySelector(".stylesheet-editor-input");
             await showEditor.load(inputElement, this._cssProperties);
           }
 
           showEditor.onShow();
 
           this.emit("editor-selected", showEditor);
-
-          // Is there any CSS coverage markup to include?
-          const usage = await this._target.getFront("cssUsage");
-          if (usage == null) {
-            return;
-          }
-
-          const sheet = showEditor.styleSheet;
-          const {reports} = await usage.createEditorReportForSheet(sheet);
-
-          showEditor.removeAllUnusedRegions();
-
-          if (reports.length > 0) {
-            // Only apply if this file isn't compressed. We detect a
-            // compressed file if there are more rules than lines.
-            const editorText = showEditor.sourceEditor.getText();
-            const lineCount = editorText.split("\n").length;
-            const ruleCount = showEditor.styleSheet.ruleCount;
-            if (lineCount >= ruleCount) {
-              showEditor.addUnusedRegions(reports);
-            } else {
-              this.emit("error", { key: "error-compressed", level: "info" });
-            }
-          }
         }.bind(this))().catch(console.error);
       },
     });
   },
 
   /**
    * Switch to the editor that has been marked to be selected.
    *
--- a/devtools/client/styleeditor/StyleSheetEditor.jsm
+++ b/devtools/client/styleeditor/StyleSheetEditor.jsm
@@ -37,19 +37,16 @@ const TRANSITION_PREF = "devtools.stylee
 
 // How long to wait to update linked CSS file after original source was saved
 // to disk. Time in ms.
 const CHECK_LINKED_SHEET_DELAY = 500;
 
 // How many times to check for linked file changes
 const MAX_CHECK_COUNT = 10;
 
-// The classname used to show a line that is not used
-const UNUSED_CLASS = "cm-unused-line";
-
 // How much time should the mouse be still before the selector at that position
 // gets highlighted?
 const SELECTOR_HIGHLIGHT_TIMEOUT = 500;
 
 // Minimum delay between firing two media-rules-changed events.
 const EMIT_MEDIA_RULES_THROTTLING = 500;
 
 /**
@@ -301,51 +298,16 @@ StyleSheetEditor.prototype = {
         this.emit("error", { key: LOAD_ERROR, append: this.styleSheet.href,
                              level: "warning" });
         throw e;
       }
     });
   },
 
   /**
-   * Add markup to a region. UNUSED_CLASS is added to specified lines
-   * @param region An object shaped like
-   *   {
-   *     start: { line: L1, column: C1 },
-   *     end: { line: L2, column: C2 }    // optional
-   *   }
-   */
-  addUnusedRegion: function(region) {
-    this.sourceEditor.addLineClass(region.start.line - 1, UNUSED_CLASS);
-    if (region.end) {
-      for (let i = region.start.line; i <= region.end.line; i++) {
-        this.sourceEditor.addLineClass(i - 1, UNUSED_CLASS);
-      }
-    }
-  },
-
-  /**
-   * As addUnusedRegion except that it takes an array of regions
-   */
-  addUnusedRegions: function(regions) {
-    for (const region of regions) {
-      this.addUnusedRegion(region);
-    }
-  },
-
-  /**
-   * Remove all the unused markup regions added by addUnusedRegion
-   */
-  removeAllUnusedRegions: function() {
-    for (let i = 0; i < this.sourceEditor.lineCount(); i++) {
-      this.sourceEditor.removeLineClass(i, UNUSED_CLASS);
-    }
-  },
-
-  /**
    * Forward property-change event from stylesheet.
    *
    * @param  {string} event
    *         Event type
    * @param  {string} property
    *         Property that has changed on sheet
    */
   _onPropertyChange: function(property, value) {
--- a/devtools/client/styleeditor/index.xul
+++ b/devtools/client/styleeditor/index.xul
@@ -4,18 +4,16 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <!DOCTYPE window [
 <!ENTITY % styleEditorDTD SYSTEM "chrome://devtools/locale/styleeditor.dtd" >
  %styleEditorDTD;
 <!ENTITY % editMenuStrings SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
  %editMenuStrings;
 <!ENTITY % sourceEditorStrings SYSTEM "chrome://devtools/locale/sourceeditor.dtd">
  %sourceEditorStrings;
-<!ENTITY % csscoverageDTD SYSTEM "chrome://devtools-shared/locale/csscoverage.dtd">
- %csscoverageDTD;
 ]>
 
 <?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
 <?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
 <?xml-stylesheet href="chrome://devtools/content/shared/splitview.css" type="text/css"?>
 <?xml-stylesheet href="chrome://devtools/skin/chart.css" type="text/css"?>
 <?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
 <?xml-stylesheet href="chrome://devtools/skin/splitview.css" type="text/css"?>
@@ -164,65 +162,11 @@
                 <html:div class="stylesheet-media-list" />
               </vbox>
             </vbox>
           </hbox>
         </box>
       </html:div> <!-- #splitview-templates -->
     </box>   <!-- .splitview-root -->
 
-    <box class="csscoverage-template" hidden="true">
-      <toolbar class="devtools-toolbar csscoverage-toolbar">
-        <button class="devtools-toolbarbutton csscoverage-toolbarbutton"
-            label="&csscoverage.backButton;"
-            onclick="${onback}"/>
-      </toolbar>
-      <!-- The data for this comes from CSSUsageActor.createPageReport -->
-      <html:div class="csscoverage-report-container">
-        <html:div class="csscoverage-report-content">
-          <html:div class="csscoverage-report-summary">
-            <html:div class="csscoverage-report-chart"/>
-          </html:div>
-          <html:div class="csscoverage-report-unused">
-            <html:h2>&csscoverage.unused;</html:h2>
-            <html:p>&csscoverage.noMatches;</html:p>
-            <html:div foreach="page in ${unused}">
-              <html:h3>${page.url}</html:h3>
-              <html:code foreach="rule in ${page.rules}"
-                         href="${rule.url}"
-                         class="csscoverage-list">${rule.selectorText}</html:code>
-            </html:div>
-          </html:div>
-          <html:div class="csscoverage-report-optimize">
-            <html:h2>&csscoverage.optimize.header;</html:h2>
-            <html:p>
-              &csscoverage.optimize.body1;
-              <html:code>&lt;link ...></html:code>
-              &csscoverage.optimize.body2;
-              <html:code>&lt;style>...</html:code>
-              &csscoverage.optimize.body3;
-            </html:p>
-            <html:div if="${preload.length == 0}">&csscoverage.optimize.bodyX;</html:div>
-            <html:div if="${preload.length > 0}">
-              <html:div foreach="page in ${preload}">
-                <html:h3>${page.url}</html:h3>
-                <html:textarea>&lt;style>
-<html:loop foreach="rule in ${page.rules}"
-                      onclick="${rule.onclick}">${rule.formattedCssText}</html:loop>&lt;/style></html:textarea>
-              </html:div>
-            </html:div>
-            <html:p>
-              &csscoverage.footer1;
-              <html:a target="_blank" href="&csscoverage.footer2a;">&csscoverage.footer3;</html:a>
-              &csscoverage.footer4;
-            </html:p>
-          </html:div>
-          <html:p>&#160;</html:p>
-        </html:div>
-      </html:div>
-    </box>
-
-    <box class="csscoverage-report" hidden="true">
-    </box>
-
   </stack>
 
 </window>
--- a/devtools/client/themes/styleeditor.css
+++ b/devtools/client/themes/styleeditor.css
@@ -273,147 +273,8 @@ h3 {
     -moz-box-flex: 1;
     -moz-box-pack: end;
   }
 
   .stylesheet-more > spacer {
     -moz-box-flex: 0;
   }
 }
-
-/* CSS coverage */
-.csscoverage-report {
-  background-color: var(--theme-toolbar-background);
-  -moz-box-orient: horizontal;
-}
-
-.csscoverage-report-container {
-  height: 100vh;
-  padding: 0 10px;
-  overflow-x: hidden;
-  overflow-y: auto;
-  -moz-box-flex: 1;
-}
-
-.csscoverage-report-content {
-  margin: 20px auto;
-  -moz-column-width: 300px;
-  font-size: 13px;
-  -moz-user-select: text;
-}
-
-.csscoverage-report-summary,
-.csscoverage-report-unused,
-.csscoverage-report-optimize {
-  display: inline-block;
-}
-
-.csscoverage-report-unused,
-.csscoverage-report-optimize {
-  flex: 1;
-  min-width: 0;
-}
-
-@media (max-width: 950px) {
-  .csscoverage-report-content {
-    display: block;
-  }
-
-  .csscoverage-report-summary {
-    display: block;
-    text-align: center;
-  }
-}
-
-.csscoverage-report h1 {
-  font-size: 120%;
-}
-
-.csscoverage-report h2 {
-  font-size: 110%;
-}
-
-.csscoverage-report h1,
-.csscoverage-report h2,
-.csscoverage-report h3 {
-  font-weight: bold;
-  margin: 10px 0;
-}
-
-.csscoverage-report code,
-.csscoverage-report textarea {
-  font-family: var(--monospace-font-family);
-  font-size: inherit;
-}
-
-.csscoverage-list:after {
-  content: ', ';
-}
-
-.csscoverage-list:last-child:after {
-  display: none;
-}
-
-.csscoverage-report textarea {
-  width: 100%;
-  height: 100px;
-}
-
-.csscoverage-report a {
-  cursor: pointer;
-  text-decoration: underline;
-}
-
-.csscoverage-report > .csscoverage-toolbar {
-  border: none;
-  margin: 0;
-  padding: 0;
-}
-
-.csscoverage-report > .csscoverage-toolbarbutton {
-  min-width: 4em;
-  min-height: 100vh;
-  margin: 0;
-  padding: 0;
-  border-radius: 0;
-  border-top: none;
-  border-bottom: none;
-  border-inline-start: none;
-}
-
-.csscoverage-report .pie-table-chart-container {
-  -moz-box-orient: vertical;
-  text-align: start;
-}
-
-.chart-colored-blob[name="Used Preload"] {
-  fill: var(--theme-highlight-pink);
-  background: var(--theme-highlight-pink);
-}
-
-.chart-colored-blob[name=Used] {
-  fill: var(--theme-highlight-green);
-  background: var(--theme-highlight-green);
-}
-
-.chart-colored-blob[name=Unused] {
-  fill: var(--theme-highlight-lightorange);
-  background: var(--theme-highlight-lightorange);
-}
-
-/* Undo 'largest' customization */
-.theme-dark .pie-chart-slice[largest] {
-  stroke-width: 1px;
-  stroke: rgba(0,0,0,0.2);
-}
-
-.theme-light .pie-chart-slice[largest] {
-  stroke-width: 1px;
-  stroke: rgba(255,255,255,0.8);
-}
-
-.csscoverage-report .pie-chart-slice {
-  cursor: default;
-}
-
-.csscoverage-report-chart {
-  margin: 0 20px;
-}
deleted file mode 100644
--- a/devtools/server/actors/csscoverage.js
+++ /dev/null
@@ -1,715 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { Ci } = require("chrome");
-
-const InspectorUtils = require("InspectorUtils");
-const Services = require("Services");
-const ChromeUtils = require("ChromeUtils");
-
-const protocol = require("devtools/shared/protocol");
-const { cssUsageSpec } = require("devtools/shared/specs/csscoverage");
-
-loader.lazyRequireGetter(this, "prettifyCSS", "devtools/shared/inspector/css-logic", true);
-
-const MAX_UNUSED_RULES = 10000;
-
-/**
- * Allow: let foo = l10n.lookup("csscoverageFoo");
- */
-const l10n = exports.l10n = {
-  _URI: "chrome://devtools-shared/locale/csscoverage.properties",
-  lookup: function(msg) {
-    if (this._stringBundle == null) {
-      this._stringBundle = Services.strings.createBundle(this._URI);
-    }
-    return this._stringBundle.GetStringFromName(msg);
-  },
-};
-
-/**
- * CSSUsage manages the collection of CSS usage data.
- * The core of a CSSUsage is a JSON-able data structure called _knownRules
- * which looks like this:
- * This records the CSSStyleRules and their usage.
- * The format is:
- *     Map({
- *       <CSS-URL>|<START-LINE>|<START-COLUMN>: {
- *         selectorText: <CSSStyleRule.selectorText>,
- *         test: <simplify(CSSStyleRule.selectorText)>,
- *         cssText: <CSSStyleRule.cssText>,
- *         isUsed: <TRUE|FALSE>,
- *         presentOn: Set([ <HTML-URL>, ... ]),
- *         preLoadOn: Set([ <HTML-URL>, ... ]),
- *         isError: <TRUE|FALSE>,
- *       }
- *     })
- *
- * For example:
- *     this._knownRules = Map({
- *       "http://eg.com/styles1.css|15|0": {
- *         selectorText: "p.quote:hover",
- *         test: "p.quote",
- *         cssText: "p.quote { color: red; }",
- *         isUsed: true,
- *         presentOn: Set([ "http://eg.com/page1.html", ... ]),
- *         preLoadOn: Set([ "http://eg.com/page1.html" ]),
- *         isError: false,
- *       }, ...
- *     });
- */
-var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, {
-  initialize: function(conn, targetActor) {
-    protocol.Actor.prototype.initialize.call(this, conn);
-
-    this._targetActor = targetActor;
-    this._running = false;
-
-    this._onTabLoad = this._onTabLoad.bind(this);
-    this._onChange = this._onChange.bind(this);
-
-    this._notifyOn = Ci.nsIWebProgress.NOTIFY_STATE_ALL;
-  },
-
-  destroy: function() {
-    this._targetActor = undefined;
-
-    delete this._onTabLoad;
-    delete this._onChange;
-
-    protocol.Actor.prototype.destroy.call(this);
-  },
-
-  /**
-   * Begin recording usage data
-   * @param noreload It's best if we start by reloading the current page
-   * because that starts the test at a known point, but there could be reasons
-   * why we don't want to do that (e.g. the page contains state that will be
-   * lost across a reload)
-   */
-  start: function(noreload) {
-    if (this._running) {
-      throw new Error(l10n.lookup("csscoverageRunningError"));
-    }
-
-    this._isOneShot = false;
-    this._visitedPages = new Set();
-    this._knownRules = new Map();
-    this._running = true;
-    this._tooManyUnused = false;
-
-    this._progressListener = {
-      QueryInterface: ChromeUtils.generateQI([ Ci.nsIWebProgressListener,
-                                               Ci.nsISupportsWeakReference ]),
-
-      onStateChange: (progress, request, flags, status) => {
-        const isStop = flags & Ci.nsIWebProgressListener.STATE_STOP;
-        const isWindow = flags & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
-
-        if (isStop && isWindow) {
-          this._onTabLoad(progress.DOMWindow.document);
-        }
-      },
-
-      destroy: () => {},
-    };
-
-    this._progress = this._targetActor.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                                            .getInterface(Ci.nsIWebProgress);
-    this._progress.addProgressListener(this._progressListener, this._notifyOn);
-
-    if (noreload) {
-      // If we're not starting by reloading the page, then pretend that onload
-      // has just happened.
-      this._onTabLoad(this._targetActor.window.document);
-    } else {
-      this._targetActor.window.location.reload();
-    }
-
-    this.emit("state-change", { isRunning: true });
-  },
-
-  /**
-   * Cease recording usage data
-   */
-  stop: function() {
-    if (!this._running) {
-      throw new Error(l10n.lookup("csscoverageNotRunningError"));
-    }
-
-    this._progress.removeProgressListener(this._progressListener, this._notifyOn);
-    this._progress = undefined;
-
-    this._running = false;
-    this.emit("state-change", { isRunning: false });
-  },
-
-  /**
-   * Start/stop recording usage data depending on what we're currently doing.
-   */
-  toggle: function() {
-    return this._running ? this.stop() : this.start();
-  },
-
-  /**
-   * Running start() quickly followed by stop() does a bunch of unnecessary
-   * work, so this cuts all that out
-   */
-  oneshot: function() {
-    if (this._running) {
-      throw new Error(l10n.lookup("csscoverageRunningError"));
-    }
-
-    this._isOneShot = true;
-    this._visitedPages = new Set();
-    this._knownRules = new Map();
-
-    this._populateKnownRules(this._targetActor.window.document);
-    this._updateUsage(this._targetActor.window.document, false);
-  },
-
-  /**
-   * Called by the ProgressListener to simulate a "load" event
-   */
-  _onTabLoad: function(document) {
-    this._populateKnownRules(document);
-    this._updateUsage(document, true);
-
-    this._observeMutations(document);
-  },
-
-  /**
-   * Setup a MutationObserver on the current document
-   */
-  _observeMutations: function(document) {
-    const MutationObserver = document.defaultView.MutationObserver;
-    const observer = new MutationObserver(mutations => {
-      // It's possible that one of the mutations in this list adds a 'use' of
-      // a CSS rule, and another takes it away. See Bug 1010189
-      this._onChange(document);
-    });
-
-    observer.observe(document, {
-      attributes: true,
-      childList: true,
-      characterData: false,
-      subtree: true,
-    });
-  },
-
-  /**
-   * Event handler for whenever we think the page has changed in a way that
-   * means the CSS usage might have changed.
-   */
-  _onChange: function(document) {
-    // Ignore changes pre 'load'
-    if (!this._visitedPages.has(getURL(document))) {
-      return;
-    }
-    this._updateUsage(document, false);
-  },
-
-  /**
-   * Called whenever we think the list of stylesheets might have changed so
-   * we can update the list of rules that we should be checking
-   */
-  _populateKnownRules: function(document) {
-    const url = getURL(document);
-    this._visitedPages.add(url);
-    // Go through all the rules in the current sheets adding them to knownRules
-    // if needed and adding the current url to the list of pages they're on
-    for (const rule of getAllSelectorRules(document)) {
-      const ruleId = ruleToId(rule);
-      let ruleData = this._knownRules.get(ruleId);
-      if (ruleData == null) {
-        ruleData = {
-          selectorText: rule.selectorText,
-          cssText: rule.cssText,
-          test: getTestSelector(rule.selectorText),
-          isUsed: false,
-          presentOn: new Set(),
-          preLoadOn: new Set(),
-          isError: false,
-        };
-        this._knownRules.set(ruleId, ruleData);
-      }
-
-      ruleData.presentOn.add(url);
-    }
-  },
-
-  /**
-   * Update knownRules with usage information from the current page
-   */
-  _updateUsage: function(document, isLoad) {
-    let qsaCount = 0;
-
-    // Update this._data with matches to say 'used at load time' by sheet X
-    const url = getURL(document);
-
-    for (const [ , ruleData ] of this._knownRules) {
-      // If it broke before, don't try again selectors don't change
-      if (ruleData.isError) {
-        continue;
-      }
-
-      // If it's used somewhere already, don't bother checking again unless
-      // this is a load event in which case we need to add preLoadOn
-      if (!isLoad && ruleData.isUsed) {
-        continue;
-      }
-
-      // Ignore rules that are not present on this page
-      if (!ruleData.presentOn.has(url)) {
-        continue;
-      }
-
-      qsaCount++;
-      if (qsaCount > MAX_UNUSED_RULES) {
-        console.error("Too many unused rules on " + url + " ");
-        this._tooManyUnused = true;
-        continue;
-      }
-
-      try {
-        const match = document.querySelector(ruleData.test);
-        if (match != null) {
-          ruleData.isUsed = true;
-          if (isLoad) {
-            ruleData.preLoadOn.add(url);
-          }
-        }
-      } catch (ex) {
-        ruleData.isError = true;
-      }
-    }
-  },
-
-  /**
-   * Returns a JSONable structure designed to help marking up the style editor,
-   * which describes the CSS selector usage.
-   * Example:
-   *   [
-   *     {
-   *       selectorText: "p#content",
-   *       usage: "unused|used",
-   *       start: { line: 3, column: 0 },
-   *     },
-   *     ...
-   *   ]
-   */
-  createEditorReport: function(url) {
-    if (this._knownRules == null) {
-      return { reports: [] };
-    }
-
-    const reports = [];
-    for (const [ruleId, ruleData] of this._knownRules) {
-      const { url: ruleUrl, line, column } = deconstructRuleId(ruleId);
-      if (ruleUrl !== url || ruleData.isUsed) {
-        continue;
-      }
-
-      const ruleReport = {
-        selectorText: ruleData.selectorText,
-        start: { line: line, column: column },
-      };
-
-      if (ruleData.end) {
-        ruleReport.end = ruleData.end;
-      }
-
-      reports.push(ruleReport);
-    }
-
-    return { reports: reports };
-  },
-
-  /**
-   * Compute the stylesheet URL and delegate the report creation to createEditorReport.
-   * See createEditorReport documentation.
-   *
-   * @param {StyleSheetActor} stylesheetActor
-   *        the stylesheet actor for which the coverage report should be generated.
-   */
-  createEditorReportForSheet: function(stylesheetActor) {
-    const url = sheetToUrl(stylesheetActor.rawSheet);
-    return this.createEditorReport(url);
-  },
-
-  /**
-   * Returns a JSONable structure designed for the page report which shows
-   * the recommended changes to a page.
-   *
-   * "preload" means that a rule is used before the load event happens, which
-   * means that the page could by optimized by placing it in a <style> element
-   * at the top of the page, moving the <link> elements to the bottom.
-   *
-   * Example:
-   *   {
-   *     preload: [
-   *       {
-   *         url: "http://example.org/page1.html",
-   *         shortUrl: "page1.html",
-   *         rules: [
-   *           {
-   *             url: "http://example.org/style1.css",
-   *             shortUrl: "style1.css",
-   *             start: { line: 3, column: 4 },
-   *             selectorText: "p#content",
-   *             formattedCssText: "p#content {\n  color: red;\n }\n"
-   *          },
-   *          ...
-   *         ]
-   *       }
-   *     ],
-   *     unused: [
-   *       {
-   *         url: "http://example.org/style1.css",
-   *         shortUrl: "style1.css",
-   *         rules: [ ... ]
-   *       }
-   *     ]
-   *   }
-   */
-  createPageReport: function() {
-    if (this._running) {
-      throw new Error(l10n.lookup("csscoverageRunningError"));
-    }
-
-    if (this._visitedPages == null) {
-      throw new Error(l10n.lookup("csscoverageNotRunError"));
-    }
-
-    if (this._isOneShot) {
-      throw new Error(l10n.lookup("csscoverageOneShotReportError"));
-    }
-
-    // Helper function to create a JSONable data structure representing a rule
-    const ruleToRuleReport = function(rule, ruleData) {
-      return {
-        url: rule.url,
-        shortUrl: rule.url.split("/").slice(-1)[0],
-        start: { line: rule.line, column: rule.column },
-        selectorText: ruleData.selectorText,
-        formattedCssText: prettifyCSS(ruleData.cssText),
-      };
-    };
-
-    // A count of each type of rule for the bar chart
-    const summary = { used: 0, unused: 0, preload: 0 };
-
-    // Create the set of the unused rules
-    const unusedMap = new Map();
-    for (const [ruleId, ruleData] of this._knownRules) {
-      const rule = deconstructRuleId(ruleId);
-      let rules = unusedMap.get(rule.url);
-      if (rules == null) {
-        rules = [];
-        unusedMap.set(rule.url, rules);
-      }
-      if (!ruleData.isUsed) {
-        const ruleReport = ruleToRuleReport(rule, ruleData);
-        rules.push(ruleReport);
-      } else {
-        summary.unused++;
-      }
-    }
-    const unused = [];
-    for (const [url, rules] of unusedMap) {
-      unused.push({
-        url: url,
-        shortUrl: url.split("/").slice(-1),
-        rules: rules,
-      });
-    }
-
-    // Create the set of rules that could be pre-loaded
-    const preload = [];
-    for (const url of this._visitedPages) {
-      const page = {
-        url: url,
-        shortUrl: url.split("/").slice(-1),
-        rules: [],
-      };
-
-      for (const [ruleId, ruleData] of this._knownRules) {
-        if (ruleData.preLoadOn.has(url)) {
-          const rule = deconstructRuleId(ruleId);
-          const ruleReport = ruleToRuleReport(rule, ruleData);
-          page.rules.push(ruleReport);
-          summary.preload++;
-        } else {
-          summary.used++;
-        }
-      }
-
-      if (page.rules.length > 0) {
-        preload.push(page);
-      }
-    }
-
-    return {
-      summary: summary,
-      preload: preload,
-      unused: unused,
-    };
-  },
-
-  /**
-   * For testing only. What pages did we visit.
-   */
-  _testOnlyVisitedPages: function() {
-    return [...this._visitedPages];
-  },
-});
-
-exports.CSSUsageActor = CSSUsageActor;
-
-/**
- * Generator that filters the CSSRules out of _getAllRules so it only
- * iterates over the CSSStyleRules
- */
-function* getAllSelectorRules(document) {
-  for (const rule of getAllRules(document)) {
-    if (rule.type === CSSRule.STYLE_RULE && rule.selectorText !== "") {
-      yield rule;
-    }
-  }
-}
-
-/**
- * Generator to iterate over the CSSRules in all the stylesheets the
- * current document (i.e. it includes import rules, media rules, etc)
- */
-function* getAllRules(document) {
-  // sheets is an array of the <link> and <style> element in this document
-  const sheets = getAllSheets(document);
-  for (let i = 0; i < sheets.length; i++) {
-    for (let j = 0; j < sheets[i].cssRules.length; j++) {
-      yield sheets[i].cssRules[j];
-    }
-  }
-}
-
-/**
- * Get an array of all the stylesheets that affect this document. That means
- * the <link> and <style> based sheets, and the @imported sheets (recursively)
- * but not the sheets in nested frames.
- */
-function getAllSheets(document) {
-  // sheets is an array of the <link> and <style> element in this document
-  let sheets = Array.slice(document.styleSheets);
-  // Add @imported sheets
-  for (let i = 0; i < sheets.length; i++) {
-    const subSheets = getImportedSheets(sheets[i]);
-    sheets = sheets.concat(...subSheets);
-  }
-  return sheets;
-}
-
-/**
- * Recursively find @import rules in the given stylesheet.
- * We're relying on the browser giving rule.styleSheet == null to resolve
- * @import loops
- */
-function getImportedSheets(stylesheet) {
-  let sheets = [];
-  for (let i = 0; i < stylesheet.cssRules.length; i++) {
-    const rule = stylesheet.cssRules[i];
-    // rule.styleSheet == null with duplicate @imports for the same URL.
-    if (rule.type === CSSRule.IMPORT_RULE && rule.styleSheet != null) {
-      sheets.push(rule.styleSheet);
-      const subSheets = getImportedSheets(rule.styleSheet);
-      sheets = sheets.concat(...subSheets);
-    }
-  }
-  return sheets;
-}
-
-/**
- * Get a unique identifier for a rule. This is currently the string
- * <CSS-URL>|<START-LINE>|<START-COLUMN>
- * @see deconstructRuleId(ruleId)
- */
-function ruleToId(rule) {
-  const line = InspectorUtils.getRelativeRuleLine(rule);
-  const column = InspectorUtils.getRuleColumn(rule);
-  return sheetToUrl(rule.parentStyleSheet) + "|" + line + "|" + column;
-}
-
-/**
- * Convert a ruleId to an object with { url, line, column } properties
- * @see ruleToId(rule)
- */
-const deconstructRuleId = exports.deconstructRuleId = function(ruleId) {
-  const split = ruleId.split("|");
-  if (split.length > 3) {
-    const replace = split.slice(0, split.length - 3 + 1).join("|");
-    split.splice(0, split.length - 3 + 1, replace);
-  }
-  const [ url, line, column ] = split;
-  return {
-    url: url,
-    line: parseInt(line, 10),
-    column: parseInt(column, 10),
-  };
-};
-
-/**
- * We're only interested in the origin and pathname, because changes to the
- * username, password, hash, or query string probably don't significantly
- * change the CSS usage properties of a page.
- * @param document
- */
-const getURL = exports.getURL = function(document) {
-  const url = new document.defaultView.URL(document.documentURI);
-  return url == "about:blank" ? "" : "" + url.origin + url.pathname;
-};
-
-/**
- * Pseudo class handling constants:
- * We split pseudo-classes into a number of categories so we can decide how we
- * should match them. See getTestSelector for how we use these constants.
- *
- * @see http://dev.w3.org/csswg/selectors4/#overview
- * @see https://developer.mozilla.org/en-US/docs/tag/CSS%20Pseudo-class
- * @see https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements
- */
-
-/**
- * Category 1: Pseudo-classes that depend on external browser/OS state
- * This includes things like the time, locale, position of mouse/caret/window,
- * contents of browser history, etc. These can be hard to mimic.
- * Action: Remove from selectors
- */
-const SEL_EXTERNAL = [
-  "active", "active-drop", "current", "dir", "focus", "future", "hover",
-  "invalid-drop", "lang", "past", "placeholder-shown", "target", "valid-drop",
-  "visited",
-];
-
-/**
- * Category 2: Pseudo-classes that depend on user-input state
- * These are pseudo-classes that arguably *should* be covered by unit tests but
- * which probably aren't and which are unlikely to be covered by manual tests.
- * We're currently stripping them out,
- * Action: Remove from selectors (but consider future command line flag to
- * enable them in the future. e.g. 'csscoverage start --strict')
- */
-const SEL_FORM = [
-  "checked", "default", "disabled", "enabled", "fullscreen", "in-range",
-  "indeterminate", "invalid", "optional", "out-of-range", "required", "valid",
-];
-
-/**
- * Category 3: Pseudo-elements
- * querySelectorAll doesn't return matches with pseudo-elements because there
- * is no element to match (they're pseudo) so we have to remove them all.
- * (See http://codepen.io/joewalker/pen/sanDw for a demo)
- * Action: Remove from selectors (including deprecated single colon versions)
- */
-const SEL_ELEMENT = [
-  "after", "before", "first-letter", "first-line", "selection",
-];
-
-/**
- * Category 4: Structural pseudo-classes
- * This is a category defined by the spec (also called tree-structural and
- * grid-structural) for selection based on relative position in the document
- * tree that cannot be represented by other simple selectors or combinators.
- * Action: Require a page-match
- */
-const SEL_STRUCTURAL = [
-  "empty", "first-child", "first-of-type", "last-child", "last-of-type",
-  "nth-column", "nth-last-column", "nth-child", "nth-last-child",
-  "nth-last-of-type", "nth-of-type", "only-child", "only-of-type", "root",
-];
-
-/**
- * Category 4a: Semi-structural pseudo-classes
- * These are not structural according to the spec, but act nevertheless on
- * information in the document tree.
- * Action: Require a page-match
- */
-const SEL_SEMI = [ "any-link", "link", "read-only", "read-write", "scope" ];
-
-/**
- * Category 5: Combining pseudo-classes
- * has(), not() etc join selectors together in various ways. We take care when
- * removing pseudo-classes to convert "not(:hover)" into "not(*)" and so on.
- * With these changes the combining pseudo-classes should probably stand on
- * their own.
- * Action: Require a page-match
- */
-const SEL_COMBINING = [ "not", "has", "matches" ];
-
-/**
- * Category 6: Media pseudo-classes
- * Pseudo-classes that should be ignored because they're only relevant to
- * media queries
- * Action: Don't need removing from selectors as they appear in media queries
- */
-const SEL_MEDIA = [ "blank", "first", "left", "right" ];
-
-/**
- * A test selector is a reduced form of a selector that we actually test
- * against. This code strips out pseudo-elements and some pseudo-classes that
- * we think should not have to match in order for the selector to be relevant.
- */
-function getTestSelector(selector) {
-  let replacement = selector;
-  const replaceSelector = pseudo => {
-    replacement = replacement.replace(" :" + pseudo, " *")
-                             .replace("(:" + pseudo, "(*")
-                             .replace(":" + pseudo, "");
-  };
-
-  SEL_EXTERNAL.forEach(replaceSelector);
-  SEL_FORM.forEach(replaceSelector);
-  SEL_ELEMENT.forEach(replaceSelector);
-
-  // Pseudo elements work in : and :: forms
-  SEL_ELEMENT.forEach(pseudo => {
-    replacement = replacement.replace("::" + pseudo, "");
-  });
-
-  return replacement;
-}
-
-/**
- * I've documented all known pseudo-classes above for 2 reasons: To allow
- * checking logic and what might be missing, but also to allow a unit test
- * that fetches the list of supported pseudo-classes and pseudo-elements from
- * the platform and check that they were all represented here.
- */
-exports.SEL_ALL = [
-  SEL_EXTERNAL, SEL_FORM, SEL_ELEMENT, SEL_STRUCTURAL, SEL_SEMI,
-  SEL_COMBINING, SEL_MEDIA,
-].reduce(function(prev, curr) {
-  return prev.concat(curr);
-}, []);
-
-/**
- * Find a URL for a given stylesheet
- * @param {StyleSheet} stylesheet raw stylesheet
- */
-const sheetToUrl = function(stylesheet) {
-  // For <link> elements
-  if (stylesheet.href) {
-    return stylesheet.href;
-  }
-
-  // For <style> elements
-  if (stylesheet.ownerNode) {
-    const document = stylesheet.ownerNode.ownerDocument;
-    const sheets = [...document.querySelectorAll("style")];
-    const index = sheets.indexOf(stylesheet.ownerNode);
-    return getURL(document) + " → <style> index " + index;
-  }
-
-  throw new Error("Unknown sheet source");
-};
--- a/devtools/server/actors/moz.build
+++ b/devtools/server/actors/moz.build
@@ -23,17 +23,16 @@ DevToolsModules(
     'actor-registry.js',
     'animation-type-longhand.js',
     'animation.js',
     'array-buffer.js',
     'breakpoint.js',
     'changes.js',
     'common.js',
     'css-properties.js',
-    'csscoverage.js',
     'device.js',
     'emulation.js',
     'environment.js',
     'errordocs.js',
     'frame.js',
     'framerate.js',
     'heap-snapshot-file.js',
     'highlighters.css',
@@ -67,19 +66,16 @@ with Files('animation.js'):
     BUG_COMPONENT = ('DevTools', 'Inspector: Animations')
 
 with Files('breakpoint.js'):
     BUG_COMPONENT = ('DevTools', 'Debugger')
 
 with Files('css-properties.js'):
     BUG_COMPONENT = ('DevTools', 'Inspector: Rules')
 
-with Files('csscoverage.js'):
-    BUG_COMPONENT = ('DevTools', 'Graphics Commandline and Toolbar')
-
 with Files('memory.js'):
     BUG_COMPONENT = ('DevTools', 'Memory')
 
 with Files('performance*'):
     BUG_COMPONENT = ('DevTools', 'Performance Tools (Profiler/Timeline)')
 
 with Files('source.js'):
     BUG_COMPONENT = ('DevTools', 'Debugger')
--- a/devtools/server/actors/utils/actor-registry.js
+++ b/devtools/server/actors/utils/actor-registry.js
@@ -188,21 +188,16 @@ const ActorRegistry = {
       constructor: "ReflowActor",
       type: { target: true },
     });
     this.registerModule("devtools/server/actors/css-properties", {
       prefix: "cssProperties",
       constructor: "CssPropertiesActor",
       type: { target: true },
     });
-    this.registerModule("devtools/server/actors/csscoverage", {
-      prefix: "cssUsage",
-      constructor: "CSSUsageActor",
-      type: { target: true },
-    });
     if ("nsIProfiler" in Ci &&
         !Services.prefs.getBoolPref("devtools.performance.new-panel-enabled", false)) {
       this.registerModule("devtools/server/actors/performance", {
         prefix: "performance",
         constructor: "PerformanceActor",
         type: { target: true },
       });
     }
deleted file mode 100644
--- a/devtools/shared/fronts/csscoverage.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const {cssUsageSpec} = require("devtools/shared/specs/csscoverage");
-const { FrontClassWithSpec, registerFront } = require("devtools/shared/protocol");
-
-const {LocalizationHelper} = require("devtools/shared/l10n");
-const L10N = new LocalizationHelper("devtools/shared/locales/csscoverage.properties");
-
-loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
-
-/**
- * Allow: let foo = l10n.lookup("csscoverageFoo");
- */
-const l10n = exports.l10n = {
-  lookup: (msg) => L10N.getStr(msg),
-};
-
-/**
- * Running more than one usage report at a time is probably bad for performance
- * and it isn't particularly useful, and it's confusing from a notification POV
- * so we only allow one.
- */
-var isRunning = false;
-var notification;
-var target;
-var chromeWindow;
-
-/**
- * Front for CSSUsageActor
- */
-class CSSUsageFront extends FrontClassWithSpec(cssUsageSpec) {
-  constructor(client) {
-    super(client);
-    this.before("state-change", this._onStateChange.bind(this));
-
-    // Attribute name from which to retrieve the actorID out of the target actor's form
-    this.formAttributeName = "cssUsageActor";
-  }
-
-  _onStateChange(ev) {
-    isRunning = ev.isRunning;
-    ev.target = target;
-
-    if (isRunning) {
-      const gnb = chromeWindow.gNotificationBox;
-      notification = gnb.getNotificationWithValue("csscoverage-running");
-
-      if (notification == null) {
-        const notifyStop = reason => {
-          if (reason == "removed") {
-            this.stop();
-          }
-        };
-
-        const msg = l10n.lookup("csscoverageRunningReply");
-        notification = gnb.appendNotification(msg, "csscoverage-running",
-                                              "",
-                                              gnb.PRIORITY_INFO_HIGH,
-                                              null,
-                                              notifyStop);
-      }
-    } else {
-      if (notification) {
-        notification.close();
-        notification = undefined;
-      }
-
-      gDevTools.showToolbox(target, "styleeditor");
-      target = undefined;
-    }
-  }
-
-  /**
-   * Server-side start is above. Client-side start adds a notification box
-   */
-  start(newChromeWindow, newTarget, noreload = false) {
-    target = newTarget;
-    chromeWindow = newChromeWindow;
-
-    return super.start(noreload);
-  }
-
-  /**
-   * Server-side start is above. Client-side start adds a notification box
-   */
-  toggle(newChromeWindow, newTarget) {
-    target = newTarget;
-    chromeWindow = newChromeWindow;
-
-    return super.toggle();
-  }
-
-  /**
-   * We count STARTING and STOPPING as 'running'
-   */
-  isRunning() {
-    return isRunning;
-  }
-}
-
-exports.CSSUsageFront = CSSUsageFront;
-registerFront(CSSUsageFront);
--- a/devtools/shared/fronts/moz.build
+++ b/devtools/shared/fronts/moz.build
@@ -12,17 +12,16 @@ DIRS += [
 ]
 
 DevToolsModules(
     'accessibility.js',
     'actor-registry.js',
     'animation.js',
     'changes.js',
     'css-properties.js',
-    'csscoverage.js',
     'device.js',
     'emulation.js',
     'framerate.js',
     'highlighters.js',
     'inspector.js',
     'layout.js',
     'memory.js',
     'node.js',
deleted file mode 100644
--- a/devtools/shared/locales/en-US/csscoverage.dtd
+++ /dev/null
@@ -1,47 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- LOCALIZATION NOTE : FILE This file contains the CSS Coverage Report
-   - strings. See the 'csscoverage' command for more information, and
-   - devtools/client/styleeditor/index.xul for context -->
-
-<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
-   - keep it in English, or another language commonly spoken among web developers.
-   - You want to make that choice consistent across the developer tools.
-   - A good criteria is the language in which you'd find the best
-   - documentation on web development on the web. -->
-
-<!-- LOCALIZATION NOTE (csscoverage.backButton):
-  -  Text on the button to go back to the main style editor -->
-<!ENTITY csscoverage.backButton "Back">
-
-<!-- LOCALIZATION NOTE (csscoverage.unused, csscoverage.noMatches):
-  -  This is the heading and body text for the CSS usage part of the report -->
-<!ENTITY csscoverage.unused "Unused Rules">
-<!ENTITY csscoverage.noMatches "No matches found for the following rules:">
-
-<!-- LOCALIZATION NOTE (csscoverage.optimize.header):
-  -  This is the heading for the CSS optimization part of the report -->
-<!ENTITY csscoverage.optimize.header "Optimizable Pages">
-
-<!-- LOCALIZATION NOTE (csscoverage.preload1, csscoverage.preload2,
-  -  csscoverage.preload3): These 3 are part of a paragraph with 1 and 2
-  -  separated by a styled <link> tag and 2 and 3 separated by a styled
-  -  <style> tag -->
-<!ENTITY csscoverage.optimize.body1 "You can sometimes speed up loading by moving">
-<!ENTITY csscoverage.optimize.body2 "tags to the bottom of the page and creating a new inline">
-<!ENTITY csscoverage.optimize.body3 "element with the styles needed before the ‘load’ event to the top. Here are the style blocks you need:">
-
-<!-- LOCALIZATION NOTE (csscoverage.optimize.bodyX):
-  -  This is what we say when we have no optimization suggestions -->
-<!ENTITY csscoverage.optimize.bodyX "All rules are inlined.">
-
-<!-- LOCALIZATION NOTE (csscoverage.footer1, csscoverage.footer2a,
-  -  csscoverage.footer3, csscoverage.footer4): The text displayed at the
-  -  bottom of the page, with 2a being the URL opened when the link text in 3
-  -  is clicked -->
-<!ENTITY csscoverage.footer1 "See">
-<!ENTITY csscoverage.footer2a "https://developer.mozilla.org/docs/Tools/CSS_Coverage">
-<!ENTITY csscoverage.footer3 "the MDN article on the CSS Coverage Tool">
-<!ENTITY csscoverage.footer4 "for caveats in the generation of this report.">
deleted file mode 100644
--- a/devtools/shared/locales/en-US/csscoverage.properties
+++ /dev/null
@@ -1,32 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# LOCALIZATION NOTE These strings are used in the 'csscoverage' command and in
-# the user interface that this command creates.
-
-# LOCALIZATION NOTE (csscoverageDesc, csscoverageStartDesc2,
-# csscoverageStopDesc2, csscoverageOneShotDesc2, csscoverageToggleDesc2,
-# csscoverageReportDesc2): Short descriptions of the csscoverage commands
-csscoverageDesc=Control CSS coverage analysis
-csscoverageStartDesc2=Begin collecting CSS coverage data
-csscoverageStopDesc2=Stop collecting CSS coverage data
-csscoverageOneShotDesc2=Collect instantaneous CSS coverage data
-csscoverageToggleDesc2=Toggle collecting CSS coverage data
-csscoverageReportDesc2=Show CSS coverage report
-csscoverageStartNoReloadDesc=Don’t start with a page reload
-csscoverageStartNoReloadManual=It’s best if we start by reloading the current page because that starts the test at a known point, but there could be reasons why we don’t want to do that (e.g. the page contains state that will be lost across a reload)
-
-# LOCALIZATION NOTE (csscoverageRunningReply, csscoverageDoneReply): Text that
-# describes the current state of the css coverage system
-csscoverageRunningReply=Running CSS coverage analysis
-csscoverageDoneReply=CSS Coverage analysis completed
-
-# LOCALIZATION NOTE (csscoverageRunningError, csscoverageNotRunningError,
-# csscoverageNotRunError): Error message that describe things that can go wrong
-# with the css coverage system
-csscoverageRunningError=CSS coverage analysis already running
-csscoverageNotRunningError=CSS coverage analysis not running
-csscoverageNotRunError=CSS coverage analysis has not been run
-csscoverageNoRemoteError=Target does not support CSS Coverage
-csscoverageOneShotReportError=CSS coverage report is not available for ‘oneshot’ data. Please use start/stop.
deleted file mode 100644
--- a/devtools/shared/specs/csscoverage.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-const {Arg, RetVal, generateActorSpec} = require("devtools/shared/protocol");
-
-const cssUsageSpec = generateActorSpec({
-  typeName: "cssUsage",
-
-  events: {
-    "state-change": {
-      type: "stateChange",
-      stateChange: Arg(0, "json"),
-    },
-  },
-
-  methods: {
-    start: {
-      request: { url: Arg(0, "boolean") },
-    },
-    stop: {},
-    toggle: {},
-    oneshot: {},
-    createEditorReport: {
-      request: { url: Arg(0, "string") },
-      response: { reports: RetVal("array:json") },
-    },
-    createEditorReportForSheet: {
-      request: { url: Arg(0, "stylesheet") },
-      response: { reports: RetVal("array:json") },
-    },
-    createPageReport: {
-      response: RetVal("json"),
-    },
-    _testOnlyVisitedPages: {
-      response: { value: RetVal("array:string") },
-    },
-  },
-});
-
-exports.cssUsageSpec = cssUsageSpec;
--- a/devtools/shared/specs/index.js
+++ b/devtools/shared/specs/index.js
@@ -48,21 +48,16 @@ const Types = exports.__TypesForTests = 
     front: "devtools/shared/fronts/changes",
   },
   {
     types: ["cssProperties"],
     spec: "devtools/shared/specs/css-properties",
     front: "devtools/shared/fronts/css-properties",
   },
   {
-    types: ["cssUsage"],
-    spec: "devtools/shared/specs/csscoverage",
-    front: "devtools/shared/fronts/csscoverage",
-  },
-  {
     types: ["device"],
     spec: "devtools/shared/specs/device",
     front: "devtools/shared/fronts/device",
   },
   {
     types: ["emulation"],
     spec: "devtools/shared/specs/emulation",
     front: "devtools/shared/fronts/emulation",
--- a/devtools/shared/specs/moz.build
+++ b/devtools/shared/specs/moz.build
@@ -11,17 +11,16 @@ DIRS += [
 ]
 
 DevToolsModules(
     'accessibility.js',
     'actor-registry.js',
     'animation.js',
     'changes.js',
     'css-properties.js',
-    'csscoverage.js',
     'device.js',
     'emulation.js',
     'environment.js',
     'frame.js',
     'framerate.js',
     'heap-snapshot-file.js',
     'highlighters.js',
     'index.js',