Bug 1361311 - Remove project editor. r=pbro
authorJ. Ryan Stinnett <jryans@gmail.com>
Wed, 07 Jun 2017 15:30:50 -0500
changeset 411137 3568cd107bf40d1442539d7905de3ca353d70c31
parent 411136 f7248d3f0d8a54c54df4ea2b9819a2e2730ad1a8
child 411138 c17be0697cfba90244e38eccfb98a94ba0901120
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1361311
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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;
-}