Backed out 4 changesets (bug 1464461) for Talos damp failures on webconsole/objectexpand.js. CLOSED TREE
authorCosmin Sabou <csabou@mozilla.com>
Tue, 03 Jul 2018 15:28:03 +0300
changeset 424818 cf26f1c33da6
parent 424817 ce1755e40f5b
child 424819 b94f288b7600
push id65858
push usercsabou@mozilla.com
push dateTue, 03 Jul 2018 12:28:23 +0000
treeherderautoland@cf26f1c33da6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1464461
milestone63.0a1
backs out001370fe21e3
014fa1322e94
50f7f633bb7d
6c9488ed5ebd
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
Backed out 4 changesets (bug 1464461) for Talos damp failures on webconsole/objectexpand.js. CLOSED TREE Backed out changeset 001370fe21e3 (bug 1464461) Backed out changeset 014fa1322e94 (bug 1464461) Backed out changeset 50f7f633bb7d (bug 1464461) Backed out changeset 6c9488ed5ebd (bug 1464461)
devtools/client/webconsole/components/JSTerm.js
devtools/client/webconsole/test/mochitest/browser.ini
devtools/client/webconsole/test/mochitest/browser_jsterm_screenshot_command_clipboard.js
devtools/client/webconsole/test/mochitest/browser_jsterm_screenshot_command_file.js
devtools/client/webconsole/test/mochitest/test_jsterm_screenshot_command.html
devtools/client/webconsole/webconsole-output-wrapper.js
devtools/server/actors/webconsole.js
devtools/server/actors/webconsole/commands.js
devtools/server/actors/webconsole/moz.build
devtools/server/actors/webconsole/screenshot.js
devtools/server/actors/webconsole/utils.js
devtools/server/tests/unit/test_format_command.js
devtools/server/tests/unit/xpcshell.ini
devtools/shared/locales/en-US/screenshot.properties
devtools/shared/webconsole/moz.build
devtools/shared/webconsole/screenshot-helper.js
--- a/devtools/client/webconsole/components/JSTerm.js
+++ b/devtools/client/webconsole/components/JSTerm.js
@@ -14,17 +14,16 @@ loader.lazyRequireGetter(this, "defer", 
 loader.lazyRequireGetter(this, "Debugger", "Debugger");
 loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
 loader.lazyRequireGetter(this, "AutocompletePopup", "devtools/client/shared/autocomplete-popup");
 loader.lazyRequireGetter(this, "PropTypes", "devtools/client/shared/vendor/react-prop-types");
 loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
 loader.lazyRequireGetter(this, "KeyCodes", "devtools/client/shared/keycodes", true);
 loader.lazyRequireGetter(this, "Editor", "devtools/client/sourceeditor/editor");
 loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
-loader.lazyRequireGetter(this, "processScreenshot", "devtools/shared/webconsole/screenshot-helper");
 
 const l10n = require("devtools/client/webconsole/webconsole-l10n");
 
 const HELP_URL = "https://developer.mozilla.org/docs/Tools/Web_Console/Helpers";
 
 function gSequenceId() {
   return gSequenceId.n++;
 }
@@ -327,17 +326,17 @@ class JSTerm extends Component {
    *
    * @private
    * @param function [callback]
    *        Optional function to invoke when the evaluation result is added to
    *        the output.
    * @param object response
    *        The message received from the server.
    */
-  async _executeResultCallback(callback, response) {
+  _executeResultCallback(callback, response) {
     if (!this.hud) {
       return;
     }
     if (response.error) {
       console.error("Evaluation error " + response.error + ": " + response.message);
       return;
     }
     let errorMessage = response.exceptionMessage;
@@ -369,22 +368,16 @@ class JSTerm extends Component {
           }
           break;
         case "help":
           this.hud.owner.openLink(HELP_URL);
           break;
         case "copyValueToClipboard":
           clipboardHelper.copyString(helperResult.value);
           break;
-        case "screenshotOutput":
-          const { args, value } = helperResult;
-          const results = await processScreenshot(this.hud.window, args, value);
-          this.screenshotNotify(results);
-          // early return as screenshot notify has dispatched all necessary messages
-          return;
       }
     }
 
     // Hide undefined results coming from JSTerm helper functions.
     if (!errorMessage && result && typeof result == "object" &&
       result.type == "undefined" &&
       helperResult && !helperHasRawOutput) {
       callback && callback();
@@ -401,21 +394,16 @@ class JSTerm extends Component {
       helperResult: {
         type: "inspectObject",
         object: objectActor
       }
     }, true);
     return this.hud.consoleOutput;
   }
 
-  screenshotNotify(results) {
-    const wrappedResults = results.map(result => ({ result }));
-    this.hud.consoleOutput.dispatchMessagesAdd(wrappedResults);
-  }
-
   /**
    * Execute a string. Execution happens asynchronously in the content process.
    *
    * @param string [executeString]
    *        The string you want to execute. If this is not provided, the current
    *        user input is used - taken from |this.getInputValue()|.
    * @param function [callback]
    *        Optional function to invoke when the result is displayed.
--- a/devtools/client/webconsole/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/test/mochitest/browser.ini
@@ -98,17 +98,16 @@ support-files =
   test-ineffective-iframe-sandbox-warning4.html
   test-ineffective-iframe-sandbox-warning5.html
   test-insecure-frame.html
   test-insecure-passwords-about-blank-web-console-warning.html
   test-insecure-passwords-web-console-warning.html
   test-inspect-cross-domain-objects-frame.html
   test-inspect-cross-domain-objects-top.html
   test-jsterm-dollar.html
-  test_jsterm_screenshot_command.html
   test-local-session-storage.html
   test-location-debugger-link-console-log.js
   test-location-debugger-link-errors.js
   test-location-debugger-link.html
   test-location-styleeditor-link-1.css
   test-location-styleeditor-link-2.css
   test-location-styleeditor-link.html
   test-message-categories-canvas-css.html
@@ -223,20 +222,16 @@ skip-if = os != 'mac' # The tested ctrl+
 [browser_jsterm_instance_of.js]
 [browser_jsterm_multiline.js]
 [browser_jsterm_no_autocompletion_on_defined_variables.js]
 [browser_jsterm_no_input_and_tab_key_pressed.js]
 [browser_jsterm_no_input_change_and_tab_key_pressed.js]
 [browser_jsterm_null_undefined.js]
 [browser_jsterm_popup_close_on_tab_switch.js]
 [browser_jsterm_popup.js]
-[browser_jsterm_screenshot_command_clipboard.js]
-subsuite = clipboard
-[browser_jsterm_screenshot_command_file.js]
-skip-if = (os == 'win') # Bug 1464461, disabled on Win due to timeouts
 [browser_jsterm_selfxss.js]
 subsuite = clipboard
 [browser_webconsole_allow_mixedcontent_securityerrors.js]
 tags = mcb
 [browser_webconsole_batching.js]
 [browser_webconsole_block_mixedcontent_securityerrors.js]
 tags = mcb
 [browser_webconsole_cached_messages.js]
deleted file mode 100644
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_screenshot_command_clipboard.js
+++ /dev/null
@@ -1,209 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Test that screenshot command works properly
-
-"use strict";
-
-const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
-                 "test/mochitest/test_jsterm_screenshot_command.html";
-
-// on some machines, such as macOS, dpr is set to 2. This is expected behavior, however
-// to keep tests consistant across OSs we are setting the dpr to 1
-const dpr = "--dpr 1";
-
-add_task(async function() {
-  const hud = await openNewTabAndConsole(TEST_URI);
-  ok(hud, "web console opened");
-
-  await testClipboard(hud);
-  await testFullpageClipboard(hud);
-  await testSelectorClipboard(hud);
-
-  // overflow
-  await createScrollbarOverflow();
-  await testFullpageClipboardScrollbar(hud);
-});
-
-async function testClipboard(hud) {
-  const command = `:screenshot --clipboard ${dpr}`;
-  const onMessage = waitForMessage(hud, "Screenshot copied to clipboard.");
-  hud.jsterm.execute(command);
-  await onMessage;
-  const contentSize = await getContentSize();
-  const imgSize = await getImageSizeFromClipboard();
-
-  is(imgSize.width, contentSize.innerWidth,
-     "Clipboard: Image width matches window size");
-  is(imgSize.height, contentSize.innerHeight,
-     "Clipboard: Image height matches window size");
-}
-
-async function testFullpageClipboard(hud) {
-  const command = `:screenshot --fullpage --clipboard ${dpr}`;
-  const onMessage = waitForMessage(hud, "Screenshot copied to clipboard.");
-  hud.jsterm.execute(command);
-  await onMessage;
-  const contentSize = await getContentSize();
-  const imgSize = await getImageSizeFromClipboard();
-
-  is(imgSize.width,
-    (contentSize.innerWidth + contentSize.scrollMaxX -
-     contentSize.scrollMinX),
-    "Fullpage Clipboard: Image width matches page size");
-  is(imgSize.height,
-    (contentSize.innerHeight + contentSize.scrollMaxY -
-     contentSize.scrollMinY),
-    "Fullpage Clipboard: Image height matches page size");
-}
-
-async function testSelectorClipboard(hud) {
-  const command = `:screenshot --selector "img#testImage" --clipboard ${dpr}`;
-  const messageReceived = waitForMessage(hud, "Screenshot copied to clipboard.");
-  hud.jsterm.execute(command);
-  await messageReceived;
-  const imgSize1 = await getImageSizeFromClipboard();
-  await ContentTask.spawn(
-    gBrowser.selectedBrowser,
-    imgSize1,
-    function(imgSize) {
-      const img = content.document.querySelector("#testImage");
-      is(imgSize.width, img.clientWidth,
-         "Selector Clipboard: Image width matches element size");
-      is(imgSize.height, img.clientHeight,
-         "Selector Clipboard: Image height matches element size");
-    }
-  );
-}
-
-async function testFullpageClipboardScrollbar(hud) {
-  const command = `:screenshot --fullpage --clipboard ${dpr}`;
-  const onMessage = waitForMessage(hud, "Screenshot copied to clipboard.");
-  hud.jsterm.execute(command);
-  await onMessage;
-  const contentSize = await getContentSize();
-  const scrollbarSize = await getScrollbarSize();
-  const imgSize = await getImageSizeFromClipboard();
-
-  is(imgSize.width,
-    (contentSize.innerWidth + contentSize.scrollMaxX -
-     contentSize.scrollMinX) - scrollbarSize.width,
-    "Scroll Fullpage Clipboard: Image width matches page size minus scrollbar size");
-  is(imgSize.height,
-    (contentSize.innerHeight + contentSize.scrollMaxY -
-     contentSize.scrollMinY) - scrollbarSize.height,
-    "Scroll Fullpage Clipboard: Image height matches page size minus scrollbar size");
-}
-
-async function createScrollbarOverflow() {
-  // Trigger scrollbars by forcing document to overflow
-  // This only affects results on OSes with scrollbars that reduce document size
-  // (non-floating scrollbars).  With default OS settings, this means Windows
-  // and Linux are affected, but Mac is not.  For Mac to exhibit this behavior,
-  // change System Preferences -> General -> Show scroll bars to Always.
-  await ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
-    content.document.body.classList.add("overflow");
-  });
-}
-
-async function getScrollbarSize() {
-  const scrollbarSize = await ContentTask.spawn(
-    gBrowser.selectedBrowser,
-    {},
-    function() {
-      const winUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                              .getInterface(Ci.nsIDOMWindowUtils);
-      const scrollbarHeight = {};
-      const scrollbarWidth = {};
-      winUtils.getScrollbarSize(true, scrollbarWidth, scrollbarHeight);
-      return {
-        width: scrollbarWidth.value,
-        height: scrollbarHeight.value,
-      };
-    }
-  );
-  info(`Scrollbar size: ${scrollbarSize.width}x${scrollbarSize.height}`);
-  return scrollbarSize;
-}
-
-async function getContentSize() {
-  const contentSize = await ContentTask.spawn(
-    gBrowser.selectedBrowser,
-    {},
-    function() {
-      return {
-        scrollMaxY: content.scrollMaxY,
-        scrollMaxX: content.scrollMaxX,
-        scrollMinY: content.scrollMinY,
-        scrollMinX: content.scrollMinX,
-        innerWidth: content.innerWidth,
-        innerHeight: content.innerHeight
-      };
-    }
-  );
-
-  info(`content size: ${contentSize.innerWidth}x${contentSize.innerHeight}`);
-  return contentSize;
-}
-
-async function getImageSizeFromClipboard() {
-  const clipid = Ci.nsIClipboard;
-  const clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
-  const trans = Cc["@mozilla.org/widget/transferable;1"]
-                .createInstance(Ci.nsITransferable);
-  const flavor = "image/png";
-  trans.init(null);
-  trans.addDataFlavor(flavor);
-
-  clip.getData(trans, clipid.kGlobalClipboard);
-  const data = {};
-  const dataLength = {};
-  trans.getTransferData(flavor, data, dataLength);
-
-  ok(data.value, "screenshot exists");
-  ok(dataLength.value > 0, "screenshot has length");
-
-  let image = data.value;
-  let dataURI = `data:${flavor};base64,`;
-
-  // Due to the differences in how images could be stored in the clipboard the
-  // checks below are needed. The clipboard could already provide the image as
-  // byte streams, but also as pointer, or as image container. If it's not
-  // possible obtain a byte stream, the function returns `null`.
-  if (image instanceof Ci.nsISupportsInterfacePointer) {
-    image = image.data;
-  }
-
-  if (image instanceof Ci.imgIContainer) {
-    image = Cc["@mozilla.org/image/tools;1"]
-              .getService(Ci.imgITools)
-              .encodeImage(image, flavor);
-  }
-
-  if (image instanceof Ci.nsIInputStream) {
-    const binaryStream = Cc["@mozilla.org/binaryinputstream;1"]
-                         .createInstance(Ci.nsIBinaryInputStream);
-    binaryStream.setInputStream(image);
-    const rawData = binaryStream.readBytes(binaryStream.available());
-    const charCodes = Array.from(rawData, c => c.charCodeAt(0) & 0xff);
-    let encodedData = String.fromCharCode(...charCodes);
-    encodedData = btoa(encodedData);
-    dataURI = dataURI + encodedData;
-  } else {
-    throw new Error("Unable to read image data");
-  }
-
-  const img = document.createElementNS("http://www.w3.org/1999/xhtml", "img");
-
-  const loaded =  once(img, "load");
-
-  img.src = dataURI;
-  document.documentElement.appendChild(img);
-  await loaded;
-  img.remove();
-
-  return {
-    width: img.width,
-    height: img.height,
-  };
-}
deleted file mode 100644
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_screenshot_command_file.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Test that screenshot command works properly
-
-"use strict";
-
-const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
-                 "test/mochitest/test_jsterm_screenshot_command.html";
-
-const FileUtils = (ChromeUtils.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils;
-// on some machines, such as macOS, dpr is set to 2. This is expected behavior, however
-// to keep tests consistant across OSs we are setting the dpr to 1
-const dpr = "--dpr 1";
-
-add_task(async function() {
-  await addTab(TEST_URI);
-
-  const hud = await openConsole();
-  ok(hud, "web console opened");
-
-  await testFile(hud);
-});
-
-async function testFile(hud) {
-  // Test capture to file
-  const file = FileUtils.getFile("TmpD", [ "TestScreenshotFile.png" ]);
-  const command = `:screenshot ${file.path} ${dpr}`;
-  const onMessage = waitForMessage(hud, `Saved to ${file.path}`);
-  hud.jsterm.execute(command);
-  await onMessage;
-
-  ok(file.exists(), "Screenshot file exists");
-
-  if (file.exists()) {
-    file.remove(false);
-  }
-}
-
deleted file mode 100644
--- a/devtools/client/webconsole/test/mochitest/test_jsterm_screenshot_command.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<html>
-  <head>
-    <style>
-      img {
-        height: 100px;
-        width: 100px;
-      }
-      .overflow {
-        overflow: scroll;
-        height: 200%;
-        width: 200%;
-      }
-    </style>
-  </head>
-  <body>
-    <img id="testImage" ></img>
-  </body>
-</html>
--- a/devtools/client/webconsole/webconsole-output-wrapper.js
+++ b/devtools/client/webconsole/webconsole-output-wrapper.js
@@ -256,22 +256,22 @@ WebConsoleOutputWrapper.prototype = {
             }
           }
         }.bind(this));
       });
     } else {
       promise = Promise.resolve();
     }
 
-    this.batchedMessageAdd(packet);
+    this.batchedMessagesAdd(packet);
     return promise;
   },
 
   dispatchMessagesAdd: function(messages) {
-    this.batchedMessagesAdd(messages);
+    store.dispatch(actions.messagesAdd(messages));
   },
 
   dispatchMessagesClear: function() {
     // We might still have pending message additions and updates when the clear action is
     // triggered, so we need to flush them to make sure we don't have unexpected behavior
     // in the ConsoleOutput.
     this.queuedMessageAdds = [];
     this.queuedMessageUpdates = [];
@@ -368,26 +368,21 @@ WebConsoleOutputWrapper.prototype = {
     this.setTimeoutIfNeeded();
   },
 
   batchedRequestUpdates: function(message) {
     this.queuedRequestUpdates.push(message);
     this.setTimeoutIfNeeded();
   },
 
-  batchedMessageAdd: function(message) {
+  batchedMessagesAdd: function(message) {
     this.queuedMessageAdds.push(message);
     this.setTimeoutIfNeeded();
   },
 
-  batchedMessagesAdd: function(messages) {
-    this.queuedMessageAdds = this.queuedMessageAdds.concat(messages);
-    this.setTimeoutIfNeeded();
-  },
-
   dispatchClearHistory: function() {
     store.dispatch(actions.clearHistory());
   },
 
   /**
    * Returns a Promise that resolves once any async dispatch is finally dispatched.
    */
   waitAsyncDispatches: function() {
--- a/devtools/server/actors/webconsole.js
+++ b/devtools/server/actors/webconsole.js
@@ -22,18 +22,16 @@ loader.lazyRequireGetter(this, "NetworkM
 loader.lazyRequireGetter(this, "NetworkMonitorChild", "devtools/shared/webconsole/network-monitor", true);
 loader.lazyRequireGetter(this, "NetworkEventActor", "devtools/server/actors/network-event", true);
 loader.lazyRequireGetter(this, "ConsoleProgressListener", "devtools/shared/webconsole/network-monitor", true);
 loader.lazyRequireGetter(this, "StackTraceCollector", "devtools/shared/webconsole/network-monitor", true);
 loader.lazyRequireGetter(this, "JSPropertyProvider", "devtools/shared/webconsole/js-property-provider", true);
 loader.lazyRequireGetter(this, "Parser", "resource://devtools/shared/Parser.jsm", true);
 loader.lazyRequireGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm", true);
 loader.lazyRequireGetter(this, "addWebConsoleCommands", "devtools/server/actors/webconsole/utils", true);
-loader.lazyRequireGetter(this, "formatCommand", "devtools/server/actors/webconsole/commands", true);
-loader.lazyRequireGetter(this, "isCommand", "devtools/server/actors/webconsole/commands", true);
 loader.lazyRequireGetter(this, "CONSOLE_WORKER_IDS", "devtools/server/actors/webconsole/utils", true);
 loader.lazyRequireGetter(this, "WebConsoleUtils", "devtools/server/actors/webconsole/utils", true);
 loader.lazyRequireGetter(this, "EnvironmentActor", "devtools/server/actors/environment", true);
 loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
 
 // Overwrite implemented listeners for workers so that we don't attempt
 // to load an unsupported module.
 if (isWorker) {
@@ -872,17 +870,16 @@ WebConsoleActor.prototype =
     };
   },
 
   /**
    * Handler for the "evaluateJSAsync" request. This method evaluates the given
    * JavaScript string and sends back a packet with a unique ID.
    * The result will be returned later as an unsolicited `evaluationResult`,
    * that can be associated back to this request via the `resultID` field.
-   * Cannot be async, see Comment two on Bug #1452920
    *
    * @param object request
    *        The JSON request object received from the Web Console client.
    * @return object
    *         The response packet to send to with the unique id in the
    *         `resultID` field.
    */
   evaluateJSAsync: function(request) {
@@ -895,49 +892,16 @@ WebConsoleActor.prototype =
       from: this.actorID,
       resultID: resultID
     });
 
     // Then, execute the script that may pause.
     const response = this.evaluateJS(request);
     response.resultID = resultID;
 
-    this._waitForHelperResultAndSend(response).catch(e =>
-      DevToolsUtils.reportException(
-        "evaluateJSAsync",
-        Error(`Encountered error while waiting for Helper Result: ${e}`)
-      )
-    );
-  },
-
-  /**
-   * In order to have asynchronous commands such as screenshot, we have to be
-   * able to handle promises in the helper result. This method handles waiting
-   * for the promise, and then dispatching the result
-   *
-   *
-   * @private
-   * @param object response
-   *         The response packet to send to with the unique id in the
-   *         `resultID` field, and potentially a promise in the helperResult
-   *         field.
-   *
-   * @return object
-   *         The response packet to send to with the unique id in the
-   *         `resultID` field, with a sanitized helperResult field.
-   */
-  _waitForHelperResultAndSend: async function(response) {
-    // Wait for asynchronous command completion before sending back the response
-    if (
-      response.helperResult &&
-      typeof response.helperResult.then == "function"
-    ) {
-      response.helperResult = await response.helperResult;
-    }
-
     // Finally, send an unsolicited evaluationResult packet with
     // the normal return value
     this.conn.sendActorEvent(this.actorID, "evaluationResult", response);
   },
 
   /**
    * Handler for the "evaluateJS" request. This method evaluates the given
    * JavaScript string and sends back the result.
@@ -1119,23 +1083,18 @@ WebConsoleActor.prototype =
       if (!this._webConsoleCommandsCache) {
         const helpers = {
           sandbox: Object.create(null)
         };
         addWebConsoleCommands(helpers);
         this._webConsoleCommandsCache =
           Object.getOwnPropertyNames(helpers.sandbox);
       }
-
       matches = matches.concat(this._webConsoleCommandsCache
-          .filter(n =>
-            // filter out `screenshot` command as it is inaccessible without
-            // the `:` prefix
-            n !== "screenshot" && n.startsWith(result.matchProp)
-          ));
+          .filter(n => n.startsWith(result.matchProp)));
     }
 
     return {
       from: this.actorID,
       matches: matches.sort(),
       matchProp: result.matchProp,
     };
   },
@@ -1332,26 +1291,16 @@ WebConsoleActor.prototype =
   /* eslint-disable complexity */
   evalWithDebugger: function(string, options = {}) {
     const trimmedString = string.trim();
     // The help function needs to be easy to guess, so we make the () optional.
     if (trimmedString == "help" || trimmedString == "?") {
       string = "help()";
     }
 
-    const isCmd = isCommand(string);
-    // we support Unix like syntax for commands if it is preceeded by `:`
-    if (isCmd) {
-      try {
-        string = formatCommand(string);
-      } catch (e) {
-        string = `throw "${e}"`;
-      }
-    }
-
     // Add easter egg for console.mihai().
     if (trimmedString == "console.mihai()" || trimmedString == "console.mihai();") {
       string = "\"http://incompleteness.me/blog/2015/02/09/console-dot-mihai/\"";
     }
 
     // Find the Debugger.Frame of the given FrameActor.
     let frame = null, frameActor = null;
     if (options.frameActor) {
@@ -1415,47 +1364,37 @@ WebConsoleActor.prototype =
       if (actor) {
         helpers.selectedNode = actor.rawNode;
       }
     }
 
     // Check if the Debugger.Frame or Debugger.Object for the global include
     // $ or $$. We will not overwrite these functions with the Web Console
     // commands.
-    let found$ = false, found$$ = false, disableScreenshot = false;
-    // do not override command functions if we are using the command key `:`
-    // before the command string
-    if (!isCmd) {
-      // if we do not have the command key as a prefix, screenshot is disabled by default
-      disableScreenshot = true;
-      if (frame) {
-        const env = frame.environment;
-        if (env) {
-          found$ = !!env.find("$");
-          found$$ = !!env.find("$$");
-        }
-      } else {
-        found$ = !!dbgWindow.getOwnPropertyDescriptor("$");
-        found$$ = !!dbgWindow.getOwnPropertyDescriptor("$$");
+    let found$ = false, found$$ = false;
+    if (frame) {
+      const env = frame.environment;
+      if (env) {
+        found$ = !!env.find("$");
+        found$$ = !!env.find("$$");
       }
+    } else {
+      found$ = !!dbgWindow.getOwnPropertyDescriptor("$");
+      found$$ = !!dbgWindow.getOwnPropertyDescriptor("$$");
     }
 
-    let $ = null, $$ = null, screenshot = null;
+    let $ = null, $$ = null;
     if (found$) {
       $ = bindings.$;
       delete bindings.$;
     }
     if (found$$) {
       $$ = bindings.$$;
       delete bindings.$$;
     }
-    if (disableScreenshot) {
-      screenshot = bindings.screenshot;
-      delete bindings.screenshot;
-    }
 
     // Ready to evaluate the string.
     helpers.evalInput = string;
 
     let evalOptions;
     if (typeof options.url == "string") {
       evalOptions = { url: options.url };
     }
@@ -1548,19 +1487,16 @@ WebConsoleActor.prototype =
     delete helpers.selectedNode;
 
     if ($) {
       bindings.$ = $;
     }
     if ($$) {
       bindings.$$ = $$;
     }
-    if (screenshot) {
-      bindings.screenshot = screenshot;
-    }
 
     if (bindings._self) {
       delete bindings._self;
     }
 
     return {
       result: result,
       helperResult: helperResult,
deleted file mode 100644
--- a/devtools/server/actors/webconsole/commands.js
+++ /dev/null
@@ -1,227 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* 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 validCommands = ["help", "screenshot"];
-
-const COMMAND = "command";
-const KEY = "key";
-const ARG = "arg";
-
-const COMMAND_PREFIX = /^:/;
-const KEY_PREFIX = /^--/;
-
-// default value for flags
-const DEFAULT_VALUE = true;
-const COMMAND_DEFAULT_FLAG = {
-  screenshot: "filename"
-};
-
-/**
- * When given a string that begins with `:` and a unix style string,
- * format a JS like object.
- * This is intended to be used by the WebConsole actor only.
- *
- * @param String string
- *        A string to format that begins with `:`.
- *
- * @returns String formatted as `command({ ..args })`
- */
-function formatCommand(string) {
-  if (!isCommand(string)) {
-    throw Error("formatCommand was called without `:`");
-  }
-  const tokens = string.trim().split(/\s+/).map(createToken);
-  const { command, args } = parseCommand(tokens);
-  const argsString = formatArgs(args);
-  return `${command}(${argsString})`;
-}
-
-/**
- * collapses the array of arguments from the parsed command into
- * a single string
- *
- * @param Object tree
- *               A tree object produced by parseCommand
- *
- * @returns String formatted as ` { key: value, ... } ` or an empty string
- */
-function formatArgs(args) {
-  return Object.keys(args).length ?
-    JSON.stringify(args) :
-    "";
-}
-
-/**
- * creates a token object depending on a string which as a prefix,
- * either `:` for a command or `--` for a key, or nothing for an argument
- *
- * @param String string
- *               A string to use as the basis for the token
- *
- * @returns Object Token Object, with the following shape
- *                { type: String, value: String }
- */
-function createToken(string) {
-  if (isCommand(string)) {
-    const value = string.replace(COMMAND_PREFIX, "");
-    if (!value || !validCommands.includes(value)) {
-      throw Error(`'${value}' is not a valid command`);
-    }
-    return { type: COMMAND, value };
-  }
-  if (isKey(string)) {
-    const value = string.replace(KEY_PREFIX, "");
-    if (!value) {
-      throw Error("invalid flag");
-    }
-    return { type: KEY, value };
-  }
-  return { type: ARG, value: string };
-}
-
-/**
- * returns a command Tree object for a set of tokens
- *
- *
- * @param Array Tokens tokens
- *                     An array of Token objects
- *
- * @returns Object Tree Object, with the following shape
- *                 { command: String, args: Array of Strings }
- */
-function parseCommand(tokens) {
-  let command = null;
-  const args = {};
-
-  for (let i = 0; i < tokens.length; i++) {
-    const token = tokens[i];
-    if (token.type === COMMAND) {
-      if (command) {
-        // we are throwing here because two commands have been passed and it is unclear
-        // what the user's intention was
-        throw Error("Invalid command");
-      }
-      command = token.value;
-    }
-
-    if (token.type === KEY) {
-      const nextTokenIndex = i + 1;
-      const nextToken = tokens[nextTokenIndex];
-      let values = args[token.value] || DEFAULT_VALUE;
-      if (nextToken && nextToken.type === ARG) {
-        const { value, offset } = collectString(nextToken, tokens, nextTokenIndex);
-        // in order for JSON.stringify to correctly output values, they must be correctly
-        // typed
-        // As per the GCLI documentation, we can only have one value associated with a
-        // flag but multiple flags with the same name can exist and should be combined
-        // into and array.  Here we are associating only the value on the right hand
-        // side if it is of type `arg` as a single value; the second case initializes
-        // an array, and the final case pushes a value to an existing array
-        const typedValue = getTypedValue(value);
-        if (values === DEFAULT_VALUE) {
-          values = typedValue;
-        } else if (!Array.isArray(values)) {
-          values = [values, typedValue];
-        } else {
-          values.push(typedValue);
-        }
-        // skip the next token since we have already consumed it
-        i = nextTokenIndex + offset;
-      }
-      args[token.value] = values;
-    }
-
-    // Since this has only been implemented for screenshot, we can only have one default
-    // value. Eventually we may have more default values. For now, ignore multiple
-    // unflagged args
-    const defaultFlag = COMMAND_DEFAULT_FLAG[command];
-    if (token.type === ARG && !args[defaultFlag]) {
-      const { value, offset } = collectString(token, tokens, i);
-      args[defaultFlag] = getTypedValue(value);
-      i = i + offset;
-    }
-  }
-  return { command, args };
-}
-
-const stringChars = ["\"", "'", "`"];
-function isStringChar(testChar) {
-  return stringChars.includes(testChar);
-}
-
-function checkLastChar(string, testChar) {
-  const lastChar = string[string.length - 1];
-  return lastChar === testChar;
-}
-
-function hasUnexpectedChar(value, char, rightOffset, leftOffset) {
-  const lastPos = value.length - 1;
-  value.slice(rightOffset, lastPos - leftOffset).includes(char);
-}
-
-function collectString(token, tokens, index) {
-  const firstChar = token.value[0];
-  const isString = isStringChar(firstChar);
-  let value = token.value;
-
-  // the test value is not a string, or it is a string but a complete one
-  // i.e. `"test"`, as opposed to `"foo`. In either case, this we can return early
-  if (!isString || checkLastChar(value, firstChar)) {
-    return { value, offset: 0 };
-  }
-
-  if (hasUnexpectedChar(value, firstChar, 1, 0)) {
-    throw Error(`String contains unexpected ${firstChar} character`);
-  }
-
-  let offset = null;
-  for (let i = index + 1; i <= tokens.length; i++) {
-    if (i === tokens.length) {
-      throw Error("String does not terminate");
-    }
-
-    const nextToken = tokens[i];
-    if (nextToken.type !== ARG) {
-      throw Error(`String does not terminate before flag ${nextToken.value}`);
-    }
-
-    if (hasUnexpectedChar(nextToken.value, firstChar, 0, 1)) {
-      throw Error(`String contains unexpected ${firstChar} character`);
-    }
-
-    value = `${value} ${nextToken.value}`;
-    if (checkLastChar(nextToken.value, firstChar)) {
-      offset = i - index;
-      break;
-    }
-  }
-  return { value, offset };
-}
-
-function isCommand(string) {
-  return COMMAND_PREFIX.test(string);
-}
-
-function isKey(string) {
-  return KEY_PREFIX.test(string);
-}
-
-function getTypedValue(value) {
-  if (!isNaN(value)) {
-    return Number(value);
-  }
-  if (value === "true" || value === "false") {
-    return Boolean(value);
-  }
-  if (isStringChar(value[0])) {
-    return value.slice(1, value.length - 1);
-  }
-  return value;
-}
-
-exports.formatCommand = formatCommand;
-exports.isCommand = isCommand;
--- a/devtools/server/actors/webconsole/moz.build
+++ b/devtools/server/actors/webconsole/moz.build
@@ -1,14 +1,12 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DevToolsModules(
-    'commands.js',
     'content-process-forward.js',
     'listeners.js',
-    'screenshot.js',
     'utils.js',
     'worker-listeners.js',
 )
deleted file mode 100644
--- a/devtools/server/actors/webconsole/screenshot.js
+++ /dev/null
@@ -1,141 +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, Cu } = require("chrome");
-const { getRect } = require("devtools/shared/layout/utils");
-const { LocalizationHelper } = require("devtools/shared/l10n");
-
-const CONTAINER_FLASHING_DURATION = 500;
-const STRINGS_URI = "devtools/shared/locales/screenshot.properties";
-const L10N = new LocalizationHelper(STRINGS_URI);
-
-exports.screenshot = function takeAsyncScreenshot(owner, args = {}) {
-  if (args.help) {
-    // Early return as help will be handled on the client side.
-    return null;
-  }
-  return captureScreenshot(args, owner.window.document);
-};
-
-/**
- * This function is called to simulate camera effects
- */
-function simulateCameraFlash(document) {
-  const window = document.defaultView;
-  const frames = Cu.cloneInto({ opacity: [ 0, 1 ] }, window);
-  document.documentElement.animate(frames, CONTAINER_FLASHING_DURATION);
-}
-
-/**
- * This function simply handles the --delay argument before calling
- * createScreenshotData
- */
-function captureScreenshot(args, document) {
-  if (args.delay > 0) {
-    return new Promise((resolve, reject) => {
-      document.defaultView.setTimeout(() => {
-        createScreenshotData(document, args).then(resolve, reject);
-      }, args.delay * 1000);
-    });
-  }
-  return createScreenshotData(document, args);
-}
-
-/**
- * This does the dirty work of creating a base64 string out of an
- * area of the browser window
- */
-function createScreenshotData(document, args) {
-  const window = document.defaultView;
-  let left = 0;
-  let top = 0;
-  let width;
-  let height;
-  const currentX = window.scrollX;
-  const currentY = window.scrollY;
-
-  let filename = getFilename(args.filename);
-
-  if (args.fullpage) {
-    // Bug 961832: GCLI screenshot shows fixed position element in wrong
-    // position if we don't scroll to top
-    window.scrollTo(0, 0);
-    width = window.innerWidth + window.scrollMaxX - window.scrollMinX;
-    height = window.innerHeight + window.scrollMaxY - window.scrollMinY;
-    filename = filename.replace(".png", "-fullpage.png");
-  } else if (args.selector) {
-    const node = window.document.querySelector(args.selector);
-    ({ top, left, width, height } = getRect(window, node, window));
-  } else {
-    left = window.scrollX;
-    top = window.scrollY;
-    width = window.innerWidth;
-    height = window.innerHeight;
-  }
-
-  // Only adjust for scrollbars when considering the full window
-  if (!args.selector) {
-    const winUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDOMWindowUtils);
-    const scrollbarHeight = {};
-    const scrollbarWidth = {};
-    winUtils.getScrollbarSize(false, scrollbarWidth, scrollbarHeight);
-    width -= scrollbarWidth.value;
-    height -= scrollbarHeight.value;
-  }
-
-  const canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
-  const ctx = canvas.getContext("2d");
-  const ratio = args.dpr ? args.dpr : window.devicePixelRatio;
-  canvas.width = width * ratio;
-  canvas.height = height * ratio;
-  ctx.scale(ratio, ratio);
-  ctx.drawWindow(window, left, top, width, height, "#fff");
-  const data = canvas.toDataURL("image/png", "");
-
-  // See comment above on bug 961832
-  if (args.fullpage) {
-    window.scrollTo(currentX, currentY);
-  }
-
-  simulateCameraFlash(document);
-
-  return Promise.resolve({
-    destinations: [],
-    data: data,
-    height: height,
-    width: width,
-    filename: filename,
-  });
-}
-
-/**
- * We may have a filename specified in args, or we might have to generate
- * one.
- */
-function getFilename(defaultName) {
-  // Create a name for the file if not present
-  if (defaultName) {
-    return defaultName;
-  }
-
-  const date = new Date();
-  let dateString = date.getFullYear() + "-" + (date.getMonth() + 1) +
-                  "-" + date.getDate();
-  dateString = dateString.split("-").map(function(part) {
-    if (part.length == 1) {
-      part = "0" + part;
-    }
-    return part;
-  }).join("-");
-
-  const timeString = date.toTimeString().replace(/:/g, ".").split(" ")[0];
-  return L10N.getFormatStr(
-    "screenshotGeneratedFilename",
-    dateString,
-    timeString
-  ) + ".png";
-}
--- a/devtools/server/actors/webconsole/utils.js
+++ b/devtools/server/actors/webconsole/utils.js
@@ -1,19 +1,18 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft= javascript ts=2 et sw=2 tw=80: */
 /* 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, Cu} = require("chrome");
 
-loader.lazyRequireGetter(this, "screenshot", "devtools/server/actors/webconsole/screenshot", true);
-
 // Note that this is only used in WebConsoleCommands, see $0 and pprint().
 if (!isWorker) {
   loader.lazyImporter(this, "VariablesView", "resource://devtools/client/shared/widgets/VariablesView.jsm");
 }
 
 const CONSOLE_WORKER_IDS = exports.CONSOLE_WORKER_IDS = [
   "SharedWorker",
   "ServiceWorker",
@@ -589,38 +588,16 @@ WebConsoleCommands._registerOriginal("co
   }
   owner.helperResult = {
     type: "copyValueToClipboard",
     value: payload,
   };
 });
 
 /**
- * Take a screenshot of a page.
- *
- * @param object args
- *               The arguments to be passed to the screenshot
- * @return void
- */
-WebConsoleCommands._registerOriginal("screenshot", function(owner, args) {
-  owner.helperResult = (async () => {
-    // creates data for saving the screenshot
-    const value = await screenshot(owner, args);
-    return {
-      type: "screenshotOutput",
-      value,
-      // pass args through to the client, so that the client can take care of copying
-      // and saving the screenshot data on the client machine instead of on the
-      // remote machine
-      args
-    };
-  })();
-});
-
-/**
  * (Internal only) Add the bindings to |owner.sandbox|.
  * This is intended to be used by the WebConsole actor only.
   *
   * @param object owner
   *        The owning object.
   */
 function addWebConsoleCommands(owner) {
   // Not supporting extra commands in workers yet.  This should be possible to
deleted file mode 100644
--- a/devtools/server/tests/unit/test_format_command.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-/* eslint-disable no-shadow, max-nested-callbacks */
-
-"use strict";
-
-const { formatCommand } = require("devtools/server/actors/webconsole/commands.js");
-
-const testcases = [
-  { input: ":help", expectedOutput: "help()" },
-  {
-    input: ":screenshot  --fullscreen",
-    expectedOutput: "screenshot({\"fullscreen\":true})"
-  },
-  {
-    input: ":screenshot  --fullscreen true",
-    expectedOutput: "screenshot({\"fullscreen\":true})"
-  },
-  { input: ":screenshot  ", expectedOutput: "screenshot()" },
-  {
-    input: ":screenshot --dpr 0.5 --fullpage --chrome",
-    expectedOutput: "screenshot({\"dpr\":0.5,\"fullpage\":true,\"chrome\":true})"
-  },
-  {
-    input: ":screenshot 'filename'",
-    expectedOutput: "screenshot({\"filename\":\"filename\"})"
-  },
-  {
-    input: ":screenshot filename",
-    expectedOutput: "screenshot({\"filename\":\"filename\"})"
-  },
-  {
-    input: ":screenshot --name 'filename' --name `filename` --name \"filename\"",
-    expectedOutput: "screenshot({\"name\":[\"filename\",\"filename\",\"filename\"]})"
-  },
-  {
-    input: ":screenshot 'filename1' 'filename2' 'filename3'",
-    expectedOutput: "screenshot({\"filename\":\"filename1\"})"
-  },
-  {
-    input: ":screenshot --chrome --chrome",
-    expectedOutput: "screenshot({\"chrome\":true})"
-  },
-  {
-    input: ":screenshot \"file name with spaces\"",
-    expectedOutput: "screenshot({\"filename\":\"file name with spaces\"})"
-  },
-  {
-    input: ":screenshot 'filename1' --name 'filename2'",
-    expectedOutput: "screenshot({\"filename\":\"filename1\",\"name\":\"filename2\"})"
-  },
-  {
-    input: ":screenshot --name 'filename1' 'filename2'",
-    expectedOutput: "screenshot({\"name\":\"filename1\",\"filename\":\"filename2\"})"
-  },
-  {
-    input: ":screenshot \"fo\\\"o bar\"",
-    expectedOutput: "screenshot({\"filename\":\"fo\\\\\\\"o bar\"})"
-  },
-  {
-    input: ":screenshot \"foo b\\\"ar\"",
-    expectedOutput: "screenshot({\"filename\":\"foo b\\\\\\\"ar\"})"
-  }
-];
-
-const edgecases = [
-  { input: ":", expectedError: "'' is not a valid command" },
-  { input: ":invalid", expectedError: "'invalid' is not a valid command" },
-  { input: ":screenshot :help", expectedError: "invalid command" },
-  { input: ":screenshot --", expectedError: "invalid flag" },
-  {
-    input: ":screenshot \"fo\"o bar",
-    expectedError: "String contains unexpected `\"` character"
-  },
-  {
-    input: ":screenshot \"foo b\"ar",
-    expectedError: "String contains unexpected `\"` character"
-  },
-  { input: ": screenshot", expectedError: "'' is not a valid command" },
-  { input: ":screenshot \"file name", expectedError: "String does not terminate" },
-  {
-    input: ":screenshot \"file name --clipboard",
-    expectedError: "String does not terminate before flag \"clipboard\""
-  },
-  { input: "::screenshot", expectedError: "':screenshot' is not a valid command" }
-];
-
-function run_test() {
-  testcases.forEach(testcase => {
-    Assert.equal(formatCommand(testcase.input), testcase.expectedOutput);
-  });
-
-  edgecases.forEach(testcase => {
-    Assert.throws(() => formatCommand(testcase.input), testcase.expectedError);
-  });
-}
--- a/devtools/server/tests/unit/xpcshell.ini
+++ b/devtools/server/tests/unit/xpcshell.ini
@@ -81,17 +81,16 @@ skip-if = (verify && !debug && (os == 'w
 [test_frameclient-02.js]
 [test_nativewrappers.js]
 [test_nodelistactor.js]
 [test_eval-01.js]
 [test_eval-02.js]
 [test_eval-03.js]
 [test_eval-04.js]
 [test_eval-05.js]
-[test_format_command.js]
 [test_promises_actor_attach.js]
 [test_promises_actor_exist.js]
 [test_promises_actor_list_promises.js]
 skip-if = coverage # bug 1336670
 [test_promises_actor_onnewpromise.js]
 [test_promises_actor_onpromisesettled.js]
 [test_promises_client_getdependentpromises.js]
 [test_promises_object_creationtimestamp.js]
deleted file mode 100644
--- a/devtools/shared/locales/en-US/screenshot.properties
+++ /dev/null
@@ -1,116 +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 inside Web Console commands.
-# The Web Console command line is available from the Web Developer sub-menu
-# -> 'Web Console'.
-#
-# 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 (screenshotDesc) A very short description of the
-# 'screenshot' command. Displayed when the --help flag is passed to
-# the screenshot command.
-screenshotDesc=Save an image of the page
-
-# LOCALIZATION NOTE (screenshotFilenameDesc) A very short string to describe
-# the 'filename' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the screenshot command.
-screenshotFilenameDesc=Destination filename
-
-# LOCALIZATION NOTE (screenshotFilenameManual) A fuller description of the
-# 'filename' parameter to the 'screenshot' command.
-screenshotFilenameManual=The name of the file (should have a ‘.png’ extension) to which we write the screenshot.
-
-# LOCALIZATION NOTE (screenshotClipboardDesc) A very short string to describe
-# the 'clipboard' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the screenshot command.
-screenshotClipboardDesc=Copy screenshot to clipboard? (true/false)
-
-# LOCALIZATION NOTE (screenshotClipboardManual) A fuller description of the
-# 'clipboard' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the screenshot command.
-screenshotClipboardManual=True if you want to copy the screenshot instead of saving it to a file.
-
-# LOCALIZATION NOTE (screenshotGroupOptions) A label for the optional options of
-# the screenshot command. Displayed when the --help flag is passed to the
-# screenshot command.
-screenshotGroupOptions=Options
-
-# LOCALIZATION NOTE (screenshotDelayDesc) A very short string to describe
-# the 'delay' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the screenshot command.
-screenshotDelayDesc=Delay (seconds)
-
-# LOCALIZATION NOTE (screenshotDelayManual) A fuller description of the
-# 'delay' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the screenshot command.
-screenshotDelayManual=The time to wait (in seconds) before the screenshot is taken
-
-# LOCALIZATION NOTE (screenshotDPRDesc) A very short string to describe
-# the 'dpr' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the `screenshot command.
-screenshotDPRDesc=Device pixel ratio
-
-# LOCALIZATION NOTE (screenshotDPRManual) A fuller description of the
-# 'dpr' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the `screenshot command.
-screenshotDPRManual=The device pixel ratio to use when taking the screenshot
-
-# LOCALIZATION NOTE (screenshotFullPageDesc) A very short string to describe
-# the 'fullpage' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the `screenshot command.
-screenshotFullPageDesc=Entire webpage? (true/false)
-
-# LOCALIZATION NOTE (screenshotFullPageManual) A fuller description of the
-# 'fullpage' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the `screenshot command.
-screenshotFullPageManual=True if the screenshot should also include parts of the webpage which are outside the current scrolled bounds.
-
-# LOCALIZATION NOTE (screenshotFileDesc) A very short string to describe
-# the 'file' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the `screenshot command.
-screenshotFileDesc=Save to file? (true/false)
-
-# LOCALIZATION NOTE (screenshotFileManual) A fuller description of the
-# 'file' parameter to the 'screenshot' command. Displayed when the
-# --help flag is passed to the `screenshot command.
-screenshotFileManual=True if the screenshot should save the file even when other options are enabled (eg. clipboard).
-
-# LOCALIZATION NOTE (screenshotGeneratedFilename) The auto generated filename
-# when no file name is provided. The first argument (%1$S) is the date string
-# in yyyy-mm-dd format and the second argument (%2$S) is the time string
-# in HH.MM.SS format. Please don't add the extension here.
-screenshotGeneratedFilename=Screen Shot %1$S at %2$S
-
-# LOCALIZATION NOTE (screenshotErrorSavingToFile) Text displayed to user upon
-# encountering error while saving the screenshot to the file specified.
-# The argument (%1$S) is the filename.
-screenshotErrorSavingToFile=Error saving to %1$S
-
-# LOCALIZATION NOTE (screenshotSavedToFile) Text displayed to user when the
-# screenshot is successfully saved to the file specified.
-# The argument (%1$S) is the filename.
-screenshotSavedToFile=Saved to %1$S
-
-# LOCALIZATION NOTE (screenshotErrorCopying) Text displayed to user upon
-# encountering error while copying the screenshot to clipboard.
-screenshotErrorCopying=Error occurred while copying screenshot to clipboard.
-
-# LOCALIZATION NOTE (screenshotCopied) Text displayed to user when the
-# screenshot is successfully copied to the clipboard.
-screenshotCopied=Screenshot copied to clipboard.
-
-# LOCALIZATION NOTE (inspectNodeDesc) A very short string to describe the
-# 'node' parameter to the 'inspect' command. Displayed when the
-# --help flag is passed to the `screenshot command.
-inspectNodeDesc=CSS selector
-
-# LOCALIZATION NOTE (inspectNodeManual) A fuller description of the 'node'
-# parameter to the 'inspect' command. Displayed when the --help flag is
-# passed to the `screenshot command.
-inspectNodeManual=A CSS selector for use with document.querySelector which identifies a single element
--- a/devtools/shared/webconsole/moz.build
+++ b/devtools/shared/webconsole/moz.build
@@ -8,11 +8,10 @@ if CONFIG['OS_TARGET'] != 'Android':
     MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
     XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
 DevToolsModules(
     'client.js',
     'js-property-provider.js',
     'network-helper.js',
     'network-monitor.js',
-    'screenshot-helper.js',
     'throttle.js',
 )
deleted file mode 100644
--- a/devtools/shared/webconsole/screenshot-helper.js
+++ /dev/null
@@ -1,396 +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 { Cc, Ci, Cr } = require("chrome");
-const ChromeUtils = require("ChromeUtils");
-const { LocalizationHelper } = require("devtools/shared/l10n");
-const Services = require("Services");
-const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
-
-loader.lazyImporter(this, "Downloads", "resource://gre/modules/Downloads.jsm");
-loader.lazyImporter(this, "OS", "resource://gre/modules/osfile.jsm");
-loader.lazyImporter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm");
-loader.lazyImporter(this, "PrivateBrowsingUtils",
-                          "resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-const STRINGS_URI = "devtools/shared/locales/screenshot.properties";
-const L10N = new LocalizationHelper(STRINGS_URI);
-
-const screenshotDescription = L10N.getStr("screenshotDesc");
-const screenshotGroupOptions = L10N.getStr("screenshotGroupOptions");
-const screenshotCommandParams = [
-  {
-    name: "clipboard",
-    type: "boolean",
-    description: L10N.getStr("screenshotClipboardDesc"),
-    manual: L10N.getStr("screenshotClipboardManual")
-  },
-  {
-    name: "delay",
-    type: "number",
-    description: L10N.getStr("screenshotDelayDesc"),
-    manual: L10N.getStr("screenshotDelayManual")
-  },
-  {
-    name: "dpr",
-    type: "number",
-    description: L10N.getStr("screenshotDPRDesc"),
-    manual: L10N.getStr("screenshotDPRManual")
-  },
-  {
-    name: "fullpage",
-    type: "boolean",
-    description: L10N.getStr("screenshotFullPageDesc"),
-    manual: L10N.getStr("screenshotFullPageManual")
-  },
-  {
-    name: "selector",
-    type: "string",
-    description: L10N.getStr("inspectNodeDesc"),
-    manual: L10N.getStr("inspectNodeManual")
-  },
-  {
-    name: "file",
-    type: "boolean",
-    description: L10N.getStr("screenshotFileDesc"),
-    manual: L10N.getStr("screenshotFileManual"),
-  },
-  {
-    name: "filename",
-    type: "string",
-    description: L10N.getStr("screenshotFilenameDesc"),
-    manual: L10N.getStr("screenshotFilenameManual")
-  }
-];
-
-/**
- * Creates a string from an object for use when screenshot is passed the `--help` argument
- *
- * @param object param
- *        The param object to be formatted.
- * @return string
- *         The formatted information from the param object as a string
- */
-function formatHelpField(param) {
-  const padding = " ".repeat(5);
-  return Object.entries(param).map(([key, value]) => {
-    if (key === "name") {
-      const name = `${padding}--${value}`;
-      return name;
-    }
-    return `${padding.repeat(2)}${key}: ${value}`;
-  }).join("\n");
-}
-
-/**
- * Creates a string response from the screenshot options for use when
- * screenshot is passed the `--help` argument
- *
- * @return string
- *         The formatted information from the param object as a string
- */
-function getFormattedHelpData() {
-  const formattedParams = screenshotCommandParams
-    .map(formatHelpField)
-    .join("\n\n");
-
-  return `${screenshotDescription}\n${screenshotGroupOptions}\n\n${formattedParams}`;
-}
-
-/**
- * Main entry point in this file; Takes the original arguments that `:screenshot` was
- * called with and the image value from the server, and uses the client window to save
- * the screenshot to the remote debugging machine's memory or clipboard.
- *
- * @param object window
- *        The Debugger Client window.
- *
- * @param object args
- *        The original args with which the screenshot
- *        was called.
- * @param object value
- *        an object with a image value and file name
- *
- * @return string[]
- *         Response messages from processing the screenshot
- */
-function processScreenshot(window, args = {}, value) {
-  if (args.help) {
-    const message = getFormattedHelpData();
-    // Wrap meesage in an array so that the return value is consistant with saveScreenshot
-    return [message];
-  }
-  simulateCameraShutter(window.document);
-  return saveScreenshot(window, args, value);
-}
-
-/**
- * This function is called to simulate camera effects
- *
- * @param object document
- *        The Debugger Client document.
- */
-function simulateCameraShutter(document) {
-  const window = document.defaultView;
-  if (Services.prefs.getBoolPref("devtools.screenshot.audio.enabled")) {
-    const audioCamera = new window.Audio("resource://devtools/client/themes/audio/shutter.wav");
-    audioCamera.play();
-  }
-}
-
-/**
- * Save the captured screenshot to one of several destinations.
- *
- * @param object window
- *        The Debugger Client window.
- *
- * @param object args
- *        The original args with which the screenshot was called.
- *
- * @param object image
- *        The image object that was sent from the server.
- *
- * @return string[]
- *         Response messages from processing the screenshot.
- */
-async function saveScreenshot(window, args, image) {
-  const fileNeeded = args.filename ||
-    !args.clipboard || args.file;
-  const results = [];
-
-  if (args.clipboard) {
-    const result = await saveToClipboard(window, image.data);
-    results.push(result);
-  }
-
-  if (fileNeeded) {
-    const result = await saveToFile(window, image);
-    results.push(result);
-  }
-  return results;
-}
-
-/**
- * Save the image data to the clipboard. This returns a promise, so it can
- * be treated exactly like file processing.
- *
- * @param object window
- *        The Debugger Client window.
- *
- * @param string data
- *        The image data encoded in base64 that was sent from the server.
- *
- * @return string
- *         Response message from processing the screenshot.
- */
-function saveToClipboard(window, data) {
-  return new Promise(resolve => {
-    try {
-      const channel = NetUtil.newChannel({
-        uri: data,
-        loadUsingSystemPrincipal: true,
-        contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE
-      });
-      const input = channel.open2();
-
-      const loadContext = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIWebNavigation)
-                                .QueryInterface(Ci.nsILoadContext);
-
-      const callback = {
-        onImageReady(container, status) {
-          if (!container) {
-            console.error("imgTools.decodeImageAsync failed");
-            resolve(L10N.getStr("screenshotErrorCopying"));
-            return;
-          }
-
-          try {
-            const wrapped = Cc["@mozilla.org/supports-interface-pointer;1"]
-                              .createInstance(Ci.nsISupportsInterfacePointer);
-            wrapped.data = container;
-
-            const trans = Cc["@mozilla.org/widget/transferable;1"]
-                            .createInstance(Ci.nsITransferable);
-            trans.init(loadContext);
-            trans.addDataFlavor(channel.contentType);
-            trans.setTransferData(channel.contentType, wrapped, -1);
-
-            Services.clipboard.setData(trans, null, Ci.nsIClipboard.kGlobalClipboard);
-
-            resolve(L10N.getStr("screenshotCopied"));
-          } catch (ex) {
-            console.error(ex);
-            resolve(L10N.getStr("screenshotErrorCopying"));
-          }
-        }
-      };
-
-      const threadManager = Cc["@mozilla.org/thread-manager;1"].getService();
-      const imgTools = Cc["@mozilla.org/image/tools;1"]
-                          .getService(Ci.imgITools);
-      imgTools.decodeImageAsync(input, channel.contentType, callback,
-                                threadManager.currentThread);
-    } catch (ex) {
-      console.error(ex);
-      resolve(L10N.getStr("screenshotErrorCopying"));
-    }
-  });
-}
-
-/**
- * Progress listener that forwards calls to a transfer object.
- *
- * This is used below in saveToFile to forward progress updates from the
- * nsIWebBrowserPersist object that does the actual saving to the nsITransfer
- * which just represents the operation for the Download Manager. This keeps the
- * Download Manager updated on saving progress and completion, so that it gives
- * visual feedback from the downloads toolbar button when the save is done.
- *
- * It also allows the browser window to show auth prompts if needed (should not
- * be needed for saving screenshots).
- *
- * This code is borrowed directly from contentAreaUtils.js.
- *
- * @param object win
- *        The Debugger Client window.
- *
- * @param object transfer
- *        The transfer object.
- *
- */
-function DownloadListener(win, transfer) {
-  this.window = win;
-  this.transfer = transfer;
-
-  // For most method calls, forward to the transfer object.
-  for (const name in transfer) {
-    if (name != "QueryInterface" &&
-        name != "onStateChange") {
-      this[name] = (...args) => transfer[name].apply(transfer, args);
-    }
-  }
-
-  // Allow saveToFile to await completion for error handling
-  this._completedDeferred = {};
-  this.completed = new Promise((resolve, reject) => {
-    this._completedDeferred.resolve = resolve;
-    this._completedDeferred.reject = reject;
-  });
-}
-
-DownloadListener.prototype = {
-  QueryInterface: ChromeUtils.generateQI(["nsIInterfaceRequestor",
-                                          "nsIWebProgressListener",
-                                          "nsIWebProgressListener2"]),
-
-  getInterface: function(iid) {
-    if (iid.equals(Ci.nsIAuthPrompt) ||
-        iid.equals(Ci.nsIAuthPrompt2)) {
-      const ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]
-                 .getService(Ci.nsIPromptFactory);
-      return ww.getPrompt(this.window, iid);
-    }
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-  onStateChange: function(webProgress, request, state, status) {
-    // Check if the download has completed
-    if ((state & Ci.nsIWebProgressListener.STATE_STOP) &&
-        (state & Ci.nsIWebProgressListener.STATE_IS_NETWORK)) {
-      if (status == Cr.NS_OK) {
-        this._completedDeferred.resolve();
-      } else {
-        this._completedDeferred.reject();
-      }
-    }
-
-    this.transfer.onStateChange.apply(this.transfer, arguments);
-  }
-};
-
-/**
- * Save the screenshot data to disk, returning a promise which is resolved on
- * completion.
- *
- * @param object window
- *        The Debugger Client window.
- *
- * @param object image
- *        The image object that was sent from the server.
- *
- * @return string
- *         Response message from processing the screenshot.
- */
-async function saveToFile(window, image) {
-  const document = window.document;
-  let filename = image.filename;
-
-  // Check there is a .png extension to filename
-  if (!filename.match(/.png$/i)) {
-    filename += ".png";
-  }
-
-  const downloadsDir = await Downloads.getPreferredDownloadsDirectory();
-  const downloadsDirExists = await OS.File.exists(downloadsDir);
-  if (downloadsDirExists) {
-    // If filename is absolute, it will override the downloads directory and
-    // still be applied as expected.
-    filename = OS.Path.join(downloadsDir, filename);
-  }
-
-  const sourceURI = Services.io.newURI(image.data);
-  const targetFile = new FileUtils.File(filename);
-  const targetFileURI = Services.io.newFileURI(targetFile);
-
-  // Create download and track its progress.
-  // This is adapted from saveURL in contentAreaUtils.js, but simplified greatly
-  // and modified to allow saving to arbitrary paths on disk. Using these
-  // objects as opposed to just writing with OS.File allows us to tie into the
-  // download manager to record a download entry and to get visual feedback from
-  // the downloads toolbar button when the save is done.
-  const nsIWBP = Ci.nsIWebBrowserPersist;
-  const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
-                nsIWBP.PERSIST_FLAGS_FORCE_ALLOW_COOKIES |
-                nsIWBP.PERSIST_FLAGS_BYPASS_CACHE |
-                nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
-  const isPrivate =
-    PrivateBrowsingUtils.isContentWindowPrivate(document.defaultView);
-  const persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
-                  .createInstance(Ci.nsIWebBrowserPersist);
-  persist.persistFlags = flags;
-  const tr = Cc["@mozilla.org/transfer;1"].createInstance(Ci.nsITransfer);
-  tr.init(sourceURI,
-          targetFileURI,
-          "",
-          null,
-          null,
-          null,
-          persist,
-          isPrivate);
-  const listener = new DownloadListener(window, tr);
-  persist.progressListener = listener;
-  persist.savePrivacyAwareURI(sourceURI,
-                              0,
-                              document.documentURIObject,
-                              Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
-                              null,
-                              null,
-                              targetFileURI,
-                              isPrivate);
-
-  try {
-    // Await successful completion of the save via the listener
-    await listener.completed;
-    return L10N.getFormatStr("screenshotSavedToFile", filename);
-  } catch (ex) {
-    console.error(ex);
-    return L10N.getFormatStr("screenshotErrorSavingToFile", filename);
-  }
-}
-
-module.exports = processScreenshot;