Bug 1361311 - Remove project editor. r=pbro draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Wed, 07 Jun 2017 15:30:50 -0500
changeset 591040 86256b0c417ca4665366c64c4779d9f9dbaea432
parent 591039 79cb3b63b7a5e871df123e52783ca762c6de2ab4
child 632404 f393d34b00b2789607628d005de47ef0c9b9f35e
push id62933
push userbmo:jryans@gmail.com
push dateThu, 08 Jun 2017 14:56:20 +0000
reviewerspbro
bugs1361311
milestone55.0a1
Bug 1361311 - Remove project editor. r=pbro MozReview-Commit-ID: 6p8p3slqSBG
devtools/client/jar.mn
devtools/client/locales/en-US/projecteditor.properties
devtools/client/moz.build
devtools/client/projecteditor/chrome/content/projecteditor.xul
devtools/client/projecteditor/lib/editors.js
devtools/client/projecteditor/lib/helpers/event.js
devtools/client/projecteditor/lib/helpers/file-picker.js
devtools/client/projecteditor/lib/helpers/l10n.js
devtools/client/projecteditor/lib/helpers/moz.build
devtools/client/projecteditor/lib/helpers/prompts.js
devtools/client/projecteditor/lib/helpers/readdir.js
devtools/client/projecteditor/lib/moz.build
devtools/client/projecteditor/lib/plugins/app-manager/app-project-editor.js
devtools/client/projecteditor/lib/plugins/app-manager/moz.build
devtools/client/projecteditor/lib/plugins/app-manager/plugin.js
devtools/client/projecteditor/lib/plugins/core.js
devtools/client/projecteditor/lib/plugins/delete/delete.js
devtools/client/projecteditor/lib/plugins/delete/moz.build
devtools/client/projecteditor/lib/plugins/dirty/dirty.js
devtools/client/projecteditor/lib/plugins/dirty/moz.build
devtools/client/projecteditor/lib/plugins/image-view/image-editor.js
devtools/client/projecteditor/lib/plugins/image-view/moz.build
devtools/client/projecteditor/lib/plugins/image-view/plugin.js
devtools/client/projecteditor/lib/plugins/logging/logging.js
devtools/client/projecteditor/lib/plugins/logging/moz.build
devtools/client/projecteditor/lib/plugins/moz.build
devtools/client/projecteditor/lib/plugins/new/moz.build
devtools/client/projecteditor/lib/plugins/new/new.js
devtools/client/projecteditor/lib/plugins/rename/moz.build
devtools/client/projecteditor/lib/plugins/rename/rename.js
devtools/client/projecteditor/lib/plugins/save/moz.build
devtools/client/projecteditor/lib/plugins/save/save.js
devtools/client/projecteditor/lib/plugins/status-bar/moz.build
devtools/client/projecteditor/lib/plugins/status-bar/plugin.js
devtools/client/projecteditor/lib/project.js
devtools/client/projecteditor/lib/projecteditor.js
devtools/client/projecteditor/lib/shells.js
devtools/client/projecteditor/lib/stores/base.js
devtools/client/projecteditor/lib/stores/local.js
devtools/client/projecteditor/lib/stores/moz.build
devtools/client/projecteditor/lib/stores/resource.js
devtools/client/projecteditor/lib/tree.js
devtools/client/projecteditor/moz.build
devtools/client/projecteditor/test/.eslintrc.js
devtools/client/projecteditor/test/browser.ini
devtools/client/projecteditor/test/browser_projecteditor_app_options.js
devtools/client/projecteditor/test/browser_projecteditor_confirm_unsaved.js
devtools/client/projecteditor/test/browser_projecteditor_contextmenu_01.js
devtools/client/projecteditor/test/browser_projecteditor_contextmenu_02.js
devtools/client/projecteditor/test/browser_projecteditor_delete_file.js
devtools/client/projecteditor/test/browser_projecteditor_editing_01.js
devtools/client/projecteditor/test/browser_projecteditor_editors_image.js
devtools/client/projecteditor/test/browser_projecteditor_external_change.js
devtools/client/projecteditor/test/browser_projecteditor_immediate_destroy.js
devtools/client/projecteditor/test/browser_projecteditor_init.js
devtools/client/projecteditor/test/browser_projecteditor_menubar_01.js
devtools/client/projecteditor/test/browser_projecteditor_menubar_02.js
devtools/client/projecteditor/test/browser_projecteditor_new_file.js
devtools/client/projecteditor/test/browser_projecteditor_rename_file_01.js
devtools/client/projecteditor/test/browser_projecteditor_rename_file_02.js
devtools/client/projecteditor/test/browser_projecteditor_saveall.js
devtools/client/projecteditor/test/browser_projecteditor_stores.js
devtools/client/projecteditor/test/browser_projecteditor_tree_selection_01.js
devtools/client/projecteditor/test/browser_projecteditor_tree_selection_02.js
devtools/client/projecteditor/test/head.js
devtools/client/projecteditor/test/helper_edits.js
devtools/client/projecteditor/test/helper_homepage.html
devtools/client/projecteditor/test/projecteditor-test.xul
devtools/client/themes/projecteditor/projecteditor.css
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -4,18 +4,16 @@
 
 devtools.jar:
 %   content devtools %content/
     content/shared/vendor/d3.js (shared/vendor/d3.js)
     content/shared/vendor/dagre-d3.js (shared/vendor/dagre-d3.js)
     content/shared/widgets/widgets.css (shared/widgets/widgets.css)
     content/netmonitor/src/assets/styles/netmonitor.css (netmonitor/src/assets/styles/netmonitor.css)
     content/shared/widgets/VariablesView.xul (shared/widgets/VariablesView.xul)
-    content/projecteditor/chrome/content/projecteditor.xul (projecteditor/chrome/content/projecteditor.xul)
-    content/projecteditor/lib/helpers/readdir.js (projecteditor/lib/helpers/readdir.js)
     content/netmonitor/index.html (netmonitor/index.html)
     content/webconsole/webconsole.xul (webconsole/webconsole.xul)
     content/scratchpad/scratchpad.xul (scratchpad/scratchpad.xul)
     content/scratchpad/scratchpad.js (scratchpad/scratchpad.js)
     content/shared/splitview.css (shared/splitview.css)
     content/shared/theme-switching.js (shared/theme-switching.js)
     content/shared/frame-script-utils.js (shared/frame-script-utils.js)
     content/styleeditor/styleeditor.xul (styleeditor/styleeditor.xul)
@@ -248,17 +246,16 @@ devtools.jar:
     skin/images/sort-descending-arrow.svg (themes/images/sort-descending-arrow.svg)
     skin/images/cubic-bezier-swatch.png (themes/images/cubic-bezier-swatch.png)
     skin/images/cubic-bezier-swatch@2x.png (themes/images/cubic-bezier-swatch@2x.png)
     skin/fonts.css (themes/fonts.css)
     skin/computed.css (themes/computed.css)
     skin/layout.css (themes/layout.css)
     skin/images/arrow-e.png (themes/images/arrow-e.png)
     skin/images/arrow-e@2x.png (themes/images/arrow-e@2x.png)
-    skin/projecteditor/projecteditor.css (themes/projecteditor/projecteditor.css)
     skin/images/search-clear-failed.svg (themes/images/search-clear-failed.svg)
     skin/images/search-clear-light.svg (themes/images/search-clear-light.svg)
     skin/images/search-clear-dark.svg (themes/images/search-clear-dark.svg)
     skin/tooltip/arrow-horizontal-dark.png (themes/tooltip/arrow-horizontal-dark.png)
     skin/tooltip/arrow-horizontal-dark@2x.png (themes/tooltip/arrow-horizontal-dark@2x.png)
     skin/tooltip/arrow-vertical-dark.png (themes/tooltip/arrow-vertical-dark.png)
     skin/tooltip/arrow-vertical-dark@2x.png (themes/tooltip/arrow-vertical-dark@2x.png)
     skin/tooltip/arrow-horizontal-light.png (themes/tooltip/arrow-horizontal-light.png)
deleted file mode 100644
--- a/devtools/client/locales/en-US/projecteditor.properties
+++ /dev/null
@@ -1,88 +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 the ProjectEditor component
-# which is used for editing files in a directory and is used inside the
-# App Manager.
-# 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 (projecteditor.confirmUnsavedTitle):
-# This string is displayed as as the title of the confirm prompt that checks
-# to make sure if the project can be closed/switched without saving changes
-projecteditor.confirmUnsavedTitle=Unsaved Changes
-
-# LOCALIZATION NOTE (projecteditor.confirmUnsavedLabel2):
-# This string is displayed as the message of the confirm prompt that checks
-# to make sure if the project can be closed/switched without saving changes
-projecteditor.confirmUnsavedLabel2=You have unsaved changes that will be lost. Are you sure you want to continue?
-
-# LOCALIZATION NOTE (projecteditor.deleteLabel):
-# This string is displayed as a context menu item for allowing the selected
-# file / folder to be deleted.
-projecteditor.deleteLabel=Delete
-
-# LOCALIZATION NOTE (projecteditor.deletePromptTitle):
-# This string is displayed as as the title of the confirm prompt that checks
-# to make sure if a file or folder should be removed.
-projecteditor.deletePromptTitle=Delete
-
-# LOCALIZATION NOTE (projecteditor.deleteFolderPromptMessage):
-# This string is displayed as as the message of the confirm prompt that checks
-# to make sure if a folder should be removed.
-projecteditor.deleteFolderPromptMessage=Are you sure you want to delete this folder?
-
-# LOCALIZATION NOTE (projecteditor.deleteFilePromptMessage):
-# This string is displayed as as the message of the confirm prompt that checks
-# to make sure if a file should be removed.
-projecteditor.deleteFilePromptMessage=Are you sure you want to delete this file?
-
-# LOCALIZATION NOTE (projecteditor.newLabel):
-# This string is displayed as a menu item for adding a new file to
-# the directory.
-projecteditor.newLabel=New…
-
-# LOCALIZATION NOTE (projecteditor.renameLabel):
-# This string is displayed as a menu item for renaming a file in
-# the directory.
-projecteditor.renameLabel=Rename
-
-# LOCALIZATION NOTE (projecteditor.saveLabel):
-# This string is displayed as a menu item for saving the current file.
-projecteditor.saveLabel=Save
-
-# LOCALIZATION NOTE (projecteditor.saveAsLabel):
-# This string is displayed as a menu item for saving the current file
-# with a new name.
-projecteditor.saveAsLabel=Save As…
-
-# LOCALIZATION NOTE (projecteditor.selectFileLabel):
-# This string is displayed as the title on the file picker when saving a file.
-projecteditor.selectFileLabel=Select a File
-
-# LOCALIZATION NOTE (projecteditor.openFolderLabel):
-# This string is displayed as the title on the file picker when opening a folder.
-projecteditor.openFolderLabel=Select a Folder
-
-# LOCALIZATION NOTE (projecteditor.openFileLabel):
-# This string is displayed as the title on the file picker when opening a file.
-projecteditor.openFileLabel=Open a File
-
-# LOCALIZATION NOTE  (projecteditor.find.commandkey): This is the key to use in
-# conjunction with accel (Command on Mac or Ctrl on other platforms) to search
-# text in the files.
-projecteditor.find.commandkey=F
-
-# LOCALIZATION NOTE  (projecteditor.save.commandkey): This is the key to use in
-# conjunction with accel (Command on Mac or Ctrl on other platforms) to
-# save the file.  It is used with accel+shift to "save as".
-projecteditor.save.commandkey=S
-
-# LOCALIZATION NOTE  (projecteditor.new.commandkey): This is the key to use in
-# conjunction with accel (Command on Mac or Ctrl on other platforms) to
-# create a new file.
-projecteditor.new.commandkey=N
--- a/devtools/client/moz.build
+++ b/devtools/client/moz.build
@@ -16,17 +16,16 @@ DIRS += [
     'framework',
     'inspector',
     'jsonview',
     'locales',
     'memory',
     'netmonitor',
     'performance',
     'preferences',
-    'projecteditor',
     'responsive.html',
     'responsivedesign',
     'scratchpad',
     'shadereditor',
     'shared',
     'shims',
     'sourceeditor',
     'storage',
@@ -48,10 +47,10 @@ EXTRA_COMPONENTS += [
 
 JAR_MANIFESTS += ['jar.mn']
 
 DevToolsModules(
     'definitions.js',
     'menus.js',
 )
 
-with Files('**'):
-    BUG_COMPONENT = ('Firefox', 'Developer Tools')
+with Files('**'):
+    BUG_COMPONENT = ('Firefox', 'Developer Tools')
deleted file mode 100644
--- a/devtools/client/projecteditor/chrome/content/projecteditor.xul
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.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/. -->
-<?xml-stylesheet href="chrome://devtools/skin/light-theme.css" type="text/css"?>
-<?xml-stylesheet href="chrome://devtools/skin/projecteditor/projecteditor.css" type="text/css"?>
-<?xml-stylesheet href="chrome://devtools/content/debugger/debugger.css" type="text/css"?>
-<?xml-stylesheet href="resource://devtools/client/themes/common.css" type="text/css"?>
-<?xml-stylesheet href="chrome://devtools/skin/markup.css" type="text/css"?>
-
-<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
-
-<!DOCTYPE window [
-<!ENTITY % scratchpadDTD SYSTEM "chrome://devtools/locale/scratchpad.dtd" >
- %scratchpadDTD;
-<!ENTITY % editMenuStrings SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
-%editMenuStrings;
-<!ENTITY % sourceEditorStrings SYSTEM "chrome://devtools/locale/sourceeditor.dtd">
-%sourceEditorStrings;
-]>
-
-<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" class="theme-body theme-light">
-
-  <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
-
-  <commandset id="projecteditor-commandset" />
-  <commandset id="editMenuCommands"/>
-  <keyset id="projecteditor-keyset" />
-  <keyset id="editMenuKeys"/>
-
-  <!-- Eventually we want to let plugins declare their own menu items.
-       Wait unti app manager lands to deal with this integration point.
-  -->
-  <menubar id="projecteditor-menubar">
-    <menu id="file-menu" label="&fileMenu.label;" accesskey="&fileMenu.accesskey;">
-      <menupopup id="file-menu-popup" />
-    </menu>
-
-    <menu id="edit-menu" label="&editMenu.label;"
-          accesskey="&editMenu.accesskey;">
-      <menupopup id="edit-menu-popup">
-        <menuitem id="menu_undo"/>
-        <menuitem id="menu_redo"/>
-        <menuseparator/>
-        <menuitem id="menu_cut"/>
-        <menuitem id="menu_copy"/>
-        <menuitem id="menu_paste"/>
-      </menupopup>
-    </menu>
-  </menubar>
-
-  <popupset>
-    <menupopup id="context-menu-popup">
-    </menupopup>
-    <menupopup id="texteditor-context-popup">
-      <menuitem id="cMenu_cut"/>
-      <menuitem id="cMenu_copy"/>
-      <menuitem id="cMenu_paste"/>
-      <menuitem id="cMenu_delete"/>
-      <menuseparator/>
-      <menuitem id="cMenu_selectAll"/>
-    </menupopup>
-  </popupset>
-
-  <deck id="main-deck" flex="1">
-    <vbox flex="1" id="source-deckitem">
-      <hbox id="sources-body" flex="1">
-        <vbox width="250" id="sources">
-          <vbox flex="1">
-          </vbox>
-          <toolbar id="project-toolbar" class="devtools-toolbar" hidden="true"></toolbar>
-        </vbox>
-        <splitter id="source-editor-splitter" class="devtools-side-splitter"/>
-        <vbox id="shells" flex="4">
-          <toolbar id="projecteditor-toolbar" class="devtools-toolbar">
-            <hbox id="plugin-toolbar-left"/>
-            <spacer flex="1"/>
-            <hbox id="plugin-toolbar-right"/>
-          </toolbar>
-          <box id="shells-deck-container" flex="4"></box>
-          <toolbar id="projecteditor-toolbar-bottom" class="devtools-toolbar">
-          </toolbar>
-        </vbox>
-      </hbox>
-    </vbox>
-  </deck>
-</page>
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/editors.js
+++ /dev/null
@@ -1,303 +0,0 @@
-/* -*- 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/. */
-
-const { Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const { EventTarget } = require("sdk/event/target");
-const { emit } = require("sdk/event/core");
-const promise = require("promise");
-const Editor = require("devtools/client/sourceeditor/editor");
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
-/**
- * ItchEditor is extended to implement an editor, which is the main view
- * that shows up when a file is selected.  This object should not be used
- * directly - use TextEditor for a basic code editor.
- */
-var ItchEditor = Class({
-  extends: EventTarget,
-
-  /**
-   * A boolean specifying if the toolbar above the editor should be hidden.
-   */
-  hidesToolbar: false,
-
-  /**
-   * A boolean specifying whether the editor can be edited / saved.
-   * For instance, a 'save' doesn't make sense on an image.
-   */
-  isEditable: false,
-
-  toString: function () {
-    return this.label || "";
-  },
-
-  emit: function (name, ...args) {
-    emit(this, name, ...args);
-  },
-
-  /* Does the editor not have any unsaved changes? */
-  isClean: function () {
-    return true;
-  },
-
-  /**
-   * Initialize the editor with a single host.  This should be called
-   * by objects extending this object with:
-   * ItchEditor.prototype.initialize.apply(this, arguments)
-   */
-  initialize: function (host) {
-    this.host = host;
-    this.doc = host.document;
-    this.label = "";
-    this.elt = this.doc.createElement("vbox");
-    this.elt.setAttribute("flex", "1");
-    this.elt.editor = this;
-    this.toolbar = this.doc.querySelector("#projecteditor-toolbar");
-    this.projectEditorKeyset = host.projectEditorKeyset;
-    this.projectEditorCommandset = host.projectEditorCommandset;
-  },
-
-  /**
-   * Sets the visibility of the element that shows up above the editor
-   * based on the this.hidesToolbar property.
-   */
-  setToolbarVisibility: function () {
-    if (this.hidesToolbar) {
-      this.toolbar.setAttribute("hidden", "true");
-    } else {
-      this.toolbar.removeAttribute("hidden");
-    }
-  },
-
-
-  /**
-   * Load a single resource into the editor.
-   *
-   * @param Resource resource
-   *        The single file / item that is being dealt with (see stores/base)
-   * @returns Promise
-   *          A promise that is resolved once the editor has loaded the contents
-   *          of the resource.
-   */
-  load: function (resource) {
-    return promise.resolve();
-  },
-
-  /**
-   * Clean up the editor.  This can have different meanings
-   * depending on the type of editor.
-   */
-  destroy: function () {
-
-  },
-
-  /**
-   * Give focus to the editor.  This can have different meanings
-   * depending on the type of editor.
-   *
-   * @returns Promise
-   *          A promise that is resolved once the editor has been focused.
-   */
-  focus: function () {
-    return promise.resolve();
-  }
-});
-exports.ItchEditor = ItchEditor;
-
-/**
- * The main implementation of the ItchEditor class.  The TextEditor is used
- * when editing any sort of plain text file, and can be created with different
- * modes for syntax highlighting depending on the language.
- */
-var TextEditor = Class({
-  extends: ItchEditor,
-
-  isEditable: true,
-
-  /**
-   * Extra keyboard shortcuts to use with the editor.  Shortcuts defined
-   * within projecteditor should be triggered when they happen in the editor, and
-   * they would usually be swallowed without registering them.
-   * See "devtools/sourceeditor/editor" for more information.
-   */
-  get extraKeys() {
-    let extraKeys = {};
-
-    // Copy all of the registered keys into extraKeys object, to notify CodeMirror
-    // that it should be ignoring these keys
-    [...this.projectEditorKeyset.querySelectorAll("key")].forEach((key) => {
-      let keyUpper = key.getAttribute("key").toUpperCase();
-      let toolModifiers = key.getAttribute("modifiers");
-      let modifiers = {
-        alt: toolModifiers.includes("alt"),
-        shift: toolModifiers.includes("shift")
-      };
-
-      // On the key press, we will dispatch the event within projecteditor.
-      extraKeys[Editor.accel(keyUpper, modifiers)] = () => {
-        let doc = this.projectEditorCommandset.ownerDocument;
-        let event = doc.createEvent("Event");
-        event.initEvent("command", true, true);
-        let command = this.projectEditorCommandset.querySelector("#" + key.getAttribute("command"));
-        command.dispatchEvent(event);
-      };
-    });
-
-    return extraKeys;
-  },
-
-  isClean: function () {
-    if (!this.editor.isAppended()) {
-      return true;
-    }
-    return this.editor.getText() === this._savedResourceContents;
-  },
-
-  initialize: function (document, mode = Editor.modes.text) {
-    ItchEditor.prototype.initialize.apply(this, arguments);
-    this.label = mode.name;
-    this.editor = new Editor({
-      mode: mode,
-      lineNumbers: true,
-      extraKeys: this.extraKeys,
-      themeSwitching: false,
-      autocomplete: true,
-      contextMenu:  this.host.textEditorContextMenuPopup
-    });
-
-    // Trigger a few editor specific events on `this`.
-    this.editor.on("change", (...args) => {
-      this.emit("change", ...args);
-    });
-    this.editor.on("cursorActivity", (...args) => {
-      this.emit("cursorActivity", ...args);
-    });
-    this.editor.on("focus", (...args) => {
-      this.emit("focus", ...args);
-    });
-    this.editor.on("saveRequested", (...args) => {
-      this.emit("saveRequested", ...args);
-    });
-
-    this.appended = this.editor.appendTo(this.elt);
-  },
-
-  /**
-   * Clean up the editor.  This can have different meanings
-   * depending on the type of editor.
-   */
-  destroy: function () {
-    this.editor.destroy();
-    this.editor = null;
-  },
-
-  /**
-   * Load a single resource into the text editor.
-   *
-   * @param Resource resource
-   *        The single file / item that is being dealt with (see stores/base)
-   * @returns Promise
-   *          A promise that is resolved once the text editor has loaded the
-   *          contents of the resource.
-   */
-  load: function (resource) {
-    // Wait for the editor.appendTo and resource.load before proceeding.
-    // They can run in parallel.
-    return promise.all([
-      resource.load(),
-      this.appended
-    ]).then(([resourceContents])=> {
-      if (!this.editor) {
-        return;
-      }
-      this._savedResourceContents = resourceContents;
-      this.editor.setText(resourceContents);
-      this.editor.clearHistory();
-      this.editor.setClean();
-      this.emit("load");
-    }, console.error);
-  },
-
-  /**
-   * Save the resource based on the current state of the editor
-   *
-   * @param Resource resource
-   *        The single file / item to be saved
-   * @returns Promise
-   *          A promise that is resolved once the resource has been
-   *          saved.
-   */
-  save: function (resource) {
-    let newText = this.editor.getText();
-    return resource.save(newText).then(() => {
-      this._savedResourceContents = newText;
-      this.emit("save", resource);
-    });
-  },
-
-  /**
-   * Give focus to the code editor.
-   *
-   * @returns Promise
-   *          A promise that is resolved once the editor has been focused.
-   */
-  focus: function () {
-    return this.appended.then(() => {
-      if (this.editor) {
-        this.editor.focus();
-      }
-    });
-  }
-});
-
-/**
- * Wrapper for TextEditor using JavaScript syntax highlighting.
- */
-function JSEditor(host) {
-  return TextEditor(host, Editor.modes.js);
-}
-
-/**
- * Wrapper for TextEditor using CSS syntax highlighting.
- */
-function CSSEditor(host) {
-  return TextEditor(host, Editor.modes.css);
-}
-
-/**
- * Wrapper for TextEditor using HTML syntax highlighting.
- */
-function HTMLEditor(host) {
-  return TextEditor(host, Editor.modes.html);
-}
-
-/**
- * Get the type of editor that can handle a particular resource.
- * @param Resource resource
- *        The single file that is going to be opened.
- * @returns Type:Editor
- *          The type of editor that can handle this resource.  The
- *          return value is a constructor function.
- */
-function EditorTypeForResource(resource) {
-  const categoryMap = {
-    "txt": TextEditor,
-    "html": HTMLEditor,
-    "xml": HTMLEditor,
-    "css": CSSEditor,
-    "js": JSEditor,
-    "json": JSEditor
-  };
-  return categoryMap[resource.contentCategory] || TextEditor;
-}
-
-exports.TextEditor = TextEditor;
-exports.JSEditor = JSEditor;
-exports.CSSEditor = CSSEditor;
-exports.HTMLEditor = HTMLEditor;
-exports.EditorTypeForResource = EditorTypeForResource;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/helpers/event.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/* -*- 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/. */
-
-/**
- * This file wraps EventEmitter objects to provide functions to forget
- * all events bound on a certain object.
- */
-
-const { Class } = require("sdk/core/heritage");
-
-/**
- * The Scope object is used to keep track of listeners.
- * This object is not exported.
- */
-var Scope = Class({
-  on: function (target, event, handler) {
-    this.listeners = this.listeners || [];
-    this.listeners.push({
-      target: target,
-      event: event,
-      handler: handler
-    });
-    target.on(event, handler);
-  },
-
-  off: function (t, e, h) {
-    if (!this.listeners) return;
-    this.listeners = this.listeners.filter(({ target, event, handler }) => {
-      return !(target === t && event === e && handler === h);
-    });
-    target.off(event, handler);
-  },
-
-  clear: function (clearTarget) {
-    if (!this.listeners) return;
-    this.listeners = this.listeners.filter(({ target, event, handler }) => {
-      if (target === clearTarget) {
-        target.off(event, handler);
-        return false;
-      }
-      return true;
-    });
-  },
-
-  destroy: function () {
-    if (!this.listeners) return;
-    this.listeners.forEach(({ target, event, handler }) => {
-      target.off(event, handler);
-    });
-    this.listeners = undefined;
-  }
-});
-
-var scopes = new WeakMap();
-function scope(owner) {
-  if (!scopes.has(owner)) {
-    let scope = new Scope(owner);
-    scopes.set(owner, scope);
-    return scope;
-  }
-  return scopes.get(owner);
-}
-exports.scope = scope;
-
-exports.on = function on(owner, target, event, handler) {
-  if (!target) return;
-  scope(owner).on(target, event, handler);
-};
-
-exports.off = function off(owner, target, event, handler) {
-  if (!target) return;
-  scope(owner).off(target, event, handler);
-};
-
-exports.forget = function forget(owner, target) {
-  scope(owner).clear(target);
-};
-
-exports.done = function done(owner) {
-  scope(owner).destroy();
-  scopes.delete(owner);
-};
-
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/helpers/file-picker.js
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- 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/. */
-
-/**
- * This file contains helper functions for showing OS-specific
- * file and folder pickers.
- */
-
-const { Cu, Cc, Ci } = require("chrome");
-const { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
-const promise = require("promise");
-const { merge } = require("sdk/util/object");
-const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n");
-
-/**
- * Show a file / folder picker.
- * https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFilePicker
- *
- * @param object options
- *        Additional options for setting the source. Supported options:
- *          - directory: string, The path to default opening
- *          - defaultName: string, The filename including extension that
- *                         should be suggested to the user as a default
- *          - window: DOMWindow, The filename including extension that
- *                         should be suggested to the user as a default
- *          - title: string, The filename including extension that
- *                         should be suggested to the user as a default
- *          - mode: int, The type of picker to open.
- *
- * @return promise
- *         A promise that is resolved with the full path
- *         after the file has been picked.
- */
-function showPicker(options) {
-  let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
-  if (options.directory) {
-    try {
-      fp.displayDirectory = FileUtils.File(options.directory);
-    } catch (ex) {
-      console.warn(ex);
-    }
-  }
-
-  if (options.defaultName) {
-    fp.defaultString = options.defaultName;
-  }
-
-  fp.init(options.window, options.title, options.mode);
-  let deferred = promise.defer();
-  fp.open({
-    done: function (res) {
-      if (res === Ci.nsIFilePicker.returnOK || res === Ci.nsIFilePicker.returnReplace) {
-        deferred.resolve(fp.file.path);
-      } else {
-        deferred.reject();
-      }
-    }
-  });
-  return deferred.promise;
-}
-exports.showPicker = showPicker;
-
-/**
- * Show a save dialog
- * https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFilePicker
- *
- * @param object options
- *        Additional options as specified in showPicker
- *
- * @return promise
- *         A promise that is resolved when the save dialog has closed
- */
-function showSave(options) {
-  return showPicker(merge({
-    title: getLocalizedString("projecteditor.selectFileLabel"),
-    mode: Ci.nsIFilePicker.modeSave
-  }, options));
-}
-exports.showSave = showSave;
-
-/**
- * Show a file open dialog
- *
- * @param object options
- *        Additional options as specified in showPicker
- *
- * @return promise
- *         A promise that is resolved when the file has been opened
- */
-function showOpen(options) {
-  return showPicker(merge({
-    title: getLocalizedString("projecteditor.openFileLabel"),
-    mode: Ci.nsIFilePicker.modeOpen
-  }, options));
-}
-exports.showOpen = showOpen;
-
-/**
- * Show a folder open dialog
- *
- * @param object options
- *        Additional options as specified in showPicker
- *
- * @return promise
- *         A promise that is resolved when the folder has been opened
- */
-function showOpenFolder(options) {
-  return showPicker(merge({
-    title: getLocalizedString("projecteditor.openFolderLabel"),
-    mode: Ci.nsIFilePicker.modeGetFolder
-  }, options));
-}
-exports.showOpenFolder = showOpenFolder;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/helpers/l10n.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/* -*- 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";
-
-/**
- * This file contains helper functions for internationalizing projecteditor strings
- */
-
-const { LocalizationHelper } = require("devtools/shared/l10n");
-const ITCHPAD_STRINGS_URI = "devtools/client/locales/projecteditor.properties";
-const L10N = new LocalizationHelper(ITCHPAD_STRINGS_URI);
-
-function getLocalizedString(name) {
-  try {
-    return L10N.getStr(name);
-  } catch (ex) {
-    console.log("Error reading '" + name + "'");
-    throw new Error("l10n error with " + name);
-  }
-}
-
-exports.getLocalizedString = getLocalizedString;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/helpers/moz.build
+++ /dev/null
@@ -1,12 +0,0 @@
-# -*- 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(
-    'event.js',
-    'file-picker.js',
-    'l10n.js',
-    'prompts.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/helpers/prompts.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
-
-/**
- * This file contains helper functions for showing user prompts.
- * See https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIPromptService
- */
-
-const { Cu, Cc, Ci } = require("chrome");
-const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n");
-const prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"]
-                        .getService(Ci.nsIPromptService);
-
-/**
- * Show a prompt.
- *
- * @param string title
- *               The title to the dialog
- * @param string message
- *               The message to display
- *
- * @return bool
- *         Whether the user has confirmed the action
- */
-function confirm(title, message) {
-  var result = prompts.confirm(null, title || "Title of this Dialog", message || "Are you sure?");
-  return result;
-}
-exports.confirm = confirm;
-
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/helpers/readdir.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- 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/. */
-
-importScripts("resource://gre/modules/osfile.jsm");
-
-/**
- * This file is meant to be loaded in a worker using:
- *   new ChromeWorker("chrome://devtools/content/projecteditor/lib/helpers/readdir.js");
- *
- * Read a local directory inside of a web woker
- *
- * @param {string} path
- *        window to inspect
- * @param {RegExp|string} ignore
- *        A pattern to ignore certain files.  This is
- *        called with file.name.match(ignore).
- * @param {Number} maxDepth
- *        How many directories to recurse before stopping.
- *        Directories with depth > maxDepth will be ignored.
- */
-function readDir(path, ignore, maxDepth = Infinity) {
-  let ret = {};
-
-  let set = new Set();
-
-  let info = OS.File.stat(path);
-  set.add({
-    path: path,
-    name: info.name,
-    isDir: info.isDir,
-    isSymLink: info.isSymLink,
-    depth: 0
-  });
-
-  for (let info of set) {
-    let children = [];
-
-    if (info.isDir && !info.isSymLink) {
-      if (info.depth > maxDepth) {
-        continue;
-      }
-
-      let iterator = new OS.File.DirectoryIterator(info.path);
-      try {
-        for (let child in iterator) {
-          if (ignore && child.name.match(ignore)) {
-            continue;
-          }
-
-          children.push(child.path);
-          set.add({
-            path: child.path,
-            name: child.name,
-            isDir: child.isDir,
-            isSymLink: child.isSymLink,
-            depth: info.depth + 1
-          });
-        }
-      } finally {
-        iterator.close();
-      }
-    }
-
-    ret[info.path] = {
-      name: info.name,
-      isDir: info.isDir,
-      isSymLink: info.isSymLink,
-      depth: info.depth,
-      children: children,
-    };
-  }
-
-  return ret;
-}
-
-onmessage = function (event) {
-  try {
-    let {path, ignore, depth} = event.data;
-    let message = readDir(path, ignore, depth);
-    postMessage(message);
-  } catch (ex) {
-    console.log(ex);
-  }
-};
-
-
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/moz.build
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- 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/.
-
-DIRS += [
-    'helpers',
-    'plugins',
-    'stores',
-]
-
-DevToolsModules(
-    'editors.js',
-    'project.js',
-    'projecteditor.js',
-    'shells.js',
-    'tree.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/app-manager/app-project-editor.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- 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/. */
-
-const { Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const promise = require("promise");
-const { ItchEditor } = require("devtools/client/projecteditor/lib/editors");
-
-var AppProjectEditor = Class({
-  extends: ItchEditor,
-
-  hidesToolbar: true,
-
-  initialize: function (host) {
-    ItchEditor.prototype.initialize.apply(this, arguments);
-    this.appended = promise.resolve();
-    this.host = host;
-    this.label = "app-manager";
-  },
-
-  destroy: function () {
-    this.elt.remove();
-    this.elt = null;
-  },
-
-  load: function (resource) {
-    let {appManagerOpts} = this.host.project;
-
-    // Only load the frame the first time it is selected
-    if (!this.iframe || this.iframe.getAttribute("src") !== appManagerOpts.projectOverviewURL) {
-
-      this.elt.textContent = "";
-      let iframe = this.iframe = this.elt.ownerDocument.createElement("iframe");
-      let iframeLoaded = this.iframeLoaded = promise.defer();
-
-      iframe.addEventListener("load", function () {
-        iframeLoaded.resolve();
-      }, {once: true});
-
-      iframe.setAttribute("flex", "1");
-      iframe.setAttribute("src", appManagerOpts.projectOverviewURL);
-      this.elt.appendChild(iframe);
-
-    }
-
-    promise.all([this.iframeLoaded.promise, this.appended]).then(() => {
-      this.emit("load");
-    });
-  }
-});
-
-exports.AppProjectEditor = AppProjectEditor;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/app-manager/moz.build
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- 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(
-    'app-project-editor.js',
-    'plugin.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/app-manager/plugin.js
+++ /dev/null
@@ -1,77 +0,0 @@
-const { Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const { EventTarget } = require("sdk/event/target");
-const { emit } = require("sdk/event/core");
-const promise = require("promise");
-var { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core");
-const { AppProjectEditor } = require("./app-project-editor");
-const OPTION_URL = "chrome://devtools/skin/images/tool-options.svg";
-const Services = require("Services");
-const Strings = Services.strings.createBundle("chrome://devtools/locale/webide.properties");
-
-var AppManagerRenderer = Class({
-  extends: Plugin,
-
-  isAppManagerProject: function () {
-    return !!this.host.project.appManagerOpts;
-  },
-  editorForResource: function (resource) {
-    if (!resource.parent && this.isAppManagerProject()) {
-      return AppProjectEditor;
-    }
-  },
-  getUI: function (parent) {
-    let doc = parent.ownerDocument;
-    if (parent.childElementCount == 0) {
-      let image = doc.createElement("image");
-      let optionImage = doc.createElement("image");
-      let flexElement = doc.createElement("div");
-      let nameLabel = doc.createElement("span");
-      let statusElement = doc.createElement("div");
-
-      image.className = "project-image";
-      optionImage.className = "project-options";
-      optionImage.setAttribute("src", OPTION_URL);
-      nameLabel.className = "project-name-label";
-      statusElement.className = "project-status";
-      flexElement.className = "project-flex";
-
-      parent.appendChild(image);
-      parent.appendChild(nameLabel);
-      parent.appendChild(flexElement);
-      parent.appendChild(statusElement);
-      parent.appendChild(optionImage);
-    }
-
-    return {
-      image: parent.querySelector(".project-image"),
-      nameLabel: parent.querySelector(".project-name-label"),
-      statusElement: parent.querySelector(".project-status")
-    };
-  },
-  onAnnotate: function (resource, editor, elt) {
-    if (resource.parent || !this.isAppManagerProject()) {
-      return;
-    }
-
-    let {appManagerOpts} = this.host.project;
-    let doc = elt.ownerDocument;
-
-    let {image, nameLabel, statusElement} = this.getUI(elt);
-    let name = appManagerOpts.name || resource.basename;
-    let url = appManagerOpts.iconUrl || "icon-sample.png";
-    let status = appManagerOpts.validationStatus || "unknown";
-    let tooltip = Strings.formatStringFromName("status_tooltip",
-      [Strings.GetStringFromName("status_" + status)], 1);
-
-    nameLabel.textContent = name;
-    image.setAttribute("src", url);
-    statusElement.setAttribute("status", status);
-    statusElement.setAttribute("tooltiptext", tooltip);
-
-    return true;
-  }
-});
-
-exports.AppManagerRenderer = AppManagerRenderer;
-registerPlugin(AppManagerRenderer);
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/core.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*- 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/. */
-
-// This is the core plugin API.
-
-const { Class } = require("sdk/core/heritage");
-
-var Plugin = Class({
-  initialize: function (host) {
-    this.host = host;
-    this.init(host);
-  },
-
-  destroy: function (host) { },
-
-  init: function (host) {},
-
-  showForCategories: function (elt, categories) {
-    this._showFor = this._showFor || [];
-    let set = new Set(categories);
-    this._showFor.push({
-      elt: elt,
-      categories: new Set(categories)
-    });
-    if (this.host.currentEditor) {
-      this.onEditorActivated(this.host.currentEditor);
-    } else {
-      elt.classList.add("plugin-hidden");
-    }
-  },
-
-  priv: function (item) {
-    if (!this._privData) {
-      this._privData = new WeakMap();
-    }
-    if (!this._privData.has(item)) {
-      this._privData.set(item, {});
-    }
-    return this._privData.get(item);
-  },
-  onTreeSelected: function (resource) {},
-
-
-  // Editor state lifetime...
-  onEditorCreated: function (editor) {},
-  onEditorDestroyed: function (editor) {},
-
-  onEditorActivated: function (editor) {
-    if (this._showFor) {
-      let category = editor.category;
-      for (let item of this._showFor) {
-        if (item.categories.has(category)) {
-          item.elt.classList.remove("plugin-hidden");
-        } else {
-          item.elt.classList.add("plugin-hidden");
-        }
-      }
-    }
-  },
-  onEditorDeactivated: function (editor) {
-    if (this._showFor) {
-      for (let item of this._showFor) {
-        item.elt.classList.add("plugin-hidden");
-      }
-    }
-  },
-
-  onEditorLoad: function (editor) {},
-  onEditorSave: function (editor) {},
-  onEditorChange: function (editor) {},
-  onEditorCursorActivity: function (editor) {},
-});
-exports.Plugin = Plugin;
-
-function registerPlugin(constr) {
-  exports.registeredPlugins.push(constr);
-}
-exports.registerPlugin = registerPlugin;
-
-exports.registeredPlugins = [];
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/delete/delete.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- 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/. */
-
-const { Class } = require("sdk/core/heritage");
-const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core");
-const { confirm } = require("devtools/client/projecteditor/lib/helpers/prompts");
-const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n");
-
-var DeletePlugin = Class({
-  extends: Plugin,
-  shouldConfirm: true,
-
-  init: function (host) {
-    this.host.addCommand(this, {
-      id: "cmd-delete"
-    });
-    this.contextMenuItem = this.host.createMenuItem({
-      parent: this.host.contextMenuPopup,
-      label: getLocalizedString("projecteditor.deleteLabel"),
-      command: "cmd-delete"
-    });
-  },
-
-  confirmDelete: function (resource) {
-    let deletePromptMessage = resource.isDir ?
-      getLocalizedString("projecteditor.deleteFolderPromptMessage") :
-      getLocalizedString("projecteditor.deleteFilePromptMessage");
-    return !this.shouldConfirm || confirm(
-      getLocalizedString("projecteditor.deletePromptTitle"),
-      deletePromptMessage
-    );
-  },
-
-  onContextMenuOpen: function (resource) {
-    // Do not allow deletion of the top level items in the tree.  In the
-    // case of the Web IDE in particular this can leave the UI in a weird
-    // state. If we'd like to add ability to delete the project folder from
-    // the tree in the future, then the UI could be cleaned up by listening
-    // to the ProjectTree's "resource-removed" event.
-    if (!resource.parent) {
-      this.contextMenuItem.setAttribute("hidden", "true");
-    } else {
-      this.contextMenuItem.removeAttribute("hidden");
-    }
-  },
-
-  onCommand: function (cmd) {
-    if (cmd === "cmd-delete") {
-      let tree = this.host.projectTree;
-      let resource = tree.getSelectedResource();
-
-      if (!this.confirmDelete(resource)) {
-        return;
-      }
-
-      resource.delete().then(() => {
-        this.host.project.refresh();
-      });
-    }
-  }
-});
-
-exports.DeletePlugin = DeletePlugin;
-registerPlugin(DeletePlugin);
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/delete/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- 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(
-    'delete.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/dirty/dirty.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- 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/. */
-
-const { Class } = require("sdk/core/heritage");
-const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core");
-const { emit } = require("sdk/event/core");
-
-var DirtyPlugin = Class({
-  extends: Plugin,
-
-  onEditorSave: function (editor) { this.onEditorChange(editor); },
-  onEditorLoad: function (editor) { this.onEditorChange(editor); },
-
-  onEditorChange: function (editor) {
-    // Only run on a TextEditor
-    if (!editor || !editor.editor) {
-      return;
-    }
-
-    // Dont' force a refresh unless the dirty state has changed...
-    let priv = this.priv(editor);
-    let clean = editor.isClean();
-    if (priv.isClean !== clean) {
-      let resource = editor.shell.resource;
-      emit(resource, "label-change", resource);
-      priv.isClean = clean;
-    }
-  },
-
-  onAnnotate: function (resource, editor, elt) {
-    // Only run on a TextEditor
-    if (!editor || !editor.editor) {
-      return;
-    }
-
-    if (!editor.isClean()) {
-      elt.textContent = "*" + resource.displayName;
-      return true;
-    }
-  }
-});
-exports.DirtyPlugin = DirtyPlugin;
-
-registerPlugin(DirtyPlugin);
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/dirty/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- 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(
-    'dirty.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/image-view/image-editor.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- 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/. */
-
-const { Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const promise = require("promise");
-const { ItchEditor } = require("devtools/client/projecteditor/lib/editors");
-
-var ImageEditor = Class({
-  extends: ItchEditor,
-
-  initialize: function () {
-    ItchEditor.prototype.initialize.apply(this, arguments);
-    this.label = "image";
-    this.appended = promise.resolve();
-  },
-
-  load: function (resource) {
-    this.elt.innerHTML = "";
-    let image = this.image = this.doc.createElement("image");
-    image.className = "editor-image";
-    image.setAttribute("src", resource.uri);
-
-    let box1 = this.doc.createElement("box");
-    box1.appendChild(image);
-
-    let box2 = this.doc.createElement("box");
-    box2.setAttribute("flex", 1);
-
-    this.elt.appendChild(box1);
-    this.elt.appendChild(box2);
-
-    this.appended.then(() => {
-      this.emit("load");
-    });
-  },
-
-  destroy: function () {
-    if (this.image) {
-      this.image.remove();
-      this.image = null;
-    }
-  }
-
-});
-
-exports.ImageEditor = ImageEditor;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/image-view/moz.build
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- 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(
-    'image-editor.js',
-    'plugin.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/image-view/plugin.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- 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/. */
-
-const { Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const promise = require("promise");
-const { ImageEditor } = require("./image-editor");
-const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core");
-
-var ImageEditorPlugin = Class({
-  extends: Plugin,
-
-  editorForResource: function (node) {
-    if (node.contentCategory === "image") {
-      return ImageEditor;
-    }
-  },
-
-  init: function (host) {
-
-  }
-});
-
-exports.ImageEditorPlugin = ImageEditorPlugin;
-registerPlugin(ImageEditorPlugin);
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/logging/logging.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/* -*- 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/. */
-
-var { Class } = require("sdk/core/heritage");
-var { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core");
-
-var LoggingPlugin = Class({
-  extends: Plugin,
-
-  // Editor state lifetime...
-  onEditorCreated: function (editor) { console.log("editor created: " + editor); },
-  onEditorDestroyed: function (editor) { console.log("editor destroyed: " + editor);},
-
-  onEditorSave: function (editor) { console.log("editor saved: " + editor); },
-  onEditorLoad: function (editor) { console.log("editor loaded: " + editor); },
-
-  onEditorActivated: function (editor) { console.log("editor activated: " + editor);},
-  onEditorDeactivated: function (editor) { console.log("editor deactivated: " + editor);},
-
-  onEditorChange: function (editor) { console.log("editor changed: " + editor);},
-
-  onCommand: function (cmd) { console.log("Command: " + cmd); }
-});
-exports.LoggingPlugin = LoggingPlugin;
-
-registerPlugin(LoggingPlugin);
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/logging/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- 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(
-    'logging.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/moz.build
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- 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/.
-
-DIRS += [
-    'app-manager',
-    'delete',
-    'dirty',
-    'image-view',
-    'logging',
-    'new',
-    'rename',
-    'save',
-    'status-bar',
-]
-
-DevToolsModules(
-    'core.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/new/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- 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(
-    'new.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/new/new.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- 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/. */
-
-const { Class } = require("sdk/core/heritage");
-const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core");
-const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n");
-
-// Handles the new command.
-var NewFile = Class({
-  extends: Plugin,
-
-  init: function () {
-    this.command = this.host.addCommand(this, {
-      id: "cmd-new",
-      key: getLocalizedString("projecteditor.new.commandkey"),
-      modifiers: "accel"
-    });
-    this.host.createMenuItem({
-      parent: this.host.fileMenuPopup,
-      label: getLocalizedString("projecteditor.newLabel"),
-      command: "cmd-new",
-      key: "key_cmd-new"
-    });
-    this.host.createMenuItem({
-      parent: this.host.contextMenuPopup,
-      label: getLocalizedString("projecteditor.newLabel"),
-      command: "cmd-new"
-    });
-  },
-
-  onCommand: function (cmd) {
-    if (cmd === "cmd-new") {
-      let tree = this.host.projectTree;
-      let resource = tree.getSelectedResource();
-      parent = resource.isDir ? resource : resource.parent;
-      sibling = resource.isDir ? null : resource;
-
-      if (!("createChild" in parent)) {
-        return;
-      }
-
-      let extension = sibling ? sibling.contentCategory : parent.store.defaultCategory;
-      let template = "untitled{1}." + extension;
-      let name = this.suggestName(parent, template);
-
-      tree.promptNew(name, parent, sibling).then(name => {
-
-        // XXX: sanitize bad file names.
-
-        // If the name is already taken, just add/increment a number.
-        if (parent.hasChild(name)) {
-          let matches = name.match(/([^\d.]*)(\d*)([^.]*)(.*)/);
-          template = matches[1] + "{1}" + matches[3] + matches[4];
-          name = this.suggestName(parent, template, parseInt(matches[2]) || 2);
-        }
-
-        return parent.createChild(name);
-      }).then(resource => {
-        tree.selectResource(resource);
-        this.host.currentEditor.focus();
-      }).then(null, console.error);
-    }
-  },
-
-  suggestName: function (parent, template, start = 1) {
-    let i = start;
-    let name;
-    do {
-      name = template.replace("\{1\}", i === 1 ? "" : i);
-      i++;
-    } while (parent.hasChild(name));
-
-    return name;
-  }
-});
-exports.NewFile = NewFile;
-registerPlugin(NewFile);
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/rename/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- 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(
-    'rename.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/rename/rename.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*- 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/. */
-
-const { Class } = require("sdk/core/heritage");
-const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core");
-const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n");
-
-var RenamePlugin = Class({
-  extends: Plugin,
-
-  init: function (host) {
-    this.host.addCommand(this, {
-      id: "cmd-rename"
-    });
-    this.contextMenuItem = this.host.createMenuItem({
-      parent: this.host.contextMenuPopup,
-      label: getLocalizedString("projecteditor.renameLabel"),
-      command: "cmd-rename"
-    });
-  },
-
-  onContextMenuOpen: function (resource) {
-    if (resource.isRoot) {
-      this.contextMenuItem.setAttribute("hidden", "true");
-    } else {
-      this.contextMenuItem.removeAttribute("hidden");
-    }
-  },
-
-  onCommand: function (cmd) {
-    if (cmd === "cmd-rename") {
-      let tree = this.host.projectTree;
-      let resource = tree.getSelectedResource();
-      let parent = resource.parent;
-      let oldName = resource.basename;
-
-      tree.promptEdit(oldName, resource).then(name => {
-        if (name === oldName) {
-          return resource;
-        }
-        if (parent.hasChild(name)) {
-          let matches = name.match(/([^\d.]*)(\d*)([^.]*)(.*)/);
-          let template = matches[1] + "{1}" + matches[3] + matches[4];
-          name = this.suggestName(resource, template, parseInt(matches[2]) || 2);
-        }
-        return parent.rename(oldName, name);
-      }).then(resource => {
-        this.host.project.refresh();
-        tree.selectResource(resource);
-        if (!resource.isDir) {
-          this.host.currentEditor.focus();
-        }
-      }).then(null, console.error);
-    }
-  },
-
-  suggestName: function (resource, template, start = 1) {
-    let i = start;
-    let name;
-    let parent = resource.parent;
-    do {
-      name = template.replace("\{1\}", i === 1 ? "" : i);
-      i++;
-    } while (parent.hasChild(name));
-
-    return name;
-  }
-});
-
-exports.RenamePlugin = RenamePlugin;
-registerPlugin(RenamePlugin);
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/save/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- 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(
-    'save.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/save/save.js
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- 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/. */
-
-const { Class } = require("sdk/core/heritage");
-const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core");
-const picker = require("devtools/client/projecteditor/lib/helpers/file-picker");
-const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n");
-
-// Handles the save command.
-var SavePlugin = Class({
-  extends: Plugin,
-
-  init: function (host) {
-
-    this.host.addCommand(this, {
-      id: "cmd-save",
-      key: getLocalizedString("projecteditor.save.commandkey"),
-      modifiers: "accel"
-    });
-    this.host.addCommand(this, {
-      id: "cmd-saveas",
-      key: getLocalizedString("projecteditor.save.commandkey"),
-      modifiers: "accel shift"
-    });
-    this.host.createMenuItem({
-      parent: this.host.fileMenuPopup,
-      label: getLocalizedString("projecteditor.saveLabel"),
-      command: "cmd-save",
-      key: "key_cmd-save"
-    });
-    this.host.createMenuItem({
-      parent: this.host.fileMenuPopup,
-      label: getLocalizedString("projecteditor.saveAsLabel"),
-      command: "cmd-saveas",
-      key: "key_cmd-saveas"
-    });
-  },
-
-  isCommandEnabled: function (cmd) {
-    let currentEditor = this.host.currentEditor;
-    return currentEditor.isEditable;
-  },
-
-  onCommand: function (cmd) {
-    if (cmd === "cmd-save") {
-      this.onEditorSaveRequested();
-    } else if (cmd === "cmd-saveas") {
-      this.saveAs();
-    }
-  },
-
-  saveAs: function () {
-    let editor = this.host.currentEditor;
-    let project = this.host.resourceFor(editor);
-
-    let resource;
-    picker.showSave({
-      window: this.host.window,
-      directory: project && project.parent ? project.parent.path : null,
-      defaultName: project ? project.basename : null,
-    }).then(path => {
-      return this.createResource(path);
-    }).then(res => {
-      resource = res;
-      return this.saveResource(editor, resource);
-    }).then(() => {
-      this.host.openResource(resource);
-    }).then(null, console.error);
-  },
-
-  onEditorSaveRequested: function () {
-    let editor = this.host.currentEditor;
-    let resource = this.host.resourceFor(editor);
-    if (!resource) {
-      return this.saveAs();
-    }
-
-    return this.saveResource(editor, resource);
-  },
-
-  createResource: function (path) {
-    return this.host.project.resourceFor(path, { create: true });
-  },
-
-  saveResource: function (editor, resource) {
-    return editor.save(resource);
-  }
-});
-exports.SavePlugin = SavePlugin;
-registerPlugin(SavePlugin);
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/status-bar/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- 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(
-    'plugin.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/plugins/status-bar/plugin.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- 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/. */
-
-const { Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const promise = require("promise");
-const { registerPlugin, Plugin } = require("devtools/client/projecteditor/lib/plugins/core");
-
-/**
- * Print information about the currently opened file
- * and the state of the current editor
- */
-var StatusBarPlugin = Class({
-  extends: Plugin,
-
-  init: function () {
-    this.box = this.host.createElement("hbox", {
-      parent: "#projecteditor-toolbar-bottom"
-    });
-
-    this.activeMode = this.host.createElement("label", {
-      parent: this.box,
-      class: "projecteditor-basic-display"
-    });
-
-    this.cursorPosition = this.host.createElement("label", {
-      parent: this.box,
-      class: "projecteditor-basic-display"
-    });
-
-    this.fileLabel = this.host.createElement("label", {
-      parent: "#plugin-toolbar-left",
-      class: "projecteditor-file-label"
-    });
-  },
-
-  destroy: function () {
-  },
-
-  /**
-   * Print information about the current state of the editor
-   *
-   * @param Editor editor
-   */
-  render: function (editor, resource) {
-    if (!resource || resource.isDir) {
-      this.fileLabel.textContent = "";
-      this.cursorPosition.value = "";
-      return;
-    }
-
-    this.fileLabel.textContent = resource.basename;
-    this.activeMode.value = editor.toString();
-    if (editor.editor) {
-      let cursorStart = editor.editor.getCursor("start");
-      let cursorEnd = editor.editor.getCursor("end");
-      if (cursorStart.line === cursorEnd.line && cursorStart.ch === cursorEnd.ch) {
-        this.cursorPosition.value = cursorStart.line + " " + cursorStart.ch;
-      } else {
-        this.cursorPosition.value = cursorStart.line + " " + cursorStart.ch + " | " +
-                                    cursorEnd.line + " " + cursorEnd.ch;
-      }
-    } else {
-      this.cursorPosition.value = "";
-    }
-  },
-
-
-  /**
-   * Print the current file name
-   *
-   * @param Resource resource
-   */
-  onTreeSelected: function (resource) {
-    if (!resource || resource.isDir) {
-      this.fileLabel.textContent = "";
-      return;
-    }
-    this.fileLabel.textContent = resource.basename;
-  },
-
-  onEditorDeactivated: function (editor) {
-    this.fileLabel.textContent = "";
-    this.cursorPosition.value = "";
-  },
-
-  onEditorChange: function (editor, resource) {
-    this.render(editor, resource);
-  },
-
-  onEditorCursorActivity: function (editor, resource) {
-    this.render(editor, resource);
-  },
-
-  onEditorActivated: function (editor, resource) {
-    this.render(editor, resource);
-  },
-
-});
-
-exports.StatusBarPlugin = StatusBarPlugin;
-registerPlugin(StatusBarPlugin);
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/project.js
+++ /dev/null
@@ -1,246 +0,0 @@
-/* -*- 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/. */
-
-const { Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const { EventTarget } = require("sdk/event/target");
-const { emit } = require("sdk/event/core");
-const { scope, on, forget } = require("devtools/client/projecteditor/lib/helpers/event");
-const prefs = require("sdk/preferences/service");
-const { LocalStore } = require("devtools/client/projecteditor/lib/stores/local");
-const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
-const { Task } = require("devtools/shared/task");
-const promise = require("promise");
-const { TextEncoder, TextDecoder } = require("sdk/io/buffer");
-const url = require("sdk/url");
-
-const gDecoder = new TextDecoder();
-const gEncoder = new TextEncoder();
-
-/**
- * A Project keeps track of the opened folders using LocalStore
- * objects.  Resources are generally requested from the project,
- * even though the Store is actually keeping track of them.
- *
- *
- * This object emits the following events:
- *   - "refresh-complete": After all stores have been refreshed from disk.
- *   - "store-added": When a store has been added to the project.
- *   - "store-removed": When a store has been removed from the project.
- *   - "resource-added": When a resource has been added to one of the stores.
- *   - "resource-removed": When a resource has been removed from one of the stores.
- */
-var Project = Class({
-  extends: EventTarget,
-
-  /**
-   * Intialize the Project.
-   *
-   * @param Object options
-   *               Options to be passed into Project.load function
-   */
-  initialize: function (options) {
-    this.localStores = new Map();
-
-    this.load(options);
-  },
-
-  destroy: function () {
-    // We are removing the store because the project never gets persisted.
-    // There may need to be separate destroy functionality that doesn't remove
-    // from project if this is saved to DB.
-    this.removeAllStores();
-  },
-
-  toString: function () {
-    return "[Project] " + this.name;
-  },
-
-  /**
-   * Load a project given metadata about it.
-   *
-   * @param Object options
-   *               Information about the project, containing:
-   *                id: An ID (currently unused, but could be used for saving)
-   *                name: The display name of the project
-   *                directories: An array of path strings to load
-   */
-  load: function (options) {
-    this.id = options.id;
-    this.name = options.name || "Untitled";
-
-    let paths = new Set(options.directories.map(name => OS.Path.normalize(name)));
-
-    for (let [path, store] of this.localStores) {
-      if (!paths.has(path)) {
-        this.removePath(path);
-      }
-    }
-
-    for (let path of paths) {
-      this.addPath(path);
-    }
-  },
-
-  /**
-   * Refresh all project stores from disk
-   *
-   * @returns Promise
-   *          A promise that resolves when everything has been refreshed.
-   */
-  refresh: function () {
-    return Task.spawn(function* () {
-      for (let [path, store] of this.localStores) {
-        yield store.refresh();
-      }
-      emit(this, "refresh-complete");
-    }.bind(this));
-  },
-
-
-  /**
-   * Fetch a resource from the backing storage system for the store.
-   *
-   * @param string path
-   *               The path to fetch
-   * @param Object options
-   *               "create": bool indicating whether to create a file if it does not exist.
-   * @returns Promise
-   *          A promise that resolves with the Resource.
-   */
-  resourceFor: function (path, options) {
-    let store = this.storeContaining(path);
-    return store.resourceFor(path, options);
-  },
-
-  /**
-   * Get every resource used inside of the project.
-   *
-   * @returns Array<Resource>
-   *          A list of all Resources in all Stores.
-   */
-  allResources: function () {
-    let resources = [];
-    for (let store of this.allStores()) {
-      resources = resources.concat(store.allResources());
-    }
-    return resources;
-  },
-
-  /**
-   * Get every Path used inside of the project.
-   *
-   * @returns generator-iterator<Store>
-   *          A list of all Stores
-   */
-  allStores: function* () {
-    for (let [path, store] of this.localStores) {
-      yield store;
-    }
-  },
-
-  /**
-   * Get every file path used inside of the project.
-   *
-   * @returns Array<string>
-   *          A list of all file paths
-   */
-  allPaths: function () {
-    return [...this.localStores.keys()];
-  },
-
-  /**
-   * Get the store that contains a path.
-   *
-   * @returns Store
-   *          The store, if any.  Will return null if no store
-   *          contains the given path.
-   */
-  storeContaining: function (path) {
-    let containingStore = null;
-    for (let store of this.allStores()) {
-      if (store.contains(path)) {
-        // With nested projects, the final containing store will be returned.
-        containingStore = store;
-      }
-    }
-    return containingStore;
-  },
-
-  /**
-   * Add a store at the current path.  If a store already exists
-   * for this path, then return it.
-   *
-   * @param string path
-   * @returns LocalStore
-   */
-  addPath: function (path) {
-    if (!this.localStores.has(path)) {
-      this.addLocalStore(new LocalStore(path));
-    }
-    return this.localStores.get(path);
-  },
-
-  /**
-   * Remove a store for a given path.
-   *
-   * @param string path
-   */
-  removePath: function (path) {
-    this.removeLocalStore(this.localStores.get(path));
-  },
-
-
-  /**
-   * Add the given Store to the project.
-   * Fires a 'store-added' event on the project.
-   *
-   * @param Store store
-   */
-  addLocalStore: function (store) {
-    store.canPair = true;
-    this.localStores.set(store.path, store);
-
-    // Originally StoreCollection.addStore
-    on(this, store, "resource-added", (resource) => {
-      emit(this, "resource-added", resource);
-    });
-    on(this, store, "resource-removed", (resource) => {
-      emit(this, "resource-removed", resource);
-    });
-
-    emit(this, "store-added", store);
-  },
-
-
-  /**
-   * Remove all of the Stores belonging to the project.
-   */
-  removeAllStores: function () {
-    for (let store of this.allStores()) {
-      this.removeLocalStore(store);
-    }
-  },
-
-  /**
-   * Remove the given Store from the project.
-   * Fires a 'store-removed' event on the project.
-   *
-   * @param Store store
-   */
-  removeLocalStore: function (store) {
-    // XXX: tree selection should be reset if active element is affected by
-    // the store being removed
-    if (store) {
-      this.localStores.delete(store.path);
-      forget(this, store);
-      emit(this, "store-removed", store);
-      store.destroy();
-    }
-  }
-});
-
-exports.Project = Project;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/projecteditor.js
+++ /dev/null
@@ -1,816 +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, Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const { Project } = require("devtools/client/projecteditor/lib/project");
-const { ProjectTreeView } = require("devtools/client/projecteditor/lib/tree");
-const { ShellDeck } = require("devtools/client/projecteditor/lib/shells");
-const { Resource } = require("devtools/client/projecteditor/lib/stores/resource");
-const { registeredPlugins } = require("devtools/client/projecteditor/lib/plugins/core");
-const { EventTarget } = require("sdk/event/target");
-const { on, forget } = require("devtools/client/projecteditor/lib/helpers/event");
-const { emit } = require("sdk/event/core");
-const { merge } = require("sdk/util/object");
-const promise = require("promise");
-const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
-const { DOMHelpers } = require("resource://devtools/client/shared/DOMHelpers.jsm");
-const Services = require("Services");
-const { Task } = require("devtools/shared/task");
-const ITCHPAD_URL = "chrome://devtools/content/projecteditor/chrome/content/projecteditor.xul";
-const { confirm } = require("devtools/client/projecteditor/lib/helpers/prompts");
-const { getLocalizedString } = require("devtools/client/projecteditor/lib/helpers/l10n");
-
-// Enabled Plugins
-require("devtools/client/projecteditor/lib/plugins/dirty/dirty");
-require("devtools/client/projecteditor/lib/plugins/delete/delete");
-require("devtools/client/projecteditor/lib/plugins/new/new");
-require("devtools/client/projecteditor/lib/plugins/rename/rename");
-require("devtools/client/projecteditor/lib/plugins/save/save");
-require("devtools/client/projecteditor/lib/plugins/image-view/plugin");
-require("devtools/client/projecteditor/lib/plugins/app-manager/plugin");
-require("devtools/client/projecteditor/lib/plugins/status-bar/plugin");
-
-// Uncomment to enable logging.
-// require("devtools/client/projecteditor/lib/plugins/logging/logging");
-
-/**
- * This is the main class tying together an instance of the ProjectEditor.
- * The frontend is contained inside of this.iframe, which loads projecteditor.xul.
- *
- * Usage:
- *   let projecteditor = new ProjectEditor(frame);
- *   projecteditor.loaded.then((projecteditor) => {
- *      // Ready to use.
- *   });
- *
- * Responsible for maintaining:
- *   - The list of Plugins for this instance.
- *   - The ShellDeck, which includes all Shells for opened Resources
- *   -- Shells take in a Resource, and construct the appropriate Editor
- *   - The Project, which includes all Stores for this instance
- *   -- Stores manage all Resources starting from a root directory
- *   --- Resources are a representation of a file on disk
- *   - The ProjectTreeView that builds the UI for interacting with the
- *     project.
- *
- * This object emits the following events:
- *   - "onEditorDestroyed": When editor is destroyed
- *   - "onEditorSave": When editor is saved
- *   - "onEditorLoad": When editor is loaded
- *   - "onEditorActivated": When editor is activated
- *   - "onEditorChange": When editor is changed
- *   - "onEditorCursorActivity": When there is cursor activity in a text editor
- *   - "onCommand": When a command happens
- *   - "onEditorDestroyed": When editor is destroyed
- *   - "onContextMenuOpen": When the context menu is opened on the project tree
- *
- * The events can be bound like so:
- *   projecteditor.on("onEditorCreated", (editor) => { });
- */
-var ProjectEditor = Class({
-  extends: EventTarget,
-
-  /**
-   * Initialize ProjectEditor, and load into an iframe if specified.
-   *
-   * @param Iframe iframe
-   *        The iframe to inject the DOM into.  If this is not
-   *        specified, then this.load(frame) will need to be called
-   *        before accessing ProjectEditor.
-   * @param Object options
-   *         - menubar: a <menubar> element to inject menus into
-   *         - menuindex: Integer child index to insert menus
-   */
-  initialize: function (iframe, options = {}) {
-    this._onTreeSelected = this._onTreeSelected.bind(this);
-    this._onTreeResourceRemoved = this._onTreeResourceRemoved.bind(this);
-    this._onEditorCreated = this._onEditorCreated.bind(this);
-    this._onEditorActivated = this._onEditorActivated.bind(this);
-    this._onEditorDeactivated = this._onEditorDeactivated.bind(this);
-    this._updateMenuItems = this._updateMenuItems.bind(this);
-    this._updateContextMenuItems = this._updateContextMenuItems.bind(this);
-    this.destroy = this.destroy.bind(this);
-    this.menubar = options.menubar || null;
-    this.menuindex = options.menuindex || null;
-    this._menuEnabled = true;
-    this._destroyed = false;
-    this._loaded = false;
-    this._pluginCommands = new Map();
-    if (iframe) {
-      this.load(iframe);
-    }
-  },
-
-  /**
-   * Load the instance inside of a specified iframe.
-   * This can be called more than once, and it will return the promise
-   * from the first call.
-   *
-   * @param Iframe iframe
-   *        The iframe to inject the projecteditor DOM into
-   * @returns Promise
-   *          A promise that is resolved once the iframe has been
-   *          loaded.
-   */
-  load: function (iframe) {
-    if (this.loaded) {
-      return this.loaded;
-    }
-
-    let deferred = promise.defer();
-    this.loaded = deferred.promise;
-    this.iframe = iframe;
-
-    let domReady = () => {
-      if (this._destroyed) {
-        deferred.reject("Error: ProjectEditor has been destroyed before loading");
-        return;
-      }
-      this._onLoad();
-      this._loaded = true;
-      deferred.resolve(this);
-    };
-
-    let domHelper = new DOMHelpers(this.iframe.contentWindow);
-    domHelper.onceDOMReady(domReady);
-
-    this.iframe.setAttribute("src", ITCHPAD_URL);
-
-    return this.loaded;
-  },
-
-  /**
-   * Build the projecteditor DOM inside of this.iframe.
-   */
-  _onLoad: function () {
-    this.document = this.iframe.contentDocument;
-    this.window = this.iframe.contentWindow;
-
-    this._initCommands();
-    this._buildMenubar();
-    this._buildSidebar();
-
-    this.window.addEventListener("unload", this.destroy);
-
-    // Editor management
-    this.shells = new ShellDeck(this, this.document);
-    this.shells.on("editor-created", this._onEditorCreated);
-    this.shells.on("editor-activated", this._onEditorActivated);
-    this.shells.on("editor-deactivated", this._onEditorDeactivated);
-
-    let shellContainer = this.document.querySelector("#shells-deck-container");
-    shellContainer.appendChild(this.shells.elt);
-
-    // We are not allowing preset projects for now - rebuild a fresh one
-    // each time.
-    this.setProject(new Project({
-      id: "",
-      name: "",
-      directories: [],
-      openFiles: []
-    }));
-
-    this._initPlugins();
-  },
-
-  _buildMenubar: function () {
-
-    this.contextMenuPopup = this.document.getElementById("context-menu-popup");
-    this.contextMenuPopup.addEventListener("popupshowing", this._updateContextMenuItems);
-
-    this.textEditorContextMenuPopup = this.document.getElementById("texteditor-context-popup");
-    this.textEditorContextMenuPopup.addEventListener("popupshowing", this._updateMenuItems);
-
-    this.editMenu = this.document.getElementById("edit-menu");
-    this.fileMenu = this.document.getElementById("file-menu");
-
-    this.editMenuPopup = this.document.getElementById("edit-menu-popup");
-    this.fileMenuPopup = this.document.getElementById("file-menu-popup");
-    this.editMenu.addEventListener("popupshowing", this._updateMenuItems);
-    this.fileMenu.addEventListener("popupshowing", this._updateMenuItems);
-
-    if (this.menubar) {
-      let body = this.menubar.ownerDocument.body ||
-                 this.menubar.ownerDocument.querySelector("window");
-      body.appendChild(this.projectEditorCommandset);
-      body.appendChild(this.projectEditorKeyset);
-      body.appendChild(this.editorCommandset);
-      body.appendChild(this.editorKeyset);
-      body.appendChild(this.contextMenuPopup);
-      body.appendChild(this.textEditorContextMenuPopup);
-
-      let index = this.menuindex || 0;
-      this.menubar.insertBefore(this.editMenu, this.menubar.children[index]);
-      this.menubar.insertBefore(this.fileMenu, this.menubar.children[index]);
-    } else {
-      this.document.getElementById("projecteditor-menubar").style.display = "block";
-    }
-
-    // Insert a controller to allow enabling and disabling of menu items.
-    this._commandWindow = this.editorCommandset.ownerDocument.defaultView;
-    this._commandController = getCommandController(this);
-    this._commandWindow.controllers.insertControllerAt(0, this._commandController);
-  },
-
-  /**
-   * Create the project tree sidebar that lists files.
-   */
-  _buildSidebar: function () {
-    this.projectTree = new ProjectTreeView(this.document, {
-      resourceVisible: this.resourceVisible.bind(this),
-      resourceFormatter: this.resourceFormatter.bind(this),
-      contextMenuPopup: this.contextMenuPopup
-    });
-    on(this, this.projectTree, "selection", this._onTreeSelected);
-    on(this, this.projectTree, "resource-removed", this._onTreeResourceRemoved);
-
-    let sourcesBox = this.document.querySelector("#sources > vbox");
-    sourcesBox.appendChild(this.projectTree.elt);
-  },
-
-  /**
-   * Set up listeners for commands to dispatch to all of the plugins
-   */
-  _initCommands: function () {
-
-    this.projectEditorCommandset = this.document.getElementById("projecteditor-commandset");
-    this.projectEditorKeyset = this.document.getElementById("projecteditor-keyset");
-
-    this.editorCommandset = this.document.getElementById("editMenuCommands");
-    this.editorKeyset = this.document.getElementById("editMenuKeys");
-
-    this.projectEditorCommandset.addEventListener("command", (evt) => {
-      evt.stopPropagation();
-      evt.preventDefault();
-      this.pluginDispatch("onCommand", evt.target.id, evt.target);
-    });
-  },
-
-  /**
-   * Initialize each plugin in registeredPlugins
-   */
-  _initPlugins: function () {
-    this._plugins = [];
-
-    for (let plugin of registeredPlugins) {
-      try {
-        this._plugins.push(plugin(this));
-      } catch (ex) {
-        console.exception(ex);
-      }
-    }
-
-    this.pluginDispatch("lateInit");
-  },
-
-  /**
-   * Enable / disable necessary menu items using globalOverlay.js.
-   */
-  _updateMenuItems: function () {
-    let window = this.editMenu.ownerDocument.defaultView;
-    let commands = ["cmd_undo", "cmd_redo", "cmd_delete", "cmd_cut", "cmd_copy", "cmd_paste"];
-    commands.forEach(window.goUpdateCommand);
-
-    for (let c of this._pluginCommands.keys()) {
-      window.goUpdateCommand(c);
-    }
-  },
-
-  /**
-   * Enable / disable necessary context menu items by passing an event
-   * onto plugins.
-   */
-  _updateContextMenuItems: function () {
-    let resource = this.projectTree.getSelectedResource();
-    this.pluginDispatch("onContextMenuOpen", resource);
-  },
-
-  /**
-   * Destroy all objects on the iframe unload event.
-   */
-  destroy: function () {
-    this._destroyed = true;
-
-
-    // If been destroyed before the iframe finished loading, then
-    // the properties below will not exist.
-    if (!this._loaded) {
-      this.iframe.setAttribute("src", "about:blank");
-      return;
-    }
-
-    // Reset the src for the iframe so if it reused for a new ProjectEditor
-    // instance, the load will fire properly.
-    this.window.removeEventListener("unload", this.destroy);
-    this.iframe.setAttribute("src", "about:blank");
-
-    this._plugins.forEach(plugin => { plugin.destroy(); });
-
-    forget(this, this.projectTree);
-    this.projectTree.destroy();
-    this.projectTree = null;
-
-    this.shells.destroy();
-
-    this.projectEditorCommandset.remove();
-    this.projectEditorKeyset.remove();
-    this.editorCommandset.remove();
-    this.editorKeyset.remove();
-    this.contextMenuPopup.remove();
-    this.textEditorContextMenuPopup.remove();
-    this.editMenu.remove();
-    this.fileMenu.remove();
-
-    this._commandWindow.controllers.removeController(this._commandController);
-    this._commandController = null;
-
-    forget(this, this.project);
-    this.project.destroy();
-    this.project = null;
-  },
-
-  /**
-   * Set the current project viewed by the projecteditor.
-   *
-   * @param Project project
-   *        The project to set.
-   */
-  setProject: function (project) {
-    if (this.project) {
-      forget(this, this.project);
-    }
-    this.project = project;
-    this.projectTree.setProject(project);
-
-    // Whenever a store gets removed, clean up any editors that
-    // exist for resources within it.
-    on(this, project, "store-removed", (store) => {
-      store.allResources().forEach((resource) => {
-        this.shells.removeResource(resource);
-      });
-    });
-  },
-
-  /**
-   * Set the current project viewed by the projecteditor to a single path,
-   * used by the app manager.
-   *
-   * @param string path
-   *               The file path to set
-   * @param Object opts
-   *               Custom options used by the project.
-   *                - name: display name for project
-   *                - iconUrl: path to icon for project
-   *                - validationStatus: one of 'unknown|error|warning|valid'
-   *                - projectOverviewURL: path to load for iframe when project
-   *                    is selected in the tree.
-   * @param Promise
-   *        Promise that is resolved once the project is ready to be used.
-   */
-  setProjectToAppPath: function (path, opts = {}) {
-    this.project.appManagerOpts = opts;
-
-    let existingPaths = this.project.allPaths();
-    if (existingPaths.length !== 1 || existingPaths[0] !== path) {
-      // Only fully reset if this is a new path.
-      this.project.removeAllStores();
-      this.project.addPath(path);
-    } else {
-      // Otherwise, just ask for the root to be redrawn
-      let rootResource = this.project.localStores.get(path).root;
-      emit(rootResource, "label-change", rootResource);
-    }
-
-    return this.project.refresh();
-  },
-
-  /**
-   * Open a resource in a particular shell.
-   *
-   * @param Resource resource
-   *                 The file to be opened.
-   */
-  openResource: function (resource) {
-    let shell = this.shells.open(resource);
-    this.projectTree.selectResource(resource);
-    shell.editor.focus();
-  },
-
-  /**
-   * When a node is selected in the tree, open its associated editor.
-   *
-   * @param Resource resource
-   *                 The file that has been selected
-   */
-  _onTreeSelected: function (resource) {
-    // Don't attempt to open a directory that is not the root element.
-    if (resource.isDir && resource.parent) {
-      return;
-    }
-    this.pluginDispatch("onTreeSelected", resource);
-    this.openResource(resource);
-  },
-
-  /**
-   * When a node is removed, destroy it and its associated editor.
-   *
-   * @param Resource resource
-   *                 The resource being removed
-   */
-  _onTreeResourceRemoved: function (resource) {
-    this.shells.removeResource(resource);
-  },
-
-  /**
-   * Create an xul element with options
-   *
-   * @param string type
-   *               The tag name of the element to create.
-   * @param Object options
-   *               "command": DOMNode or string ID of a command element.
-   *               "parent": DOMNode or selector of parent to append child to.
-   *               anything other keys are set as an attribute as the element.
-   * @returns DOMElement
-   *          The element that has been created.
-   */
-  createElement: function (type, options) {
-    let elt = this.document.createElement(type);
-
-    let parent;
-
-    for (let opt in options) {
-      if (opt === "command") {
-        let command = typeof (options.command) === "string" ? options.command : options.command.id;
-        elt.setAttribute("command", command);
-      } else if (opt === "parent") {
-        continue;
-      } else {
-        elt.setAttribute(opt, options[opt]);
-      }
-    }
-
-    if (options.parent) {
-      let parent = options.parent;
-      if (typeof (parent) === "string") {
-        parent = this.document.querySelector(parent);
-      }
-      parent.appendChild(elt);
-    }
-
-    return elt;
-  },
-
-  /**
-   * Create a "menuitem" xul element with options
-   *
-   * @param Object options
-   *               See createElement for available options.
-   * @returns DOMElement
-   *          The menuitem that has been created.
-   */
-  createMenuItem: function (options) {
-    return this.createElement("menuitem", options);
-  },
-
-  /**
-   * Add a command to the projecteditor document.
-   * This method is meant to be used with plugins.
-   *
-   * @param Object definition
-   *               key: a key/keycode string. Example: "f".
-   *               id: Unique ID.  Example: "find".
-   *               modifiers: Key modifiers. Example: "accel".
-   * @returns DOMElement
-   *          The command element that has been created.
-   */
-  addCommand: function (plugin, definition) {
-    this._pluginCommands.set(definition.id, plugin);
-    let document = this.projectEditorKeyset.ownerDocument;
-    let command = document.createElement("command");
-    command.setAttribute("id", definition.id);
-    if (definition.key) {
-      let key = document.createElement("key");
-      key.id = "key_" + definition.id;
-
-      let keyName = definition.key;
-      if (keyName.startsWith("VK_")) {
-        key.setAttribute("keycode", keyName);
-      } else {
-        key.setAttribute("key", keyName);
-      }
-      key.setAttribute("modifiers", definition.modifiers);
-      key.setAttribute("command", definition.id);
-      this.projectEditorKeyset.appendChild(key);
-    }
-    command.setAttribute("oncommand", "void(0);"); // needed. See bug 371900
-    this.projectEditorCommandset.appendChild(command);
-    return command;
-  },
-
-  /**
-   * Get the instance of a plugin registered with a certain type.
-   *
-   * @param Type pluginType
-   *             The type, such as SavePlugin
-   * @returns Plugin
-   *          The plugin instance matching the specified type.
-   */
-  getPlugin: function (pluginType) {
-    for (let plugin of this.plugins) {
-      if (plugin.constructor === pluginType) {
-        return plugin;
-      }
-    }
-    return null;
-  },
-
-  /**
-   * Get all plugin instances active for the current project
-   *
-   * @returns [Plugin]
-   */
-  get plugins() {
-    if (!this._plugins) {
-      console.log("plugins requested before _plugins was set");
-      return [];
-    }
-    // Could filter further based on the type of project selected,
-    // but no need right now.
-    return this._plugins;
-  },
-
-  /**
-   * Dispatch an onEditorCreated event, and listen for other events specific
-   * to this editor instance.
-   *
-   * @param Editor editor
-   *               The new editor instance.
-   */
-  _onEditorCreated: function (editor) {
-    this.pluginDispatch("onEditorCreated", editor);
-    this._editorListenAndDispatch(editor, "change", "onEditorChange");
-    this._editorListenAndDispatch(editor, "cursorActivity", "onEditorCursorActivity");
-    this._editorListenAndDispatch(editor, "load", "onEditorLoad");
-    this._editorListenAndDispatch(editor, "saveRequested", "onEditorSaveRequested");
-    this._editorListenAndDispatch(editor, "save", "onEditorSave");
-
-    editor.on("focus", () => {
-      this.projectTree.selectResource(this.resourceFor(editor));
-    });
-  },
-
-  /**
-   * Dispatch an onEditorActivated event and finish setting up once the
-   * editor is ready to use.
-   *
-   * @param Editor editor
-   *               The editor instance, which is now appended in the document.
-   * @param Resource resource
-   *               The resource used by the editor
-   */
-  _onEditorActivated: function (editor, resource) {
-    editor.setToolbarVisibility();
-    this.pluginDispatch("onEditorActivated", editor, resource);
-  },
-
-  /**
-   * Dispatch an onEditorDactivated event once an editor loses focus
-   *
-   * @param Editor editor
-   *               The editor instance, which is no longer active.
-   * @param Resource resource
-   *               The resource used by the editor
-   */
-  _onEditorDeactivated: function (editor, resource) {
-    this.pluginDispatch("onEditorDeactivated", editor, resource);
-  },
-
-  /**
-   * Call a method on all plugins that implement the method.
-   * Also emits the same handler name on `this`.
-   *
-   * @param string handler
-   *               Which function name to call on plugins.
-   * @param ...args args
-   *                All remaining parameters are passed into the handler.
-   */
-  pluginDispatch: function (handler, ...args) {
-    emit(this, handler, ...args);
-    this.plugins.forEach(plugin => {
-      try {
-        if (handler in plugin) plugin[handler](...args);
-      } catch (ex) {
-        console.error(ex);
-      }
-    });
-  },
-
-  /**
-   * Listen to an event on the editor object and dispatch it
-   * to all plugins that implement the associated method
-   *
-   * @param Editor editor
-   *               Which editor to listen to
-   * @param string event
-   *               Which editor event to listen for
-   * @param string handler
-   *               Which plugin method to call
-   */
-  _editorListenAndDispatch: function (editor, event, handler) {
-    editor.on(event, (...args) => {
-      this.pluginDispatch(handler, editor, this.resourceFor(editor), ...args);
-    });
-  },
-
-  /**
-   * Find a shell for a resource.
-   *
-   * @param Resource resource
-   *                 The file to be opened.
-   * @returns Shell
-   */
-  shellFor: function (resource) {
-    return this.shells.shellFor(resource);
-  },
-
-  /**
-   * Returns the Editor for a given resource.
-   *
-   * @param Resource resource
-   *                 The file to check.
-   * @returns Editor
-   *          Instance of the editor for this file.
-   */
-  editorFor: function (resource) {
-    let shell = this.shellFor(resource);
-    return shell ? shell.editor : shell;
-  },
-
-  /**
-   * Returns a resource for the given editor
-   *
-   * @param Editor editor
-   *               The editor to check
-   * @returns Resource
-   *          The resource associated with this editor
-   */
-  resourceFor: function (editor) {
-    if (editor && editor.shell && editor.shell.resource) {
-      return editor.shell.resource;
-    }
-    return null;
-  },
-
-  /**
-   * Decide whether a given resource should be hidden in the tree.
-   *
-   * @param Resource resource
-   *                 The resource in the tree
-   * @returns Boolean
-   *          True if the node should be visible, false if hidden.
-   */
-  resourceVisible: function (resource) {
-    return true;
-  },
-
-  /**
-   * Format the given node for display in the resource tree view.
-   *
-   * @param Resource resource
-   *                 The file to be opened.
-   * @param DOMNode elt
-   *                The element in the tree to render into.
-   */
-  resourceFormatter: function (resource, elt) {
-    let editor = this.editorFor(resource);
-    let renderedByPlugin = false;
-
-    // Allow plugins to override default templating of resource in tree.
-    this.plugins.forEach(plugin => {
-      if (!plugin.onAnnotate) {
-        return;
-      }
-      if (plugin.onAnnotate(resource, editor, elt)) {
-        renderedByPlugin = true;
-      }
-    });
-
-    // If no plugin wants to handle it, just use a string from the resource.
-    if (!renderedByPlugin) {
-      elt.textContent = resource.displayName;
-    }
-  },
-
-  get sourcesVisible() {
-    return this.sourceToggle.classList.contains("pane-collapsed");
-  },
-
-  get currentShell() {
-    return this.shells.currentShell;
-  },
-
-  get currentEditor() {
-    return this.shells.currentEditor;
-  },
-
-  /**
-   * Whether or not menu items should be able to be enabled.
-   * Note that even if this is true, certain menu items will not be
-   * enabled until the correct state is achieved (for instance, the
-   * 'copy' menu item is only enabled when there is a selection).
-   * But if this is false, then nothing will be enabled.
-   */
-  set menuEnabled(val) {
-    this._menuEnabled = val;
-    if (this._loaded) {
-      this._updateMenuItems();
-    }
-  },
-
-  get menuEnabled() {
-    return this._menuEnabled;
-  },
-
-  /**
-   * Are there any unsaved resources in the Project?
-   */
-  get hasUnsavedResources() {
-    return this.project.allResources().some(resource=> {
-      let editor = this.editorFor(resource);
-      return editor && !editor.isClean();
-    });
-  },
-
-  /**
-   * Check with the user about navigating away with unsaved changes.
-   *
-   * @returns Boolean
-   *          True if there are no unsaved changes
-   *          Otherwise, ask the user to confirm and return the outcome.
-   */
-  confirmUnsaved: function () {
-    if (this.hasUnsavedResources) {
-      return confirm(
-        getLocalizedString("projecteditor.confirmUnsavedTitle"),
-        getLocalizedString("projecteditor.confirmUnsavedLabel2")
-      );
-    }
-
-    return true;
-  },
-
-  /**
-   * Save all the changes in source files.
-   *
-   * @returns Boolean
-   *          True if there were resources to save.
-   */
-  saveAllFiles: Task.async(function* () {
-    if (this.hasUnsavedResources) {
-      for (let resource of this.project.allResources()) {
-        let editor = this.editorFor(resource);
-        if (editor && !editor.isClean()) {
-          yield editor.save(resource);
-        }
-      }
-
-      return true;
-    }
-
-    return false;
-  })
-
-});
-
-
-/**
- * Returns a controller object that can be used for
- * editor-specific commands such as find, jump to line,
- * copy/paste, etc.
- */
-function getCommandController(host) {
-  return {
-    supportsCommand: function (cmd) {
-      return host._pluginCommands.get(cmd);
-    },
-
-    isCommandEnabled: function (cmd) {
-      if (!host.menuEnabled) {
-        return false;
-      }
-      let plugin = host._pluginCommands.get(cmd);
-      if (plugin && plugin.isCommandEnabled) {
-        return plugin.isCommandEnabled(cmd);
-      }
-      return true;
-    },
-    doCommand: function (cmd) {
-    }
-  };
-}
-
-exports.ProjectEditor = ProjectEditor;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/shells.js
+++ /dev/null
@@ -1,243 +0,0 @@
-/* -*- 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/. */
-
-const { Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const { EventTarget } = require("sdk/event/target");
-const { emit } = require("sdk/event/core");
-const { EditorTypeForResource } = require("devtools/client/projecteditor/lib/editors");
-const NetworkHelper = require("devtools/shared/webconsole/network-helper");
-const promise = require("promise");
-
-/**
- * The Shell is the object that manages the editor for a single resource.
- * It is in charge of selecting the proper Editor (text/image/plugin-defined)
- * and instantiating / appending the editor.
- * This object is not exported, it is just used internally by the ShellDeck.
- *
- * This object has a promise `editorAppended`, that will resolve once the editor
- * is ready to be used.
- */
-var Shell = Class({
-  extends: EventTarget,
-
-  /**
-   * @param ProjectEditor host
-   * @param Resource resource
-   */
-  initialize: function (host, resource) {
-    this.host = host;
-    this.doc = host.document;
-    this.resource = resource;
-    this.elt = this.doc.createElement("vbox");
-    this.elt.classList.add("view-project-detail");
-    this.elt.shell = this;
-
-    let constructor = this._editorTypeForResource();
-
-    this.editor = constructor(this.host);
-    this.editor.shell = this;
-    this.editorAppended = this.editor.appended;
-
-    this.editor.on("load", () => {
-      this.editorDeferred.resolve();
-    });
-    this.elt.appendChild(this.editor.elt);
-  },
-
-  /**
-   * Start loading the resource.  The 'load' event happens as
-   * a result of this function, so any listeners to 'editorAppended'
-   * need to be added before calling this.
-   */
-  load: function () {
-    this.editorDeferred = promise.defer();
-    this.editorLoaded = this.editorDeferred.promise;
-    this.editor.load(this.resource);
-  },
-
-  /**
-   * Destroy the shell and its associated editor
-   */
-  destroy: function () {
-    this.editor.destroy();
-    this.resource.destroy();
-  },
-
-  /**
-   * Make sure the correct editor is selected for the resource.
-   * @returns Type:Editor
-   */
-  _editorTypeForResource: function () {
-    let resource = this.resource;
-    let constructor = EditorTypeForResource(resource);
-
-    if (this.host.plugins) {
-      this.host.plugins.forEach(plugin => {
-        if (plugin.editorForResource) {
-          let pluginEditor = plugin.editorForResource(resource);
-          if (pluginEditor) {
-            constructor = pluginEditor;
-          }
-        }
-      });
-    }
-
-    return constructor;
-  }
-});
-
-/**
- * The ShellDeck is in charge of managing the list of active Shells for
- * the current ProjectEditor instance (aka host).
- *
- * This object emits the following events:
- *   - "editor-created": When an editor is initially created
- *   - "editor-activated": When an editor is ready to use
- *   - "editor-deactivated": When an editor is ready to use
- */
-var ShellDeck = Class({
-  extends: EventTarget,
-
-  /**
-   * @param ProjectEditor host
-   * @param Document document
-   */
-  initialize: function (host, document) {
-    this.doc = document;
-    this.host = host;
-    this.deck = this.doc.createElement("deck");
-    this.deck.setAttribute("flex", "1");
-    this.elt = this.deck;
-
-    this.shells = new Map();
-
-    this._activeShell = null;
-  },
-
-  /**
-   * Open a resource in a Shell.  Will create the Shell
-   * if it doesn't exist yet.
-   *
-   * @param Resource resource
-   *                 The file to be opened
-   * @returns Shell
-   */
-  open: function (defaultResource) {
-    let shell = this.shellFor(defaultResource);
-    if (!shell) {
-      shell = this._createShell(defaultResource);
-      this.shells.set(defaultResource, shell);
-    }
-    this.selectShell(shell);
-    return shell;
-  },
-
-  /**
-   * Create a new Shell for a resource.  Called by `open`.
-   *
-   * @returns Shell
-   */
-  _createShell: function (defaultResource) {
-    let shell = Shell(this.host, defaultResource);
-
-    shell.editorAppended.then(() => {
-      this.shells.set(shell.resource, shell);
-      emit(this, "editor-created", shell.editor);
-      if (this.currentShell === shell) {
-        this.selectShell(shell);
-      }
-
-    });
-
-    shell.load();
-    this.deck.appendChild(shell.elt);
-    return shell;
-  },
-
-  /**
-   * Remove the shell for a given resource.
-   *
-   * @param Resource resource
-   */
-  removeResource: function (resource) {
-    let shell = this.shellFor(resource);
-    if (shell) {
-      this.shells.delete(resource);
-      shell.destroy();
-    }
-  },
-
-  destroy: function () {
-    for (let [resource, shell] of this.shells.entries()) {
-      this.shells.delete(resource);
-      shell.destroy();
-    }
-  },
-
-  /**
-   * Select a given shell and open its editor.
-   * Will fire editor-deactivated on the old selected Shell (if any),
-   * and editor-activated on the new one once it is ready
-   *
-   * @param Shell shell
-   */
-  selectShell: function (shell) {
-    // Don't fire another activate if this is already the active shell
-    if (this._activeShell != shell) {
-      if (this._activeShell) {
-        emit(this, "editor-deactivated", this._activeShell.editor, this._activeShell.resource);
-      }
-      this.deck.selectedPanel = shell.elt;
-      this._activeShell = shell;
-
-      // Only reload the shell if the editor doesn't have local changes.
-      if (shell.editor.isClean()) {
-        shell.load();
-      }
-      shell.editorLoaded.then(() => {
-        // Handle case where another shell has been requested before this
-        // one is finished loading.
-        if (this._activeShell === shell) {
-          emit(this, "editor-activated", shell.editor, shell.resource);
-        }
-      });
-    }
-  },
-
-  /**
-   * Find a Shell for a Resource.
-   *
-   * @param Resource resource
-   * @returns Shell
-   */
-  shellFor: function (resource) {
-    return this.shells.get(resource);
-  },
-
-  /**
-   * The currently active Shell.  Note: the editor may not yet be available
-   * on the current shell.  Best to wait for the 'editor-activated' event
-   * instead.
-   *
-   * @returns Shell
-   */
-  get currentShell() {
-    return this._activeShell;
-  },
-
-  /**
-   * The currently active Editor, or null if it is not ready.
-   *
-   * @returns Editor
-   */
-  get currentEditor() {
-    let shell = this.currentShell;
-    return shell ? shell.editor : null;
-  },
-
-});
-exports.ShellDeck = ShellDeck;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/stores/base.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- 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/. */
-
-const { Cc, Ci, Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const { EventTarget } = require("sdk/event/target");
-const { emit } = require("sdk/event/core");
-const promise = require("promise");
-
-/**
- * A Store object maintains a collection of Resource objects stored in a tree.
- *
- * The Store class should not be instantiated directly.  Instead, you should
- * use a class extending it - right now this is only a LocalStore.
- *
- * Events:
- * This object emits the 'resource-added' and 'resource-removed' events.
- */
-var Store = Class({
-  extends: EventTarget,
-
-  /**
-   * Should be called during initialize() of a subclass.
-   */
-  initStore: function () {
-    this.resources = new Map();
-  },
-
-  refresh: function () {
-    return promise.resolve();
-  },
-
-  /**
-   * Return a sorted Array of all Resources in the Store
-   */
-  allResources: function () {
-    var resources = [];
-    function addResource(resource) {
-      resources.push(resource);
-      resource.childrenSorted.forEach(addResource);
-    }
-    addResource(this.root);
-    return resources;
-  },
-
-  notifyAdd: function (resource) {
-    emit(this, "resource-added", resource);
-  },
-
-  notifyRemove: function (resource) {
-    emit(this, "resource-removed", resource);
-  }
-});
-
-exports.Store = Store;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/stores/local.js
+++ /dev/null
@@ -1,215 +0,0 @@
-/* -*- 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/. */
-
-const { Cc, Ci, Cu, ChromeWorker } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const { OS } = require("resource://gre/modules/osfile.jsm");
-const { emit } = require("sdk/event/core");
-const { Store } = require("devtools/client/projecteditor/lib/stores/base");
-const { Task } = require("devtools/shared/task");
-const promise = require("promise");
-const Services = require("Services");
-const { on, forget } = require("devtools/client/projecteditor/lib/helpers/event");
-const { FileResource } = require("devtools/client/projecteditor/lib/stores/resource");
-
-const CHECK_LINKED_DIRECTORY_DELAY = 5000;
-const SHOULD_LIVE_REFRESH = true;
-// XXX: Ignores should be customizable
-const IGNORE_REGEX = /(^\.)|(\~$)|(^node_modules$)/;
-
-/**
- * A LocalStore object maintains a collection of Resource objects
- * from the file system.
- *
- * This object emits the following events:
- *   - "resource-added": When a resource is added
- *   - "resource-removed": When a resource is removed
- */
-var LocalStore = Class({
-  extends: Store,
-
-  defaultCategory: "js",
-
-  initialize: function(path) {
-    this.initStore();
-    this.path = OS.Path.normalize(path);
-    this.rootPath = this.path;
-    this.displayName = this.path;
-    this.root = this._forPath(this.path);
-    this.notifyAdd(this.root);
-    this.refreshLoop = this.refreshLoop.bind(this);
-    this.refreshLoop();
-  },
-
-  destroy: function() {
-    clearTimeout(this._refreshTimeout);
-
-    if (this._refreshDeferred) {
-      this._refreshDeferred.reject("destroy");
-    }
-    if (this.worker) {
-      this.worker.terminate();
-    }
-
-    this._refreshTimeout = null;
-    this._refreshDeferred = null;
-    this.worker = null;
-
-    if (this.root) {
-      forget(this, this.root);
-      this.root.destroy();
-    }
-  },
-
-  toString: function() { return "[LocalStore:" + this.path + "]" },
-
-  /**
-   * Return a FileResource object for the given path.  If a FileInfo
-   * is provided the resource will use it, otherwise the FileResource
-   * might not have full information until the next refresh.
-   *
-   * The following parameters are passed into the FileResource constructor
-   * See resource.js for information about them
-   *
-   * @param String path
-   * @param FileInfo info
-   * @returns Resource
-   */
-  _forPath: function(path, info=null) {
-    if (this.resources.has(path)) {
-      return this.resources.get(path);
-    }
-
-    let resource = FileResource(this, path, info);
-    this.resources.set(path, resource);
-    return resource;
-  },
-
-  /**
-   * Return a promise that resolves to a fully-functional FileResource
-   * within this project.  This will hit the disk for stat info.
-   * options:
-   *
-   *   create: If true, a resource will be created even if the underlying
-   *     file doesn't exist.
-   */
-  resourceFor: function(path, options) {
-    path = OS.Path.normalize(path);
-
-    if (this.resources.has(path)) {
-      return promise.resolve(this.resources.get(path));
-    }
-
-    if (!this.contains(path)) {
-      return promise.reject(new Error(path + " does not belong to " + this.path));
-    }
-
-    return Task.spawn(function*() {
-      let parent = yield this.resourceFor(OS.Path.dirname(path));
-
-      let info;
-      try {
-        info = yield OS.File.stat(path);
-      } catch (ex if ex instanceof OS.File.Error && ex.becauseNoSuchFile) {
-        if (!options.create) {
-          throw ex;
-        }
-      }
-
-      let resource = this._forPath(path, info);
-      parent.addChild(resource);
-      return resource;
-    }.bind(this));
-  },
-
-  refreshLoop: function() {
-    // XXX: Once Bug 958280 adds a watch function, will not need to forever loop here.
-    this.refresh().then(() => {
-      if (SHOULD_LIVE_REFRESH) {
-        this._refreshTimeout = setTimeout(this.refreshLoop,
-          CHECK_LINKED_DIRECTORY_DELAY);
-      }
-    });
-  },
-
-  _refreshTimeout: null,
-  _refreshDeferred: null,
-
-  /**
-   * Refresh the directory structure.
-   */
-  refresh: function(path=this.rootPath) {
-    if (this._refreshDeferred) {
-      return this._refreshDeferred.promise;
-    }
-    this._refreshDeferred = promise.defer();
-
-    let worker = this.worker = new ChromeWorker("chrome://devtools/content/projecteditor/lib/helpers/readdir.js");
-    let start = Date.now();
-
-    worker.onmessage = evt => {
-      // console.log("Directory read finished in " + ( Date.now() - start ) +"ms", evt);
-      for (path in evt.data) {
-        let info = evt.data[path];
-        info.path = path;
-
-        let resource = this._forPath(path, info);
-        resource.info = info;
-        if (info.isDir) {
-          let newChildren = new Set();
-          for (let childPath of info.children) {
-            childInfo = evt.data[childPath];
-            newChildren.add(this._forPath(childPath, childInfo));
-          }
-          resource.setChildren(newChildren);
-        }
-        resource.info.children = null;
-      }
-
-      worker = null;
-      this._refreshDeferred.resolve();
-      this._refreshDeferred = null;
-    };
-    worker.onerror = ex => {
-      console.error(ex);
-      worker = null;
-      this._refreshDeferred.reject(ex);
-      this._refreshDeferred = null;
-    }
-    worker.postMessage({ path: this.rootPath, ignore: IGNORE_REGEX });
-    return this._refreshDeferred.promise;
-  },
-
-  /**
-   * Returns true if the given path would be a child of the store's
-   * root directory.
-   */
-  contains: function(path) {
-    path = OS.Path.normalize(path);
-    let thisPath = OS.Path.split(this.rootPath);
-    let thatPath = OS.Path.split(path)
-
-    if (!(thisPath.absolute && thatPath.absolute)) {
-      throw new Error("Contains only works with absolute paths.");
-    }
-
-    if (thisPath.winDrive && (thisPath.winDrive != thatPath.winDrive)) {
-      return false;
-    }
-
-    if (thatPath.components.length <= thisPath.components.length) {
-      return false;
-    }
-
-    for (let i = 0; i < thisPath.components.length; i++) {
-      if (thisPath.components[i] != thatPath.components[i]) {
-        return false;
-      }
-    }
-    return true;
-  }
-});
-exports.LocalStore = LocalStore;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/stores/moz.build
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- 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(
-    'base.js',
-    'local.js',
-    'resource.js',
-)
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/stores/resource.js
+++ /dev/null
@@ -1,398 +0,0 @@
-/* -*- 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 { Cc, Ci, Cu } = require("chrome");
-const { TextEncoder, TextDecoder } = require("sdk/io/buffer");
-const { Class } = require("sdk/core/heritage");
-const { EventTarget } = require("sdk/event/target");
-const { emit } = require("sdk/event/core");
-const URL = require("sdk/url");
-const promise = require("promise");
-const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
-const { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
-const mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
-const { Task } = require("devtools/shared/task");
-
-const gDecoder = new TextDecoder();
-const gEncoder = new TextEncoder();
-
-/**
- * A Resource is a single file-like object that can be respresented
- * as a file for ProjectEditor.
- *
- * The Resource class is not exported, and should not be instantiated
- * Instead, you should use the FileResource class that extends it.
- *
- * This object emits the following events:
- *   - "children-changed": When a child has been added or removed.
- *                         See setChildren.
- *   - "deleted": When the resource has been deleted.
- */
-var Resource = Class({
-  extends: EventTarget,
-
-  refresh: function () { return promise.resolve(this); },
-  destroy: function () { },
-  delete: function () { },
-
-  setURI: function (uri) {
-    if (typeof (uri) === "string") {
-      uri = URL.URL(uri);
-    }
-    this.uri = uri;
-  },
-
-  /**
-   * Is there more than 1 child Resource?
-   */
-  get hasChildren() { return this.children && this.children.size > 0; },
-
-  /**
-   * Is this Resource the root (top level for the store)?
-   */
-  get isRoot() {
-    return !this.parent;
-  },
-
-  /**
-   * Sorted array of children for display
-   */
-  get childrenSorted() {
-    if (!this.hasChildren) {
-      return [];
-    }
-
-    return [...this.children].sort((a, b)=> {
-      // Put directories above files.
-      if (a.isDir !== b.isDir) {
-        return b.isDir;
-      }
-      return a.basename.toLowerCase() > b.basename.toLowerCase();
-    });
-  },
-
-  /**
-   * Set the children set of this Resource, and notify of any
-   * additions / removals that happened in the change.
-   */
-  setChildren: function (newChildren) {
-    let oldChildren = this.children || new Set();
-    let change = false;
-
-    for (let child of oldChildren) {
-      if (!newChildren.has(child)) {
-        change = true;
-        child.parent = null;
-        this.store.notifyRemove(child);
-      }
-    }
-
-    for (let child of newChildren) {
-      if (!oldChildren.has(child)) {
-        change = true;
-        child.parent = this;
-        this.store.notifyAdd(child);
-      }
-    }
-
-    this.children = newChildren;
-    if (change) {
-      emit(this, "children-changed", this);
-    }
-  },
-
-  /**
-   * Add a resource to children set and notify of the change.
-   *
-   * @param Resource resource
-   */
-  addChild: function (resource) {
-    this.children = this.children || new Set();
-
-    resource.parent = this;
-    this.children.add(resource);
-    this.store.notifyAdd(resource);
-    emit(this, "children-changed", this);
-    return resource;
-  },
-
-  /**
-   * Checks if current object has child with specific name.
-   *
-   * @param string name
-   */
-  hasChild: function (name) {
-    for (let child of this.children) {
-      if (child.basename === name) {
-        return true;
-      }
-    }
-    return false;
-  },
-
-  /**
-   * Remove a resource to children set and notify of the change.
-   *
-   * @param Resource resource
-   */
-  removeChild: function (resource) {
-    resource.parent = null;
-    this.children.remove(resource);
-    this.store.notifyRemove(resource);
-    emit(this, "children-changed", this);
-    return resource;
-  },
-
-  /**
-   * Return a set with children, children of children, etc -
-   * gathered recursively.
-   *
-   * @returns Set<Resource>
-   */
-  allDescendants: function () {
-    let set = new Set();
-
-    function addChildren(item) {
-      if (!item.children) {
-        return;
-      }
-
-      for (let child of item.children) {
-        set.add(child);
-      }
-    }
-
-    addChildren(this);
-    for (let item of set) {
-      addChildren(item);
-    }
-
-    return set;
-  },
-});
-
-/**
- * A FileResource is an implementation of Resource for a File System
- * backing.  This is exported, and should be used instead of Resource.
- */
-var FileResource = Class({
-  extends: Resource,
-
-  /**
-   * @param Store store
-   * @param String path
-   * @param FileInfo info
-   *        https://developer.mozilla.org/en-US/docs/JavaScript_OS.File/OS.File.Info
-   */
-  initialize: function (store, path, info) {
-    this.store = store;
-    this.path = path;
-
-    this.setURI(URL.URL(URL.fromFilename(path)));
-    this._lastReadModification = undefined;
-
-    this.info = info;
-    this.parent = null;
-  },
-
-  toString: function () {
-    return "[FileResource:" + this.path + "]";
-  },
-
-  destroy: function () {
-    if (this._refreshDeferred) {
-      this._refreshDeferred.reject();
-    }
-    this._refreshDeferred = null;
-  },
-
-  /**
-   * Fetch and cache information about this particular file.
-   * https://developer.mozilla.org/en-US/docs/JavaScript_OS.File/OS.File_for_the_main_thread#OS.File.stat
-   *
-   * @returns Promise
-   *          Resolves once the File.stat has finished.
-   */
-  refresh: function () {
-    if (this._refreshDeferred) {
-      return this._refreshDeferred.promise;
-    }
-    this._refreshDeferred = promise.defer();
-    OS.File.stat(this.path).then(info => {
-      this.info = info;
-      if (this._refreshDeferred) {
-        this._refreshDeferred.resolve(this);
-        this._refreshDeferred = null;
-      }
-    });
-    return this._refreshDeferred.promise;
-  },
-
-  /**
-   * Return the trailing name component of this Resource
-   */
-  get basename() {
-    return this.path.replace(/\/+$/, "").replace(/\\/g, "/").replace(/.*\//, "");
-  },
-
-  /**
-   * A string to be used when displaying this Resource in views
-   */
-  get displayName() {
-    return this.basename + (this.isDir ? "/" : "");
-  },
-
-  /**
-   * Is this FileResource a directory?  Rather than checking children
-   * here, we use this.info.  So this could return a false negative
-   * if there was no info passed in on constructor and the first
-   * refresh hasn't yet finished.
-   */
-  get isDir() {
-    if (!this.info) { return false; }
-    return this.info.isDir && !this.info.isSymLink;
-  },
-
-  /**
-   * Read the file as a string asynchronously.
-   *
-   * @returns Promise
-   *          Resolves with the text of the file.
-   */
-  load: function () {
-    return OS.File.read(this.path).then(bytes => {
-      return gDecoder.decode(bytes);
-    });
-  },
-
-  /**
-   * Delete the file from the filesystem
-   *
-   * @returns Promise
-   *          Resolves when the file is deleted
-   */
-  delete: function () {
-    emit(this, "deleted", this);
-    if (this.isDir) {
-      return OS.File.removeDir(this.path);
-    } else {
-      return OS.File.remove(this.path);
-    }
-  },
-
-  /**
-   * Add a text file as a child of this FileResource.
-   * This instance must be a directory.
-   *
-   * @param string name
-   *               The filename (path will be generated based on this.path).
-   *        string initial
-   *               The content to write to the new file.
-   * @returns Promise
-   *          Resolves with the new FileResource once it has
-   *          been written to disk.
-   *          Rejected if this is not a directory.
-   */
-  createChild: function (name, initial = "") {
-    if (!this.isDir) {
-      return promise.reject(new Error("Cannot add child to a regular file"));
-    }
-
-    let newPath = OS.Path.join(this.path, name);
-
-    let buffer = initial ? gEncoder.encode(initial) : "";
-    return OS.File.writeAtomic(newPath, buffer, {
-      noOverwrite: true
-    }).then(() => {
-      return this.store.refresh();
-    }).then(() => {
-      let resource = this.store.resources.get(newPath);
-      if (!resource) {
-        throw new Error("Error creating " + newPath);
-      }
-      return resource;
-    });
-  },
-
-  /**
-   * Rename the file from the filesystem
-   *
-   * @returns Promise
-   *          Resolves with the renamed FileResource.
-   */
-  rename: function (oldName, newName) {
-    let oldPath = OS.Path.join(this.path, oldName);
-    let newPath = OS.Path.join(this.path, newName);
-
-    return OS.File.move(oldPath, newPath).then(() => {
-      return this.store.refresh();
-    }).then(() => {
-      let resource = this.store.resources.get(newPath);
-      if (!resource) {
-        throw new Error("Error creating " + newPath);
-      }
-      return resource;
-    });
-  },
-
-  /**
-   * Write a string to this file.
-   *
-   * @param string content
-   * @returns Promise
-   *          Resolves once it has been written to disk.
-   *          Rejected if there is an error
-   */
-  save: Task.async(function* (content) {
-    // XXX: writeAtomic was losing permissions after saving on OSX
-    // return OS.File.writeAtomic(this.path, buffer, { tmpPath: this.path + ".tmp" });
-    let buffer = gEncoder.encode(content);
-    let path = this.path;
-    let file = yield OS.File.open(path, {truncate: true});
-    yield file.write(buffer);
-    yield file.close();
-  }),
-
-  /**
-   * Attempts to get the content type from the file.
-   */
-  get contentType() {
-    if (this._contentType) {
-      return this._contentType;
-    }
-    if (this.isDir) {
-      return "x-directory/normal";
-    }
-    try {
-      this._contentType = mimeService.getTypeFromFile(new FileUtils.File(this.path));
-    } catch (ex) {
-      if (ex.name !== "NS_ERROR_NOT_AVAILABLE" &&
-          ex.name !== "NS_ERROR_FAILURE") {
-        console.error(ex, this.path);
-      }
-      this._contentType = null;
-    }
-    return this._contentType;
-  },
-
-  /**
-   * A string used when determining the type of Editor to open for this.
-   * See editors.js -> EditorTypeForResource.
-   */
-  get contentCategory() {
-    const NetworkHelper = require("devtools/shared/webconsole/network-helper");
-    let category = NetworkHelper.mimeCategoryMap[this.contentType];
-    // Special treatment for manifest.webapp.
-    if (!category && this.basename === "manifest.webapp") {
-      return "json";
-    }
-    return category || "txt";
-  }
-});
-
-exports.FileResource = FileResource;
deleted file mode 100644
--- a/devtools/client/projecteditor/lib/tree.js
+++ /dev/null
@@ -1,593 +0,0 @@
-/* -*- 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/. */
-
-const { Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
-const { emit } = require("sdk/event/core");
-const { EventTarget } = require("sdk/event/target");
-const { merge } = require("sdk/util/object");
-const promise = require("promise");
-const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
-const { on, forget } = require("devtools/client/projecteditor/lib/helpers/event");
-const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
-
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-
-/**
- * ResourceContainer is used as the view of a single Resource in
- * the tree.  It is not exported.
- */
-var ResourceContainer = Class({
-  /**
-   * @param ProjectTreeView tree
-   * @param Resource resource
-   */
-  initialize: function (tree, resource) {
-    this.tree = tree;
-    this.resource = resource;
-    this.elt = null;
-    this.expander = null;
-    this.children = null;
-
-    let doc = tree.doc;
-
-    this.elt = doc.createElementNS(HTML_NS, "li");
-    this.elt.classList.add("child");
-
-    this.line = doc.createElementNS(HTML_NS, "div");
-    this.line.classList.add("child");
-    this.line.classList.add("entry");
-    this.line.setAttribute("theme", "dark");
-    this.line.setAttribute("tabindex", "0");
-
-    this.elt.appendChild(this.line);
-
-    this.highlighter = doc.createElementNS(HTML_NS, "span");
-    this.highlighter.classList.add("highlighter");
-    this.line.appendChild(this.highlighter);
-
-    this.expander = doc.createElementNS(HTML_NS, "span");
-    this.expander.className = "arrow expander";
-    this.expander.setAttribute("open", "");
-    this.line.appendChild(this.expander);
-
-    this.label = doc.createElementNS(HTML_NS, "span");
-    this.label.className = "file-label";
-    this.line.appendChild(this.label);
-
-    this.line.addEventListener("contextmenu", (ev) => {
-      this.select();
-      this.openContextMenu(ev);
-    });
-
-    this.children = doc.createElementNS(HTML_NS, "ul");
-    this.children.classList.add("children");
-
-    this.elt.appendChild(this.children);
-
-    this.line.addEventListener("click", (evt) => {
-      this.select();
-      this.toggleExpansion();
-      evt.stopPropagation();
-    });
-    this.expander.addEventListener("click", (evt) => {
-      this.toggleExpansion();
-      this.select();
-      evt.stopPropagation();
-    }, true);
-
-    if (!this.resource.isRoot) {
-      this.expanded = false;
-    }
-    this.update();
-  },
-
-  toggleExpansion: function () {
-    if (!this.resource.isRoot) {
-      this.expanded = !this.expanded;
-    } else {
-      this.expanded = true;
-    }
-  },
-
-  destroy: function () {
-    this.elt.remove();
-    this.expander.remove();
-    this.highlighter.remove();
-    this.children.remove();
-    this.label.remove();
-    this.elt = this.expander = this.highlighter = this.children = this.label = null;
-  },
-
-  /**
-   * Open the context menu when right clicking on the view.
-   * XXX: We could pass this to plugins to allow themselves
-   * to be register/remove items from the context menu if needed.
-   *
-   * @param Event e
-   */
-  openContextMenu: function (ev) {
-    ev.preventDefault();
-    let popup = this.tree.options.contextMenuPopup;
-    popup.openPopupAtScreen(ev.screenX, ev.screenY, true);
-  },
-
-  /**
-   * Update the view based on the current state of the Resource.
-   */
-  update: function () {
-    let visible = this.tree.options.resourceVisible ?
-      this.tree.options.resourceVisible(this.resource) :
-      true;
-
-    this.elt.hidden = !visible;
-
-    this.tree.options.resourceFormatter(this.resource, this.label);
-
-    this.expander.style.visibility = this.resource.hasChildren ? "visible" : "hidden";
-
-  },
-
-  /**
-   * Select this view in the ProjectTreeView.
-   */
-  select: function () {
-    this.tree.selectContainer(this);
-  },
-
-  /**
-   * @returns Boolean
-   *          Is this view currently selected
-   */
-  get selected() {
-    return this.line.classList.contains("selected");
-  },
-
-  /**
-   * Set the selected state in the UI.
-   */
-  set selected(v) {
-    if (v) {
-      this.line.classList.add("selected");
-    } else {
-      this.line.classList.remove("selected");
-    }
-  },
-
-  /**
-   * @returns Boolean
-   *          Are any children visible.
-   */
-  get expanded() {
-    return !this.elt.classList.contains("tree-collapsed");
-  },
-
-  /**
-   * Set the visiblity state of children.
-   */
-  set expanded(v) {
-    if (v) {
-      this.elt.classList.remove("tree-collapsed");
-      this.expander.setAttribute("open", "");
-    } else {
-      this.expander.removeAttribute("open");
-      this.elt.classList.add("tree-collapsed");
-    }
-  }
-});
-
-/**
- * TreeView is a view managing a list of children.
- * It is not to be instantiated directly - only extended.
- * Use ProjectTreeView instead.
- */
-var TreeView = Class({
-  extends: EventTarget,
-
-  /**
-   * @param Document document
-   * @param Object options
-   *               - contextMenuPopup: a <menupopup> element
-   *               - resourceFormatter: a function(Resource, DOMNode)
-   *                 that renders the resource into the view
-   *               - resourceVisible: a function(Resource) -> Boolean
-   *                 that determines if the resource should show up.
-   */
-  initialize: function (doc, options) {
-    this.doc = doc;
-    this.options = merge({
-      resourceFormatter: function (resource, elt) {
-        elt.textContent = resource.toString();
-      }
-    }, options);
-    this.models = new Set();
-    this.roots = new Set();
-    this._containers = new Map();
-    this.elt = this.doc.createElementNS(HTML_NS, "div");
-    this.elt.tree = this;
-    this.elt.className = "sources-tree";
-    this.elt.setAttribute("with-arrows", "true");
-    this.elt.setAttribute("theme", "dark");
-    this.elt.setAttribute("flex", "1");
-
-    this.children = this.doc.createElementNS(HTML_NS, "ul");
-    this.elt.appendChild(this.children);
-
-    this.resourceChildrenChanged = this.resourceChildrenChanged.bind(this);
-    this.removeResource = this.removeResource.bind(this);
-    this.updateResource = this.updateResource.bind(this);
-  },
-
-  destroy: function () {
-    this._destroyed = true;
-    this.elt.remove();
-  },
-
-  /**
-   * Helper function to create DOM elements for promptNew and promptEdit
-   */
-  createInputContainer: function () {
-    let inputholder = this.doc.createElementNS(HTML_NS, "div");
-    inputholder.className = "child entry";
-
-    let expander = this.doc.createElementNS(HTML_NS, "span");
-    expander.className = "arrow expander";
-    expander.setAttribute("invisible", "");
-    inputholder.appendChild(expander);
-
-    let placeholder = this.doc.createElementNS(HTML_NS, "div");
-    placeholder.className = "child";
-    inputholder.appendChild(placeholder);
-
-    return {inputholder, placeholder};
-  },
-
-  /**
-   * Prompt the user to create a new file in the tree.
-   *
-   * @param string initial
-   *               The suggested starting file name
-   * @param Resource parent
-   * @param Resource sibling
-   *                 Which resource to put this next to.  If not set,
-   *                 it will be put in front of all other children.
-   *
-   * @returns Promise
-   *          Resolves once the prompt has been successful,
-   *          Rejected if it is cancelled
-   */
-  promptNew: function (initial, parent, sibling = null) {
-    let deferred = promise.defer();
-
-    let parentContainer = this._containers.get(parent);
-    let item = this.doc.createElement("li");
-    item.className = "child";
-
-    let {inputholder, placeholder} = this.createInputContainer();
-    item.appendChild(inputholder);
-
-    let children = parentContainer.children;
-    sibling = sibling ? this._containers.get(sibling).elt : null;
-    parentContainer.children.insertBefore(item, sibling ? sibling.nextSibling : children.firstChild);
-
-    new InplaceEditor({
-      element: placeholder,
-      initial: initial,
-      preserveTextStyles: true,
-      start: editor => {
-        editor.input.select();
-      },
-      done: function (val, commit) {
-        if (commit) {
-          deferred.resolve(val);
-        } else {
-          deferred.reject(val);
-        }
-        parentContainer.line.focus();
-      },
-      destroy: () => {
-        item.remove();
-      },
-    });
-
-    return deferred.promise;
-  },
-
-  /**
-   * Prompt the user to rename file in the tree.
-   *
-   * @param string initial
-   *               The suggested starting file name
-   * @param resource
-   *
-   * @returns Promise
-   *          Resolves once the prompt has been successful,
-   *          Rejected if it is cancelled
-   */
-  promptEdit: function (initial, resource) {
-    let deferred = promise.defer();
-    let item = this._containers.get(resource).elt;
-    let originalText = item.childNodes[0];
-
-    let {inputholder, placeholder} = this.createInputContainer();
-    item.insertBefore(inputholder, originalText);
-
-    item.removeChild(originalText);
-
-    new InplaceEditor({
-      element: placeholder,
-      initial: initial,
-      preserveTextStyles: true,
-      start: editor => {
-        editor.input.select();
-      },
-      done: function (val, commit) {
-        if (val === initial) {
-          item.insertBefore(originalText, inputholder);
-        }
-
-        item.removeChild(inputholder);
-
-        if (commit) {
-          deferred.resolve(val);
-        } else {
-          deferred.reject(val);
-        }
-      },
-    });
-
-    return deferred.promise;
-  },
-
-  /**
-   * Add a new Store into the TreeView
-   *
-   * @param Store model
-   */
-  addModel: function (model) {
-    if (this.models.has(model)) {
-      // Requesting to add a model that already exists
-      return;
-    }
-    this.models.add(model);
-    let placeholder = this.doc.createElementNS(HTML_NS, "li");
-    placeholder.style.display = "none";
-    this.children.appendChild(placeholder);
-    this.roots.add(model.root);
-    model.root.refresh().then(root => {
-      if (this._destroyed || !this.models.has(model)) {
-        // model may have been removed during the initial refresh.
-        // In this case, do not import the resource or add to DOM, just leave it be.
-        return;
-      }
-      let container = this.importResource(root);
-      container.line.classList.add("entry-group-title");
-      container.line.setAttribute("theme", "dark");
-      this.selectContainer(container);
-
-      this.children.insertBefore(container.elt, placeholder);
-      this.children.removeChild(placeholder);
-    });
-  },
-
-  /**
-   * Remove a Store from the TreeView
-   *
-   * @param Store model
-   */
-  removeModel: function (model) {
-    this.models.delete(model);
-    this.removeResource(model.root);
-  },
-
-
-  /**
-   * Get the ResourceContainer.  Used for testing the view.
-   *
-   * @param Resource resource
-   * @returns ResourceContainer
-   */
-  getViewContainer: function (resource) {
-    return this._containers.get(resource);
-  },
-
-  /**
-   * Select a ResourceContainer in the tree.
-   *
-   * @param ResourceContainer container
-   */
-  selectContainer: function (container) {
-    if (this.selectedContainer === container) {
-      return;
-    }
-    if (this.selectedContainer) {
-      this.selectedContainer.selected = false;
-    }
-    this.selectedContainer = container;
-    container.selected = true;
-    emit(this, "selection", container.resource);
-  },
-
-  /**
-   * Select a Resource in the tree.
-   *
-   * @param Resource resource
-   */
-  selectResource: function (resource) {
-    this.selectContainer(this._containers.get(resource));
-  },
-
-  /**
-   * Get the currently selected Resource
-   *
-   * @param Resource resource
-   */
-  getSelectedResource: function () {
-    return this.selectedContainer.resource;
-  },
-
-  /**
-   * Insert a Resource into the view.
-   * Makes a new ResourceContainer if needed
-   *
-   * @param Resource resource
-   */
-  importResource: function (resource) {
-    if (!resource) {
-      return null;
-    }
-
-    if (this._containers.has(resource)) {
-      return this._containers.get(resource);
-    }
-    var container = ResourceContainer(this, resource);
-    this._containers.set(resource, container);
-    this._updateChildren(container);
-
-    on(this, resource, "children-changed", this.resourceChildrenChanged);
-    on(this, resource, "label-change", this.updateResource);
-    on(this, resource, "deleted", this.removeResource);
-
-    return container;
-  },
-
-  /**
-   * Remove a Resource (including children) from the view.
-   *
-   * @param Resource resource
-   */
-  removeResource: function (resource) {
-    let toRemove = resource.allDescendants();
-    toRemove.add(resource);
-    for (let remove of toRemove) {
-      this._removeResource(remove);
-    }
-  },
-
-  /**
-   * Remove an individual Resource (but not children) from the view.
-   *
-   * @param Resource resource
-   */
-  _removeResource: function (resource) {
-    forget(this, resource);
-    if (this._containers.get(resource)) {
-      this._containers.get(resource).destroy();
-      this._containers.delete(resource);
-    }
-    emit(this, "resource-removed", resource);
-  },
-
-  /**
-   * Listener for when a resource has new children.
-   * This can happen as files are being loaded in from FileSystem, for example.
-   *
-   * @param Resource resource
-   */
-  resourceChildrenChanged: function (resource) {
-    this.updateResource(resource);
-    this._updateChildren(this._containers.get(resource));
-  },
-
-  /**
-   * Listener for when a label in the view has been updated.
-   * For example, the 'dirty' plugin marks changed files with an '*'
-   * next to the filename, and notifies with this event.
-   *
-   * @param Resource resource
-   */
-  updateResource: function (resource) {
-    let container = this._containers.get(resource);
-    container.update();
-  },
-
-  /**
-   * Build necessary ResourceContainers for a Resource and its
-   * children, then append them into the view.
-   *
-   * @param ResourceContainer container
-   */
-  _updateChildren: function (container) {
-    let resource = container.resource;
-    let fragment = this.doc.createDocumentFragment();
-    if (resource.children) {
-      for (let child of resource.childrenSorted) {
-        let childContainer = this.importResource(child);
-        fragment.appendChild(childContainer.elt);
-      }
-    }
-
-    while (container.children.firstChild) {
-      container.children.firstChild.remove();
-    }
-
-    container.children.appendChild(fragment);
-  },
-});
-
-/**
- * ProjectTreeView is the implementation of TreeView
- * that is exported.  This is the class that is to be used
- * directly.
- */
-var ProjectTreeView = Class({
-  extends: TreeView,
-
-  /**
-   * See TreeView.initialize
-   *
-   * @param Document document
-   * @param Object options
-   */
-  initialize: function (document, options) {
-    TreeView.prototype.initialize.apply(this, arguments);
-  },
-
-  destroy: function () {
-    this.forgetProject();
-    TreeView.prototype.destroy.apply(this, arguments);
-  },
-
-  /**
-   * Remove current project and empty the tree
-   */
-  forgetProject: function () {
-    if (this.project) {
-      forget(this, this.project);
-      for (let store of this.project.allStores()) {
-        this.removeModel(store);
-      }
-    }
-  },
-
-  /**
-   * Show a project in the tree
-   *
-   * @param Project project
-   *        The project to render into a tree
-   */
-  setProject: function (project) {
-    this.forgetProject();
-    this.project = project;
-    if (this.project) {
-      on(this, project, "store-added", this.addModel.bind(this));
-      on(this, project, "store-removed", this.removeModel.bind(this));
-      on(this, project, "project-saved", this.refresh.bind(this));
-      this.refresh();
-    }
-  },
-
-  /**
-   * Refresh the tree with all of the current project stores
-   */
-  refresh: function () {
-    for (let store of this.project.allStores()) {
-      this.addModel(store);
-    }
-  }
-});
-
-exports.ProjectTreeView = ProjectTreeView;
deleted file mode 100644
--- a/devtools/client/projecteditor/moz.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- 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/.
-
-DIRS += ['lib']
-
-BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
deleted file mode 100644
--- a/devtools/client/projecteditor/test/.eslintrc.js
+++ /dev/null
@@ -1,6 +0,0 @@
-"use strict";
-
-module.exports = {
-  // Extend from the shared list of defined globals for mochitests.
-  "extends": "../../../.eslintrc.mochitests.js"
-};
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser.ini
+++ /dev/null
@@ -1,32 +0,0 @@
-[DEFAULT]
-tags = devtools
-subsuite = devtools
-support-files =
-  head.js
-  helper_homepage.html
-  helper_edits.js
-  projecteditor-test.xul
-
-[browser_projecteditor_app_options.js]
-[browser_projecteditor_confirm_unsaved.js]
-[browser_projecteditor_contextmenu_01.js]
-skip-if = asan # Bug 1083140
-[browser_projecteditor_contextmenu_02.js]
-skip-if = true # Bug 1173950
-[browser_projecteditor_delete_file.js]
-skip-if = e10s # Frequent failures in e10s - Bug 1020027
-[browser_projecteditor_rename_file_01.js]
-[browser_projecteditor_rename_file_02.js]
-[browser_projecteditor_editing_01.js]
-[browser_projecteditor_editors_image.js]
-[browser_projecteditor_external_change.js]
-[browser_projecteditor_immediate_destroy.js]
-[browser_projecteditor_init.js]
-[browser_projecteditor_menubar_01.js]
-[browser_projecteditor_menubar_02.js]
-skip-if = true # Bug 1173950
-[browser_projecteditor_new_file.js]
-[browser_projecteditor_saveall.js]
-[browser_projecteditor_stores.js]
-[browser_projecteditor_tree_selection_01.js]
-[browser_projecteditor_tree_selection_02.js]
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_app_options.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test that options can be changed without resetting the whole
-// editor.
-add_task(function* () {
-
-  let TEMP_PATH = buildTempDirectoryStructure();
-  let projecteditor = yield addProjectEditorTab();
-
-  let resourceBeenAdded = promise.defer();
-  projecteditor.project.once("resource-added", () => {
-    info("A resource has been added");
-    resourceBeenAdded.resolve();
-  });
-
-  info("About to set project to: " + TEMP_PATH);
-  yield projecteditor.setProjectToAppPath(TEMP_PATH, {
-    name: "Test",
-    iconUrl: "chrome://devtools/skin/images/tool-options.svg",
-    projectOverviewURL: SAMPLE_WEBAPP_URL
-  });
-
-  info("Making sure a resource has been added before continuing");
-  yield resourceBeenAdded.promise;
-
-  info("From now on, if a resource is added it should fail");
-  projecteditor.project.on("resource-added", failIfResourceAdded);
-
-  info("Getting ahold and validating the project header DOM");
-  let header = projecteditor.document.querySelector(".entry-group-title");
-  let image = header.querySelector(".project-image");
-  let nameLabel = header.querySelector(".project-name-label");
-  let statusElement = header.querySelector(".project-status");
-  is(statusElement.getAttribute("status"), "unknown", "The status starts out as unknown.");
-  is(nameLabel.textContent, "Test", "The name label has been set correctly");
-  is(image.getAttribute("src"), "chrome://devtools/skin/images/tool-options.svg", "The icon has been set correctly");
-
-  info("About to set project with new options.");
-  yield projecteditor.setProjectToAppPath(TEMP_PATH, {
-    name: "Test2",
-    iconUrl: "chrome://devtools/skin/images/tool-inspector.svg",
-    projectOverviewURL: SAMPLE_WEBAPP_URL,
-    validationStatus: "error"
-  });
-
-  info("Getting ahold of and validating the project header DOM");
-  is(statusElement.getAttribute("status"), "error", "The status has been set correctly.");
-  is(nameLabel.textContent, "Test2", "The name label has been set correctly");
-  is(image.getAttribute("src"), "chrome://devtools/skin/images/tool-inspector.svg", "The icon has been set correctly");
-
-  info("About to set project with new options.");
-  yield projecteditor.setProjectToAppPath(TEMP_PATH, {
-    name: "Test3",
-    iconUrl: "chrome://devtools/skin/images/tool-webconsole.svg",
-    projectOverviewURL: SAMPLE_WEBAPP_URL,
-    validationStatus: "warning"
-  });
-
-  info("Getting ahold of and validating the project header DOM");
-  is(statusElement.getAttribute("status"), "warning", "The status has been set correctly.");
-  is(nameLabel.textContent, "Test3", "The name label has been set correctly");
-  is(image.getAttribute("src"), "chrome://devtools/skin/images/tool-webconsole.svg", "The icon has been set correctly");
-
-  info("About to set project with new options.");
-  yield projecteditor.setProjectToAppPath(TEMP_PATH, {
-    name: "Test4",
-    iconUrl: "chrome://devtools/skin/images/tool-debugger.svg",
-    projectOverviewURL: SAMPLE_WEBAPP_URL,
-    validationStatus: "valid"
-  });
-
-  info("Getting ahold of and validating the project header DOM");
-  is(statusElement.getAttribute("status"), "valid", "The status has been set correctly.");
-  is(nameLabel.textContent, "Test4", "The name label has been set correctly");
-  is(image.getAttribute("src"), "chrome://devtools/skin/images/tool-debugger.svg", "The icon has been set correctly");
-
-  info("Test finished, cleaning up");
-  projecteditor.project.off("resource-added", failIfResourceAdded);
-});
-
-function failIfResourceAdded() {
-  ok(false, "A resource has been added, but it shouldn't have been");
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_confirm_unsaved.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-loadHelperScript("helper_edits.js");
-
-// Test that a prompt shows up when requested if a file is unsaved.
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  ok(true, "ProjectEditor has loaded");
-
-  let resources = projecteditor.project.allResources();
-  yield selectFile(projecteditor, resources[2]);
-  let editor = projecteditor.currentEditor;
-  let originalText = editor.editor.getText();
-
-  ok(!projecteditor.hasUnsavedResources, "There are no unsaved resources");
-  ok(projecteditor.confirmUnsaved(), "When there are no unsaved changes, confirmUnsaved() is true");
-  editor.editor.setText("bar");
-  editor.editor.setText(originalText);
-  ok(!projecteditor.hasUnsavedResources, "There are no unsaved resources");
-  ok(projecteditor.confirmUnsaved(), "When an editor has changed but is still the original text, confirmUnsaved() is true");
-
-  editor.editor.setText("bar");
-
-  checkConfirmYes(projecteditor);
-  checkConfirmNo(projecteditor);
-});
-
-function checkConfirmYes(projecteditor, container) {
-  function confirmYes(aSubject) {
-    info("confirm dialog observed as expected, going to click OK");
-    Services.obs.removeObserver(confirmYes, "common-dialog-loaded");
-    Services.obs.removeObserver(confirmYes, "tabmodal-dialog-loaded");
-    aSubject.Dialog.ui.button0.click();
-  }
-
-  Services.obs.addObserver(confirmYes, "common-dialog-loaded");
-  Services.obs.addObserver(confirmYes, "tabmodal-dialog-loaded");
-
-  ok(projecteditor.hasUnsavedResources, "There are unsaved resources");
-  ok(projecteditor.confirmUnsaved(), "When there are unsaved changes, clicking OK makes confirmUnsaved() true");
-}
-
-function checkConfirmNo(projecteditor, container) {
-  function confirmNo(aSubject) {
-    info("confirm dialog observed as expected, going to click cancel");
-    Services.obs.removeObserver(confirmNo, "common-dialog-loaded");
-    Services.obs.removeObserver(confirmNo, "tabmodal-dialog-loaded");
-    aSubject.Dialog.ui.button1.click();
-  }
-
-  Services.obs.addObserver(confirmNo, "common-dialog-loaded");
-  Services.obs.addObserver(confirmNo, "tabmodal-dialog-loaded");
-
-  ok(projecteditor.hasUnsavedResources, "There are unsaved resources");
-  ok(!projecteditor.confirmUnsaved(), "When there are unsaved changes, clicking cancel makes confirmUnsaved() false");
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_contextmenu_01.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test that context menus append to the correct document.
-
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory({
-    menubar: false
-  });
-  ok(projecteditor, "ProjectEditor has loaded");
-
-  let contextMenuPopup = projecteditor.document.querySelector("#context-menu-popup");
-  let textEditorContextMenuPopup = projecteditor.document.querySelector("#texteditor-context-popup");
-  ok(contextMenuPopup, "The menu has loaded in the projecteditor document");
-  ok(textEditorContextMenuPopup, "The menu has loaded in the projecteditor document");
-
-  let projecteditor2 = yield addProjectEditorTabForTempDirectory();
-  contextMenuPopup = projecteditor2.document.getElementById("context-menu-popup");
-  textEditorContextMenuPopup = projecteditor2.document.getElementById("texteditor-context-popup");
-  ok(!contextMenuPopup, "The menu has NOT loaded in the projecteditor document");
-  ok(!textEditorContextMenuPopup, "The menu has NOT loaded in the projecteditor document");
-  ok(content.document.querySelector("#context-menu-popup"), "The menu has loaded in the specified element");
-  ok(content.document.querySelector("#texteditor-context-popup"), "The menu has loaded in the specified element");
-});
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_contextmenu_02.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-loadHelperScript("helper_edits.js");
-
-// Test context menu enabled / disabled state in editor
-
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  ok(projecteditor, "ProjectEditor has loaded");
-
-  let {textEditorContextMenuPopup} = projecteditor;
-
-  // Update menu items for a clean slate, so previous tests cannot
-  // affect paste, and possibly other side effects
-  projecteditor._updateMenuItems();
-
-  let cmdDelete = textEditorContextMenuPopup.querySelector("[command=cmd_delete]");
-  let cmdSelectAll = textEditorContextMenuPopup.querySelector("[command=cmd_selectAll]");
-  let cmdCut = textEditorContextMenuPopup.querySelector("[command=cmd_cut]");
-  let cmdCopy = textEditorContextMenuPopup.querySelector("[command=cmd_copy]");
-  let cmdPaste = textEditorContextMenuPopup.querySelector("[command=cmd_paste]");
-
-  info("Opening resource");
-  let resource = projecteditor.project.allResources()[2];
-  yield selectFile(projecteditor, resource);
-  let editor = projecteditor.currentEditor;
-  editor.editor.focus();
-
-  info("Opening context menu on resource");
-  yield openContextMenuForEditor(editor, textEditorContextMenuPopup);
-
-  is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
-  is(cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
-  is(cmdCut.getAttribute("disabled"), "true", "cmdCut is disabled");
-  is(cmdCopy.getAttribute("disabled"), "true", "cmdCopy is disabled");
-  is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
-
-  info("Setting a selection and repening context menu on resource");
-  yield closeContextMenuForEditor(editor, textEditorContextMenuPopup);
-  editor.editor.setSelection({line: 0, ch: 0}, {line: 0, ch: 2});
-  yield openContextMenuForEditor(editor, textEditorContextMenuPopup);
-
-  is(cmdDelete.getAttribute("disabled"), "", "cmdDelete is enabled");
-  is(cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
-  is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
-  is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
-  is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
-});
-
-function* openContextMenuForEditor(editor, contextMenu) {
-  let editorDoc = editor.editor.container.contentDocument;
-  let shown = onPopupShow(contextMenu);
-  EventUtils.synthesizeMouse(editorDoc.body, 2, 2,
-    {type: "contextmenu", button: 2}, editorDoc.defaultView);
-  yield shown;
-}
-function* closeContextMenuForEditor(editor, contextMenu) {
-  let editorDoc = editor.editor.container.contentDocument;
-  let hidden = onPopupHidden(contextMenu);
-  contextMenu.hidePopup();
-  yield hidden;
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_delete_file.js
+++ /dev/null
@@ -1,85 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test tree selection functionality
-
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  ok(true, "ProjectEditor has loaded");
-
-  let root = [...projecteditor.project.allStores()][0].root;
-  is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
-  for (let child of root.children) {
-    yield deleteWithContextMenu(projecteditor, projecteditor.projectTree.getViewContainer(child));
-  }
-
-  yield testDeleteOnRoot(projecteditor, projecteditor.projectTree.getViewContainer(root));
-});
-
-
-function openContextMenuOn(node) {
-  EventUtils.synthesizeMouseAtCenter(
-    node,
-    {button: 2, type: "contextmenu"},
-    node.ownerDocument.defaultView
-  );
-}
-
-function* testDeleteOnRoot(projecteditor, container) {
-  let popup = projecteditor.contextMenuPopup;
-  let oncePopupShown = onPopupShow(popup);
-  openContextMenuOn(container.label);
-  yield oncePopupShown;
-
-  let deleteCommand = popup.querySelector("[command=cmd-delete]");
-  ok(deleteCommand, "Delete command exists in popup");
-  is(deleteCommand.getAttribute("hidden"), "true", "Delete command is hidden");
-}
-
-function deleteWithContextMenu(projecteditor, container) {
-  let defer = promise.defer();
-
-  let popup = projecteditor.contextMenuPopup;
-  let resource = container.resource;
-  info("Going to attempt deletion for: " + resource.path);
-
-  onPopupShow(popup).then(function () {
-    let deleteCommand = popup.querySelector("[command=cmd-delete]");
-    ok(deleteCommand, "Delete command exists in popup");
-    is(deleteCommand.getAttribute("hidden"), "", "Delete command is visible");
-    is(deleteCommand.getAttribute("disabled"), "", "Delete command is enabled");
-
-    function onConfirmShown(aSubject) {
-      info("confirm dialog observed as expected");
-      Services.obs.removeObserver(onConfirmShown, "common-dialog-loaded");
-      Services.obs.removeObserver(onConfirmShown, "tabmodal-dialog-loaded");
-
-      projecteditor.project.on("refresh-complete", function refreshComplete() {
-        projecteditor.project.off("refresh-complete", refreshComplete);
-        OS.File.stat(resource.path).then(() => {
-          ok(false, "The file was not deleted");
-          defer.resolve();
-        }, (ex) => {
-          ok(ex instanceof OS.File.Error && ex.becauseNoSuchFile, "OS.File.stat promise was rejected because the file is gone");
-          defer.resolve();
-        });
-      });
-
-      // Click the 'OK' button
-      aSubject.Dialog.ui.button0.click();
-    }
-
-    Services.obs.addObserver(onConfirmShown, "common-dialog-loaded");
-    Services.obs.addObserver(onConfirmShown, "tabmodal-dialog-loaded");
-
-    deleteCommand.click();
-    popup.hidePopup();
-  });
-
-  openContextMenuOn(container.label);
-
-  return defer.promise;
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_editing_01.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-//
-// Whitelisting this test.
-// As part of bug 1077403, the leaking uncaught rejection should be fixed.
-//
-thisTestLeaksUncaughtRejectionsAndShouldBeFixed("destroy");
-
-loadHelperScript("helper_edits.js");
-
-// Test ProjectEditor basic functionality
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  let TEMP_PATH = projecteditor.project.allPaths()[0];
-
-  is(getTempFile("").path, TEMP_PATH, "Temp path is set correctly.");
-
-  ok(projecteditor.currentEditor, "There is an editor for projecteditor");
-  let resources = projecteditor.project.allResources();
-
-  for (let data of helperEditData) {
-    info("Processing " + data.path);
-    let resource = resources.filter(r=>r.basename === data.basename)[0];
-    yield selectFile(projecteditor, resource);
-    yield testEditFile(projecteditor, getTempFile(data.path).path, data.newContent);
-  }
-});
-
-function* testEditFile(projecteditor, filePath, newData) {
-  info("Testing file editing for: " + filePath);
-
-  let initialData = yield getFileData(filePath);
-  let editor = projecteditor.currentEditor;
-  let resource = projecteditor.resourceFor(editor);
-  let viewContainer = projecteditor.projectTree.getViewContainer(resource);
-  let originalTreeLabel = viewContainer.label.textContent;
-
-  is(resource.path, filePath, "Resource path is set correctly");
-  is(editor.editor.getText(), initialData, "Editor is loaded with correct file contents");
-
-  info("Setting text in the editor and doing checks before saving");
-
-  editor.editor.undo();
-  editor.editor.undo();
-  is(editor.editor.getText(), initialData, "Editor is still loaded with correct contents after undo");
-
-  editor.editor.setText(newData);
-  is(editor.editor.getText(), newData, "Editor has been filled with new data");
-  is(viewContainer.label.textContent, "*" + originalTreeLabel, "Label is marked as changed");
-
-  info("Saving the editor and checking to make sure the file gets saved on disk");
-
-  editor.save(resource);
-
-  let savedResource = yield onceEditorSave(projecteditor);
-
-  is(viewContainer.label.textContent, originalTreeLabel, "Label is unmarked as changed");
-  is(savedResource.path, filePath, "The saved resouce path matches the original file path");
-  is(savedResource, resource, "The saved resource is the same as the original resource");
-
-  let savedData = yield getFileData(filePath);
-  is(savedData, newData, "Data has been correctly saved to disk");
-
-  info("Finished checking saving for " + filePath);
-
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_editors_image.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-//
-// Whitelisting this test.
-// As part of bug 1077403, the leaking uncaught rejection should be fixed.
-//
-thisTestLeaksUncaughtRejectionsAndShouldBeFixed("destroy");
-
-loadHelperScript("helper_edits.js");
-
-// Test ProjectEditor image editor functionality
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  let TEMP_PATH = projecteditor.project.allPaths()[0];
-
-  is(getTempFile("").path, TEMP_PATH, "Temp path is set correctly.");
-
-  ok(projecteditor.currentEditor, "There is an editor for projecteditor");
-  let resources = projecteditor.project.allResources();
-
-  let helperImageData = [
-    {
-      basename: "16x16.png",
-      path: "img/icons/16x16.png"
-    },
-    {
-      basename: "32x32.png",
-      path: "img/icons/32x32.png"
-    },
-    {
-      basename: "128x128.png",
-      path: "img/icons/128x128.png"
-    },
-  ];
-
-  for (let data of helperImageData) {
-    info("Processing " + data.path);
-    let resource = resources.filter(r=>r.basename === data.basename)[0];
-    yield selectFile(projecteditor, resource);
-    yield testEditor(projecteditor, getTempFile(data.path).path);
-  }
-});
-
-function* testEditor(projecteditor, filePath) {
-  info("Testing file editing for: " + filePath);
-
-  let editor = projecteditor.currentEditor;
-  let resource = projecteditor.resourceFor(editor);
-
-  is(resource.path, filePath, "Resource path is set correctly");
-
-  let images = editor.elt.querySelectorAll("image");
-  is(images.length, 1, "There is one image inside the editor");
-  is(images[0], editor.image, "The image property is set correctly with the DOM");
-  is(editor.image.getAttribute("src"), resource.uri, "The image has the resource URL");
-
-  info("Selecting another resource, then reselecting this one");
-  projecteditor.projectTree.selectResource(resource.store.root);
-  yield onceEditorActivated(projecteditor);
-  projecteditor.projectTree.selectResource(resource);
-  yield onceEditorActivated(projecteditor);
-
-  editor = projecteditor.currentEditor;
-  images = editor.elt.querySelectorAll("image");
-  ok(images.length, 1, "There is one image inside the editor");
-  is(images[0], editor.image, "The image property is set correctly with the DOM");
-  is(editor.image.getAttribute("src"), resource.uri, "The image has the resource URL");
-
-  info("Finished checking saving for " + filePath);
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_external_change.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-loadHelperScript("helper_edits.js");
-
-// Test ProjectEditor reaction to external changes (made outside of the)
-// editor.
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  let TEMP_PATH = projecteditor.project.allPaths()[0];
-
-  is(getTempFile("").path, TEMP_PATH, "Temp path is set correctly.");
-
-  ok(projecteditor.currentEditor, "There is an editor for projecteditor");
-  let resources = projecteditor.project.allResources();
-
-  for (let data of helperEditData) {
-    info("Processing " + data.path);
-    let resource = resources.filter(r=>r.basename === data.basename)[0];
-    yield selectFile(projecteditor, resource);
-    yield testChangeFileExternally(projecteditor, getTempFile(data.path).path, data.newContent);
-    yield testChangeUnsavedFileExternally(projecteditor, getTempFile(data.path).path, data.newContent + "[changed]");
-  }
-});
-
-function* testChangeUnsavedFileExternally(projecteditor, filePath, newData) {
-  info("Testing file external changes for: " + filePath);
-
-  let editor = projecteditor.currentEditor;
-  let resource = projecteditor.resourceFor(editor);
-  let initialData = yield getFileData(filePath);
-
-  is(resource.path, filePath, "Resource path is set correctly");
-  is(editor.editor.getText(), initialData, "Editor is loaded with correct file contents");
-
-  info("Editing but not saving file in project editor");
-  ok(editor.isClean(), "Editor is clean");
-  editor.editor.setText("foobar");
-  ok(!editor.isClean(), "Editor is dirty");
-
-  info("Editor has been selected, writing to file externally");
-  yield writeToFile(resource.path, newData);
-
-  info("Selecting another resource, then reselecting this one");
-  projecteditor.projectTree.selectResource(resource.store.root);
-  yield onceEditorActivated(projecteditor);
-  projecteditor.projectTree.selectResource(resource);
-  yield onceEditorActivated(projecteditor);
-
-  editor = projecteditor.currentEditor;
-  info("Checking to make sure the editor is now populated correctly");
-  is(editor.editor.getText(), "foobar", "Editor has not been updated with new file contents");
-
-  info("Finished checking saving for " + filePath);
-}
-
-function* testChangeFileExternally(projecteditor, filePath, newData) {
-  info("Testing file external changes for: " + filePath);
-
-  let editor = projecteditor.currentEditor;
-  let resource = projecteditor.resourceFor(editor);
-  let initialData = yield getFileData(filePath);
-
-  is(resource.path, filePath, "Resource path is set correctly");
-  is(editor.editor.getText(), initialData, "Editor is loaded with correct file contents");
-
-  info("Editor has been selected, writing to file externally");
-  yield writeToFile(resource.path, newData);
-
-  info("Selecting another resource, then reselecting this one");
-  projecteditor.projectTree.selectResource(resource.store.root);
-  yield onceEditorActivated(projecteditor);
-  projecteditor.projectTree.selectResource(resource);
-  yield onceEditorActivated(projecteditor);
-
-  editor = projecteditor.currentEditor;
-  info("Checking to make sure the editor is now populated correctly");
-  is(editor.editor.getText(), newData, "Editor has been updated with correct file contents");
-
-  info("Finished checking saving for " + filePath);
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_immediate_destroy.js
+++ /dev/null
@@ -1,93 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-//
-// Whitelisting this test.
-// As part of bug 1077403, the leaking uncaught rejection should be fixed.
-//
-thisTestLeaksUncaughtRejectionsAndShouldBeFixed("destroy");
-thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.window is null");
-
-// Test that projecteditor can be destroyed in various states of loading
-// without causing any leaks or exceptions.
-
-add_task(function* () {
-
-  info("Testing tab closure when projecteditor is in various states");
-  let loaderUrl = "chrome://mochitests/content/browser/devtools/client/projecteditor/test/projecteditor-test.xul";
-
-  yield addTab(loaderUrl).then(() => {
-    let iframe = content.document.getElementById("projecteditor-iframe");
-    ok(iframe, "Tab has placeholder iframe for projecteditor");
-
-    info("Closing the tab without doing anything");
-    gBrowser.removeCurrentTab();
-  });
-
-  yield addTab(loaderUrl).then(() => {
-    let iframe = content.document.getElementById("projecteditor-iframe");
-    ok(iframe, "Tab has placeholder iframe for projecteditor");
-
-    let projecteditor = ProjectEditor.ProjectEditor();
-    ok(projecteditor, "ProjectEditor has been initialized");
-
-    info("Closing the tab before attempting to load");
-    gBrowser.removeCurrentTab();
-  });
-
-  yield addTab(loaderUrl).then(() => {
-    let iframe = content.document.getElementById("projecteditor-iframe");
-    ok(iframe, "Tab has placeholder iframe for projecteditor");
-
-    let projecteditor = ProjectEditor.ProjectEditor();
-    ok(projecteditor, "ProjectEditor has been initialized");
-
-    projecteditor.load(iframe);
-
-    info("Closing the tab after a load is requested, but before load is finished");
-    gBrowser.removeCurrentTab();
-  });
-
-  yield addTab(loaderUrl).then(() => {
-    let iframe = content.document.getElementById("projecteditor-iframe");
-    ok(iframe, "Tab has placeholder iframe for projecteditor");
-
-    let projecteditor = ProjectEditor.ProjectEditor();
-    ok(projecteditor, "ProjectEditor has been initialized");
-
-    return projecteditor.load(iframe).then(() => {
-      info("Closing the tab after a load has been requested and finished");
-      gBrowser.removeCurrentTab();
-    });
-  });
-
-  yield addTab(loaderUrl).then(() => {
-    let iframe = content.document.getElementById("projecteditor-iframe");
-    ok(iframe, "Tab has placeholder iframe for projecteditor");
-
-    let projecteditor = ProjectEditor.ProjectEditor(iframe);
-    ok(projecteditor, "ProjectEditor has been initialized");
-
-    let loadedDone = promise.defer();
-    projecteditor.loaded.then(() => {
-      ok(false, "Loaded has finished after destroy() has been called");
-      loadedDone.resolve();
-    }, () => {
-      ok(true, "Loaded has been rejected after destroy() has been called");
-      loadedDone.resolve();
-    });
-
-    projecteditor.destroy();
-
-    return loadedDone.promise.then(() => {
-      gBrowser.removeCurrentTab();
-    });
-  });
-
-  finish();
-});
-
-
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_init.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test that projecteditor can be initialized.
-
-function test() {
-  info("Initializing projecteditor");
-  addProjectEditorTab().then((projecteditor) => {
-    ok(projecteditor, "Load callback has been called");
-    ok(projecteditor.shells, "ProjectEditor has shells");
-    ok(projecteditor.project, "ProjectEditor has a project");
-    finish();
-  });
-}
-
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_menubar_01.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test that menu bar appends to the correct document.
-
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory({
-    menubar: false
-  });
-  ok(projecteditor, "ProjectEditor has loaded");
-
-  let fileMenu = projecteditor.document.getElementById("file-menu");
-  let editMenu = projecteditor.document.getElementById("edit-menu");
-  ok(fileMenu, "The menu has loaded in the projecteditor document");
-  ok(editMenu, "The menu has loaded in the projecteditor document");
-
-  let projecteditor2 = yield addProjectEditorTabForTempDirectory();
-  let menubar = projecteditor2.menubar;
-  fileMenu = projecteditor2.document.getElementById("file-menu");
-  editMenu = projecteditor2.document.getElementById("edit-menu");
-  ok(!fileMenu, "The menu has NOT loaded in the projecteditor document");
-  ok(!editMenu, "The menu has NOT loaded in the projecteditor document");
-  ok(content.document.querySelector("#file-menu"), "The menu has loaded in the specified element");
-  ok(content.document.querySelector("#edit-menu"), "The menu has loaded in the specified element");
-});
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_menubar_02.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-loadHelperScript("helper_edits.js");
-
-// Test menu bar enabled / disabled state.
-
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  let menubar = projecteditor.menubar;
-
-  // Update menu items for a clean slate, so previous tests cannot
-  // affect paste, and possibly other side effects
-  projecteditor._updateMenuItems();
-
-  // let projecteditor = yield addProjectEditorTabForTempDirectory();
-  ok(projecteditor, "ProjectEditor has loaded");
-
-  let fileMenu = menubar.querySelector("#file-menu");
-  let editMenu = menubar.querySelector("#edit-menu");
-  ok(fileMenu, "The menu has loaded in the projecteditor document");
-  ok(editMenu, "The menu has loaded in the projecteditor document");
-
-  let cmdNew = fileMenu.querySelector("[command=cmd-new]");
-  let cmdSave = fileMenu.querySelector("[command=cmd-save]");
-  let cmdSaveas = fileMenu.querySelector("[command=cmd-saveas]");
-
-  let cmdUndo = editMenu.querySelector("[command=cmd_undo]");
-  let cmdRedo = editMenu.querySelector("[command=cmd_redo]");
-  let cmdCut = editMenu.querySelector("[command=cmd_cut]");
-  let cmdCopy = editMenu.querySelector("[command=cmd_copy]");
-  let cmdPaste = editMenu.querySelector("[command=cmd_paste]");
-
-  info("Checking initial state of menus");
-  yield openAndCloseMenu(fileMenu);
-  yield openAndCloseMenu(editMenu);
-
-  is(cmdNew.getAttribute("disabled"), "", "File menu item is enabled");
-  is(cmdSave.getAttribute("disabled"), "true", "File menu item is disabled");
-  is(cmdSaveas.getAttribute("disabled"), "true", "File menu item is disabled");
-
-  is(cmdUndo.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdRedo.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdCut.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdCopy.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdPaste.getAttribute("disabled"), "true", "Edit menu item is disabled");
-
-  projecteditor.menuEnabled = false;
-
-  info("Checking with menuEnabled = false");
-  yield openAndCloseMenu(fileMenu);
-  yield openAndCloseMenu(editMenu);
-
-  is(cmdNew.getAttribute("disabled"), "true", "File menu item is disabled");
-  is(cmdSave.getAttribute("disabled"), "true", "File menu item is disabled");
-  is(cmdSaveas.getAttribute("disabled"), "true", "File menu item is disabled");
-
-  is(cmdUndo.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdRedo.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdCut.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdCopy.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdPaste.getAttribute("disabled"), "true", "Edit menu item is disabled");
-
-  info("Checking with menuEnabled=true");
-  projecteditor.menuEnabled = true;
-
-  yield openAndCloseMenu(fileMenu);
-  yield openAndCloseMenu(editMenu);
-
-  is(cmdNew.getAttribute("disabled"), "", "File menu item is enabled");
-  is(cmdSave.getAttribute("disabled"), "true", "File menu item is disabled");
-  is(cmdSaveas.getAttribute("disabled"), "true", "File menu item is disabled");
-
-  is(cmdUndo.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdRedo.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdCut.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdCopy.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdPaste.getAttribute("disabled"), "true", "Edit menu item is disabled");
-
-  info("Checking with resource selected");
-  let resource = projecteditor.project.allResources()[2];
-  yield selectFile(projecteditor, resource);
-  let editor = projecteditor.currentEditor;
-
-  let onChange = promise.defer();
-
-  projecteditor.on("onEditorChange", () => {
-    info("onEditorChange has been detected");
-    onChange.resolve();
-  });
-  editor.editor.focus();
-  EventUtils.synthesizeKey("f", { }, projecteditor.window);
-
-  yield onChange;
-  yield openAndCloseMenu(fileMenu);
-  yield openAndCloseMenu(editMenu);
-
-  is(cmdNew.getAttribute("disabled"), "", "File menu item is enabled");
-  is(cmdSave.getAttribute("disabled"), "", "File menu item is enabled");
-  is(cmdSaveas.getAttribute("disabled"), "", "File menu item is enabled");
-
-  // Use editor.canUndo() to see if this is failing - the menu disabled property
-  // should be in sync with this because of isCommandEnabled in editor.js.
-  info('cmdUndo.getAttribute("disabled") is: "' + cmdUndo.getAttribute("disabled") + '"');
-  ok(editor.editor.canUndo(), "Edit menu item is enabled");
-
-  is(cmdRedo.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdCut.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdCopy.getAttribute("disabled"), "true", "Edit menu item is disabled");
-  is(cmdPaste.getAttribute("disabled"), "", "Edit menu item is enabled");
-});
-
-function* openAndCloseMenu(menu) {
-  let shown = onPopupShow(menu);
-  EventUtils.synthesizeMouseAtCenter(menu, {}, menu.ownerDocument.defaultView);
-  yield shown;
-  let hidden = onPopupHidden(menu);
-  EventUtils.synthesizeMouseAtCenter(menu, {}, menu.ownerDocument.defaultView);
-  yield hidden;
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_new_file.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test tree selection functionality
-
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  ok(projecteditor, "ProjectEditor has loaded");
-
-});
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_rename_file_01.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test file rename functionality
-
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  ok(true, "ProjectEditor has loaded");
-
-  let root = [...projecteditor.project.allStores()][0].root;
-  is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
-  for (let child of root.children) {
-    yield renameWithContextMenu(projecteditor,
-      projecteditor.projectTree.getViewContainer(child), ".renamed");
-  }
-});
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_rename_file_02.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test file rename functionality with non ascii characters
-
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  ok(true, "ProjectEditor has loaded");
-
-  let root = [...projecteditor.project.allStores()][0].root;
-  is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
-
-  let childrenList = [];
-  for (let child of root.children) {
-    yield renameWithContextMenu(projecteditor,
-      projecteditor.projectTree.getViewContainer(child), ".ren\u0061\u0308med");
-    childrenList.push(child.basename + ".ren\u0061\u0308med");
-  }
-  for (let child of root.children) {
-    is(childrenList.indexOf(child.basename) == -1, false,
-        "Failed to update tree with non-ascii character");
-  }
-});
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_saveall.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-//
-// Whitelisting this test.
-// As part of bug 1077403, the leaking uncaught rejection should be fixed.
-//
-thisTestLeaksUncaughtRejectionsAndShouldBeFixed("destroy");
-
-loadHelperScript("helper_edits.js");
-
-// Test ProjectEditor basic functionality
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  let TEMP_PATH = projecteditor.project.allPaths()[0];
-
-  is(getTempFile("").path, TEMP_PATH, "Temp path is set correctly.");
-
-  ok(projecteditor.currentEditor, "There is an editor for projecteditor");
-  let resources = projecteditor.project.allResources();
-
-  for (let data of helperEditData) {
-    info("Processing " + data.path);
-    let resource = resources.filter(r=>r.basename === data.basename)[0];
-    yield selectFile(projecteditor, resource);
-    yield editFile(projecteditor, getTempFile(data.path).path, data.newContent);
-  }
-
-  info("Saving all resources");
-  ok(projecteditor.hasUnsavedResources, "hasUnsavedResources");
-  yield projecteditor.saveAllFiles();
-  ok(!projecteditor.hasUnsavedResources, "!hasUnsavedResources");
-  for (let data of helperEditData) {
-    let filePath = getTempFile(data.path).path;
-    info("Asserting that data at " + filePath + " has been saved");
-    let resource = resources.filter(r=>r.basename === data.basename)[0];
-    yield selectFile(projecteditor, resource);
-    let editor = projecteditor.currentEditor;
-    let savedData = yield getFileData(filePath);
-    is(savedData, data.newContent, "Data has been correctly saved to disk");
-  }
-});
-
-function* editFile(projecteditor, filePath, newData) {
-  info("Testing file editing for: " + filePath);
-
-  let initialData = yield getFileData(filePath);
-  let editor = projecteditor.currentEditor;
-  let resource = projecteditor.resourceFor(editor);
-  let viewContainer = projecteditor.projectTree.getViewContainer(resource);
-  let originalTreeLabel = viewContainer.label.textContent;
-
-  is(resource.path, filePath, "Resource path is set correctly");
-  is(editor.editor.getText(), initialData, "Editor is loaded with correct file contents");
-
-  info("Setting text in the editor");
-
-  editor.editor.setText(newData);
-  is(editor.editor.getText(), newData, "Editor has been filled with new data");
-  is(viewContainer.label.textContent, "*" + originalTreeLabel, "Label is marked as changed");
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_stores.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test ProjectEditor basic functionality
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  let TEMP_PATH = projecteditor.project.allPaths()[0];
-  is(getTempFile("").path, TEMP_PATH, "Temp path is set correctly.");
-
-  is(projecteditor.project.allPaths().length, 1, "1 path is set");
-  projecteditor.project.removeAllStores();
-  is(projecteditor.project.allPaths().length, 0, "No paths are remaining");
-});
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_tree_selection_01.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-// Test tree selection functionality
-
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  let TEMP_PATH = projecteditor.project.allPaths()[0];
-
-  is(getTempFile("").path, TEMP_PATH, "Temp path is set correctly.");
-
-  ok(projecteditor.currentEditor, "There is an editor for projecteditor");
-  let resources = projecteditor.project.allResources();
-
-  is(
-    resources.map(r=>r.basename).join("|"),
-    TEMP_FOLDER_NAME + "|css|styles.css|data|img|icons|128x128.png|16x16.png|32x32.png|vector.svg|fake.png|js|script.js|index.html|LICENSE|README.md",
-    "Resources came through in proper order"
-  );
-
-  for (let i = 0; i < resources.length; i++) {
-    yield selectFileFirstLoad(projecteditor, resources[i]);
-  }
-  for (let i = 0; i < resources.length; i++) {
-    yield selectFileSubsequentLoad(projecteditor, resources[i]);
-  }
-  for (let i = 0; i < resources.length; i++) {
-    yield selectFileSubsequentLoad(projecteditor, resources[i]);
-  }
-});
-
-function* selectFileFirstLoad(projecteditor, resource) {
-  ok(resource && resource.path, "A valid resource has been passed in for selection " + (resource && resource.path));
-  projecteditor.projectTree.selectResource(resource);
-  let container = projecteditor.projectTree.getViewContainer(resource);
-
-  if (resource.isRoot) {
-    ok(container.expanded, "The root directory is expanded by default.");
-    container.line.click();
-    ok(container.expanded, "Clicking on the line does not toggles expansion.");
-    return;
-  }
-  if (resource.isDir) {
-    ok(!container.expanded, "A directory is not expanded by default.");
-    container.line.click();
-    ok(container.expanded, "Clicking on the line toggles expansion.");
-    container.line.click();
-    ok(!container.expanded, "Clicking on the line toggles expansion.");
-    return;
-  }
-
-  let [editorCreated, editorLoaded, editorActivated] = yield promise.all([
-    onceEditorCreated(projecteditor),
-    onceEditorLoad(projecteditor),
-    onceEditorActivated(projecteditor)
-  ]);
-
-  is(editorCreated, projecteditor.currentEditor, "Editor has been created for " + resource.path);
-  is(editorActivated, projecteditor.currentEditor, "Editor has been activated for " + resource.path);
-  is(editorLoaded, projecteditor.currentEditor, "Editor has been loaded for " + resource.path);
-}
-
-function* selectFileSubsequentLoad(projecteditor, resource) {
-  ok(resource && resource.path, "A valid resource has been passed in for selection " + (resource && resource.path));
-  projecteditor.projectTree.selectResource(resource);
-
-  if (resource.isDir) {
-    return;
-  }
-
-  // Make sure text editors are focused immediately when selected.
-  let focusPromise = promise.resolve();
-  if (projecteditor.currentEditor.editor) {
-    focusPromise = onEditorFocus(projecteditor.currentEditor);
-  }
-
-  // Only activated should fire the next time
-  // (may add load() if we begin checking for changes from disk)
-  let [editorActivated] = yield promise.all([
-    onceEditorActivated(projecteditor)
-  ]);
-
-  is(editorActivated, projecteditor.currentEditor, "Editor has been activated for " + resource.path);
-
-  yield focusPromise;
-}
-
-function onEditorFocus(editor) {
-  let def = promise.defer();
-  editor.on("focus", function focus() {
-    editor.off("focus", focus);
-    def.resolve();
-  });
-  return def.promise;
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/browser_projecteditor_tree_selection_02.js
+++ /dev/null
@@ -1,76 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-//
-// Whitelisting this test.
-// As part of bug 1077403, the leaking uncaught rejection should be fixed.
-//
-thisTestLeaksUncaughtRejectionsAndShouldBeFixed("destroy");
-
-// Test that files get reselected in the tree when their editor
-// is focused.  https://bugzilla.mozilla.org/show_bug.cgi?id=1011116.
-
-add_task(function* () {
-  let projecteditor = yield addProjectEditorTabForTempDirectory();
-  let TEMP_PATH = projecteditor.project.allPaths()[0];
-
-  is(getTempFile("").path, TEMP_PATH, "Temp path is set correctly.");
-
-  ok(projecteditor.currentEditor, "There is an editor for projecteditor");
-  let resources = projecteditor.project.allResources();
-
-  is(
-    resources.map(r=>r.basename).join("|"),
-    TEMP_FOLDER_NAME + "|css|styles.css|data|img|icons|128x128.png|16x16.png|32x32.png|vector.svg|fake.png|js|script.js|index.html|LICENSE|README.md",
-    "Resources came through in proper order"
-  );
-
-  for (let i = 0; i < resources.length; i++) {
-    yield selectAndRefocusFile(projecteditor, resources[i]);
-  }
-});
-
-function* selectAndRefocusFile(projecteditor, resource) {
-  ok(resource && resource.path, "A valid resource has been passed in for selection " + (resource && resource.path));
-  projecteditor.projectTree.selectResource(resource);
-
-  if (resource.isDir) {
-    return;
-  }
-
-  let [editorCreated, editorLoaded, editorActivated] = yield promise.all([
-    onceEditorCreated(projecteditor),
-    onceEditorLoad(projecteditor),
-    onceEditorActivated(projecteditor)
-  ]);
-
-  if (projecteditor.currentEditor.editor) {
-    // This is a text editor.  Go ahead and select a directory then refocus
-    // the editor to make sure it is reselected in tree.
-    let treeContainer = projecteditor.projectTree.getViewContainer(getDirectoryInStore(resource));
-    treeContainer.line.click();
-    EventUtils.synthesizeMouseAtCenter(treeContainer.elt, {}, treeContainer.elt.ownerDocument.defaultView);
-    let waitForTreeSelect = onTreeSelection(projecteditor);
-    projecteditor.currentEditor.focus();
-    yield waitForTreeSelect;
-
-    is(projecteditor.projectTree.getSelectedResource(), resource, "The resource gets reselected in the tree");
-  }
-}
-
-// Return a directory to select in the tree.
-function getDirectoryInStore(resource) {
-  return resource.store.root.childrenSorted.filter(r=>r.isDir)[0];
-}
-
-function onTreeSelection(projecteditor) {
-  let def = promise.defer();
-  projecteditor.projectTree.on("selection", function selection() {
-    projecteditor.projectTree.off("focus", selection);
-    def.resolve();
-  });
-  return def.promise;
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/head.js
+++ /dev/null
@@ -1,389 +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/. */
-
-var Cu = Components.utils;
-const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
-const {TargetFactory} = require("devtools/client/framework/target");
-const {console} = Cu.import("resource://gre/modules/Console.jsm", {});
-const promise = require("promise");
-const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
-const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
-const ProjectEditor = require("devtools/client/projecteditor/lib/projecteditor");
-const DevToolsUtils = require("devtools/shared/DevToolsUtils");
-const flags = require("devtools/shared/flags");
-
-const TEST_URL_ROOT = "http://mochi.test:8888/browser/devtools/client/projecteditor/test/";
-const SAMPLE_WEBAPP_URL = TEST_URL_ROOT + "/helper_homepage.html";
-var TEMP_PATH;
-var TEMP_FOLDER_NAME = "ProjectEditor" + (new Date().getTime());
-
-// All test are asynchronous
-waitForExplicitFinish();
-
-// Uncomment this pref to dump all devtools emitted events to the console.
-// Services.prefs.setBoolPref("devtools.dump.emit", true);
-
-// Set the testing flag and reset it when the test ends
-flags.testing = true;
-registerCleanupFunction(() => flags.testing = false);
-
-// Clear preferences that may be set during the course of tests.
-registerCleanupFunction(() => {
-  // Services.prefs.clearUserPref("devtools.dump.emit");
-  TEMP_PATH = null;
-  TEMP_FOLDER_NAME = null;
-});
-
-// Auto close the toolbox and close the test tabs when the test ends
-registerCleanupFunction(() => {
-  try {
-    let target = TargetFactory.forTab(gBrowser.selectedTab);
-    gDevTools.closeToolbox(target);
-  } catch (ex) {
-    dump(ex);
-  }
-  while (gBrowser.tabs.length > 1) {
-    gBrowser.removeCurrentTab();
-  }
-});
-
-/**
- * Add a new test tab in the browser and load the given url.
- * @param {String} url The url to be loaded in the new tab
- * @return a promise that resolves to the tab object when the url is loaded
- */
-function addTab(url) {
-  info("Adding a new tab with URL: '" + url + "'");
-  let def = promise.defer();
-
-  let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, url);
-  BrowserTestUtils.browserLoaded(tab.linkedBrowser).then(function () {
-    info("URL '" + url + "' loading complete");
-    waitForFocus(() => {
-      def.resolve(tab);
-    }, content);
-  });
-
-  return def.promise;
-}
-
-/**
- * Some tests may need to import one or more of the test helper scripts.
- * A test helper script is simply a js file that contains common test code that
- * is either not common-enough to be in head.js, or that is located in a separate
- * directory.
- * The script will be loaded synchronously and in the test's scope.
- * @param {String} filePath The file path, relative to the current directory.
- *                 Examples:
- *                 - "helper_attributes_test_runner.js"
- *                 - "../../../commandline/test/helpers.js"
- */
-function loadHelperScript(filePath) {
-  let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
-  Services.scriptloader.loadSubScript(testDir + "/" + filePath, this);
-}
-
-function addProjectEditorTabForTempDirectory(opts = {}) {
-  try {
-    TEMP_PATH = buildTempDirectoryStructure();
-  } catch (e) {
-    // Bug 1037292 - The test servers sometimes are unable to
-    // write to the temporary directory due to locked files
-    // or access denied errors.  Try again if this failed.
-    info("Project Editor temp directory creation failed.  Trying again.");
-    TEMP_PATH = buildTempDirectoryStructure();
-  }
-  let customOpts = {
-    name: "Test",
-    iconUrl: "chrome://devtools/skin/images/tool-options.svg",
-    projectOverviewURL: SAMPLE_WEBAPP_URL
-  };
-
-  info("Adding a project editor tab for editing at: " + TEMP_PATH);
-  return addProjectEditorTab(opts).then((projecteditor) => {
-    return projecteditor.setProjectToAppPath(TEMP_PATH, customOpts).then(() => {
-      return projecteditor;
-    });
-  });
-}
-
-function addProjectEditorTab(opts = {}) {
-  return addTab("chrome://mochitests/content/browser/devtools/client/projecteditor/test/projecteditor-test.xul").then(() => {
-    let iframe = content.document.getElementById("projecteditor-iframe");
-    if (opts.menubar !== false) {
-      opts.menubar = content.document.querySelector("menubar");
-    }
-    let projecteditor = ProjectEditor.ProjectEditor(iframe, opts);
-
-
-    ok(iframe, "Tab has placeholder iframe for projecteditor");
-    ok(projecteditor, "ProjectEditor has been initialized");
-
-    return projecteditor.loaded.then((projecteditor) => {
-      return projecteditor;
-    });
-  });
-}
-
-/**
- * Build a temporary directory as a workspace for this loader
- * https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O
- */
-function buildTempDirectoryStructure() {
-
-  let dirName = TEMP_FOLDER_NAME;
-  info("Building a temporary directory at " + dirName);
-
-  // First create (and remove) the temp dir to discard any changes
-  let TEMP_DIR = FileUtils.getDir("TmpD", [dirName], true);
-  TEMP_DIR.remove(true);
-
-  // Now rebuild our fake project.
-  TEMP_DIR = FileUtils.getDir("TmpD", [dirName], true);
-
-  FileUtils.getDir("TmpD", [dirName, "css"], true);
-  FileUtils.getDir("TmpD", [dirName, "data"], true);
-  FileUtils.getDir("TmpD", [dirName, "img", "icons"], true);
-  FileUtils.getDir("TmpD", [dirName, "js"], true);
-
-  let htmlFile = FileUtils.getFile("TmpD", [dirName, "index.html"]);
-  htmlFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-  writeToFileSync(htmlFile, [
-    "<!DOCTYPE html>",
-    '<html lang="en">',
-    " <head>",
-    '   <meta charset="utf-8" />',
-    "   <title>ProjectEditor Temp File</title>",
-    '   <link rel="stylesheet" href="style.css" />',
-    " </head>",
-    ' <body id="home">',
-    "   <p>ProjectEditor Temp File</p>",
-    " </body>",
-    "</html>"].join("\n")
-  );
-
-  let readmeFile = FileUtils.getFile("TmpD", [dirName, "README.md"]);
-  readmeFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-  writeToFileSync(readmeFile, [
-    "## Readme"
-  ].join("\n")
-  );
-
-  let licenseFile = FileUtils.getFile("TmpD", [dirName, "LICENSE"]);
-  licenseFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-  writeToFileSync(licenseFile, [
-    "/* 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/. */"
-  ].join("\n")
-  );
-
-  let cssFile = FileUtils.getFile("TmpD", [dirName, "css", "styles.css"]);
-  cssFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-  writeToFileSync(cssFile, [
-    "body {",
-    " background: red;",
-    "}"
-  ].join("\n")
-  );
-
-  FileUtils.getFile("TmpD", [dirName, "js", "script.js"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-
-  FileUtils.getFile("TmpD", [dirName, "img", "fake.png"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-  FileUtils.getFile("TmpD", [dirName, "img", "icons", "16x16.png"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-  FileUtils.getFile("TmpD", [dirName, "img", "icons", "32x32.png"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-  FileUtils.getFile("TmpD", [dirName, "img", "icons", "128x128.png"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-  FileUtils.getFile("TmpD", [dirName, "img", "icons", "vector.svg"]).createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
-
-  return TEMP_DIR.path;
-}
-
-// https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#Writing_to_a_file
-function writeToFile(file, data) {
-  if (typeof file === "string") {
-    file = new FileUtils.File(file);
-  }
-  info("Writing to file: " + file.path + " (exists? " + file.exists() + ")");
-  let defer = promise.defer();
-  var ostream = FileUtils.openSafeFileOutputStream(file);
-
-  var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].
-                  createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
-  converter.charset = "UTF-8";
-  var istream = converter.convertToInputStream(data);
-
-  // The last argument (the callback) is optional.
-  NetUtil.asyncCopy(istream, ostream, function (status) {
-    if (!Components.isSuccessCode(status)) {
-      // Handle error!
-      info("ERROR WRITING TEMP FILE", status);
-    }
-    defer.resolve();
-  });
-  return defer.promise;
-}
-
-// This is used when setting up the test.
-// You should typically use the async version of this, writeToFile.
-// https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#More
-function writeToFileSync(file, data) {
-  // file is nsIFile, data is a string
-  var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
-                 createInstance(Components.interfaces.nsIFileOutputStream);
-
-  // use 0x02 | 0x10 to open file for appending.
-  foStream.init(file, 0x02 | 0x08 | 0x20, 0o666, 0);
-  // write, create, truncate
-  // In a c file operation, we have no need to set file mode with or operation,
-  // directly using "r" or "w" usually.
-
-  // if you are sure there will never ever be any non-ascii text in data you can
-  // also call foStream.write(data, data.length) directly
-  var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
-                  createInstance(Components.interfaces.nsIConverterOutputStream);
-  converter.init(foStream, "UTF-8", 0, 0);
-  converter.writeString(data);
-  converter.close(); // this closes foStream
-}
-
-function getTempFile(path) {
-  let parts = [TEMP_FOLDER_NAME];
-  parts = parts.concat(path.split("/"));
-  return FileUtils.getFile("TmpD", parts);
-}
-
-// https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#Writing_to_a_file
-function* getFileData(file) {
-  if (typeof file === "string") {
-    file = new FileUtils.File(file);
-  }
-  let def = promise.defer();
-
-  NetUtil.asyncFetch({
-    uri: NetUtil.newURI(file),
-    loadUsingSystemPrincipal: true
-  }, function (inputStream, status) {
-    if (!Components.isSuccessCode(status)) {
-      info("ERROR READING TEMP FILE", status);
-    }
-
-    // Detect if an empty file is loaded
-    try {
-      inputStream.available();
-    } catch (e) {
-      def.resolve("");
-      return;
-    }
-
-    var data = NetUtil.readInputStreamToString(inputStream, inputStream.available());
-    def.resolve(data);
-  });
-
-  return def.promise;
-}
-
-/**
- * Rename the resource of the provided container using the context menu.
- *
- * @param {ProjectEditor} projecteditor the current project editor instance
- * @param {Shell} container for the resource to rename
- * @param {String} newName the name to use for renaming the resource
- * @return {Promise} a promise that resolves when the resource has been renamed
- */
-var renameWithContextMenu = Task.async(function* (projecteditor,
-                                                  container, newName) {
-  let popup = projecteditor.contextMenuPopup;
-  let resource = container.resource;
-  info("Going to attempt renaming for: " + resource.path);
-
-  let waitForPopupShow = onPopupShow(popup);
-  openContextMenu(container.label);
-  yield waitForPopupShow;
-
-  let renameCommand = popup.querySelector("[command=cmd-rename]");
-  ok(renameCommand, "Rename command exists in popup");
-  is(renameCommand.getAttribute("hidden"), "", "Rename command is visible");
-  is(renameCommand.getAttribute("disabled"), "", "Rename command is enabled");
-
-  renameCommand.click();
-  popup.hidePopup();
-  let input = container.elt.childNodes[0].childNodes[1];
-  input.value = resource.basename + newName;
-
-  let waitForProjectRefresh = onceProjectRefreshed(projecteditor);
-  EventUtils.synthesizeKey("VK_RETURN", {}, projecteditor.window);
-  yield waitForProjectRefresh;
-
-  try {
-    yield OS.File.stat(resource.path + newName);
-    ok(true, "File is renamed");
-  } catch (e) {
-    ok(false, "Failed to rename file");
-  }
-});
-
-function onceEditorCreated(projecteditor) {
-  let def = promise.defer();
-  projecteditor.once("onEditorCreated", (editor) => {
-    def.resolve(editor);
-  });
-  return def.promise;
-}
-
-function onceEditorLoad(projecteditor) {
-  let def = promise.defer();
-  projecteditor.once("onEditorLoad", (editor) => {
-    def.resolve(editor);
-  });
-  return def.promise;
-}
-
-function onceEditorActivated(projecteditor) {
-  let def = promise.defer();
-  projecteditor.once("onEditorActivated", (editor) => {
-    def.resolve(editor);
-  });
-  return def.promise;
-}
-
-function onceEditorSave(projecteditor) {
-  let def = promise.defer();
-  projecteditor.once("onEditorSave", (editor, resource) => {
-    def.resolve(resource);
-  });
-  return def.promise;
-}
-
-function onceProjectRefreshed(projecteditor) {
-  return new Promise(resolve => {
-    projecteditor.project.on("refresh-complete", function refreshComplete() {
-      projecteditor.project.off("refresh-complete", refreshComplete);
-      resolve();
-    });
-  });
-}
-
-function onPopupShow(menu) {
-  let defer = promise.defer();
-  menu.addEventListener("popupshown", function () {
-    defer.resolve();
-  }, {once: true});
-  return defer.promise;
-}
-
-function onPopupHidden(menu) {
-  let defer = promise.defer();
-  menu.addEventListener("popuphidden", function () {
-    defer.resolve();
-  }, {once: true});
-  return defer.promise;
-}
-
-function openContextMenu(node) {
-  EventUtils.synthesizeMouseAtCenter(
-    node,
-    {button: 2, type: "contextmenu"},
-    node.ownerDocument.defaultView
-  );
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/helper_edits.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/* vim: set ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-var helperEditData = [
-  {
-    basename: "styles.css",
-    path: "css/styles.css",
-    newContent: "body,html { color: orange; }"
-  },
-  {
-    basename: "index.html",
-    path: "index.html",
-    newContent: "<h1>Changed Content Again</h1>"
-  },
-  {
-    basename: "LICENSE",
-    path: "LICENSE",
-    newContent: "My new license"
-  },
-  {
-    basename: "README.md",
-    path: "README.md",
-    newContent: "My awesome readme"
-  },
-  {
-    basename: "script.js",
-    path: "js/script.js",
-    newContent: "alert('hi')"
-  },
-  {
-    basename: "vector.svg",
-    path: "img/icons/vector.svg",
-    newContent: "<svg></svg>"
-  },
-];
-
-function* selectFile(projecteditor, resource) {
-  ok(resource && resource.path, "A valid resource has been passed in for selection " + (resource && resource.path));
-  projecteditor.projectTree.selectResource(resource);
-
-  if (resource.isDir) {
-    return;
-  }
-
-  let [editorActivated] = yield promise.all([
-    onceEditorActivated(projecteditor)
-  ]);
-
-  is(editorActivated, projecteditor.currentEditor, "Editor has been activated for " + resource.path);
-}
deleted file mode 100644
--- a/devtools/client/projecteditor/test/helper_homepage.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<h1>ProjectEditor tests</h1>
\ No newline at end of file
deleted file mode 100644
--- a/devtools/client/projecteditor/test/projecteditor-test.xul
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
-<?xml-stylesheet href="chrome://global/skin/global.css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:html="http://www.w3.org/1999/xhtml">
-
-  <script type="application/javascript" src="chrome://global/content/globalOverlay.js"></script>
-
-  <commandset id="mainCommandSet">
-    <commandset id="editMenuCommands"/>
-  </commandset>
-  <menubar></menubar>
-  <iframe id='projecteditor-iframe' flex="1"></iframe>
-</window>
deleted file mode 100644
--- a/devtools/client/themes/projecteditor/projecteditor.css
+++ /dev/null
@@ -1,184 +0,0 @@
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* 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/. */
-
-.view-project-detail {
-  overflow: auto;
-}
-
-.plugin-hidden {
-  display: none;
-}
-
-.arrow {
-  -moz-appearance: treetwisty;
-  width: 20px;
-  height: 20px;
-}
-
-.arrow[open] {
-  -moz-appearance: treetwistyopen;
-}
-
-.arrow[invisible] {
-  visibility: hidden;
-}
-
-#projecteditor-menubar {
-  display: none;
-}
-
-#projecteditor-toolbar,
-#projecteditor-toolbar-bottom {
-  display: none; /* For now don't show the status bars */
-  min-height: 22px;
-  height: 22px;
-  background: rgb(237, 237, 237);
-}
-
-#sources {
-  overflow: auto;
-}
-
-.sources-tree {
-  overflow:auto;
-  overflow-x: hidden;
-  -moz-user-focus: normal;
-
-  /* Allows this to expand inside of parent xul element, while
-     still supporting child flexbox elements, including ellipses. */
-  -moz-box-flex: 1;
-  display: block;
-}
-
-.sources-tree input {
-  margin: -1px;
-  border: 1px solid gray;
-}
-
-#main-deck .sources-tree {
-  background: rgb(225, 225, 225);
-  min-width: 100px;
-}
-
-.entry {
-  color: #18191A;
-  display: flex;
-  align-items: center;
-}
-
-.entry .file-label {
-  display: flex;
-  flex: 1;
-  align-items: center;
-}
-
-.entry {
-  border: none;
-  box-shadow: none;
-  white-space: nowrap;
-  cursor: pointer;
-}
-
-.entry:hover:not(.entry-group-title):not(.selected) {
-  background: rgba(0, 0, 0, .05);
-}
-
-.entry.selected {
-  background: rgba(56, 117, 215, 1);
-  color: #F5F7FA;
-  outline: none;
-}
-
-.entry-group-title {
-  background: rgba(56, 117, 215, 0.8);
-  color: #F5F7FA;
-  font-weight: bold;
-  font-size: 1.05em;
-  line-height: 35px;
-  padding: 0 10px;
-}
-
-.sources-tree .entry-group-title .expander {
-  display: none;
-}
-
-.entry .expander {
-  width: 16px;
-  padding: 0;
-}
-
-.tree-collapsed .children {
-  display: none;
-}
-
-/* Plugins */
-
-#projecteditor-toolbar textbox {
-  margin: 0;
-}
-
-.projecteditor-basic-display {
-  padding: 0 3px;
-}
-
-/* App Manager */
-.project-name-label {
-  font-weight: bold;
-  padding-left: 10px;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-.project-flex {
-  flex: 1;
-}
-
-.project-image {
-  max-height: 25px;
-  margin-left: -10px;
-}
-
-.project-image,
-.project-status,
-.project-options {
-  flex-shrink: 0;
-}
-
-.project-status {
-  width: 10px;
-  height: 10px;
-  border-radius: 50%;
-  border: solid 1px rgba(255, 255, 255, .5);
-  margin-right: 10px;
-  visibility: hidden;
-}
-
-.project-status[status=valid] {
-  background: #70bf53;
-  visibility: visible;
-}
-
-.project-status[status=warning] {
-  background: #d99b28;
-  visibility: visible;
-}
-
-.project-status[status=error] {
-  background: #ed2655;
-  visibility: visible;
-}
-
-/* Status Bar */
-.projecteditor-file-label {
-  font-weight: bold;
-  padding-left: 29px;
-  padding-right: 10px;
-  flex: 1;
-}
-
-/* Image View */
-.editor-image {
-  padding: 10px;
-}