Bug 1261019 - Part 2: Remove the webapps devtools actor; r=jryans
authorEhsan Akhgari <ehsan@mozilla.com>
Tue, 27 Sep 2016 09:17:59 -0400
changeset 424972 02d134905768654fc3ebfb7f72ac15584f03c2cc
parent 424971 b9b472734bfa43b19779fb9cb984292956534a94
child 424973 144625d6fafa6bd2870f9d886245e878e591b2e1
push id32314
push userbmo:hiikezoe@mozilla-japan.org
push dateFri, 14 Oct 2016 00:31:54 +0000
reviewersjryans
bugs1261019
milestone52.0a1
Bug 1261019 - Part 2: Remove the webapps devtools actor; r=jryans
devtools/client/webide/test/test_runtime.html
devtools/server/actors/moz.build
devtools/server/actors/webapps.js
devtools/server/docs/actor-registration.md
devtools/server/main.js
devtools/shared/apps/moz.build
devtools/shared/apps/tests/debugger-protocol-helper.js
devtools/shared/apps/tests/mochitest.ini
devtools/shared/apps/tests/redirect.sjs
devtools/shared/apps/tests/test_webapps_actor.html
--- a/devtools/client/webide/test/test_runtime.html
+++ b/devtools/client/webide/test/test_runtime.html
@@ -44,16 +44,24 @@
             DebuggerServer.addBrowserActors();
           }
 
           win = yield openWebIDE();
           let docRuntime = getRuntimeDocument(win);
           let docProject = getProjectDocument(win);
           let winProject = getProjectWindow(win);
 
+          let packagedAppLocation = getTestFilePath("app");
+
+          let onValidated = waitForUpdate(win, "project-validated");
+          let onDetails = waitForUpdate(win, "details");
+          yield winProject.projectList.importPackagedApp(packagedAppLocation);
+          yield onValidated;
+          yield onDetails;
+
           win.AppManager.runtimeList.usb.push({
             connect: function(connection) {
               is(connection, win.AppManager.connection, "connection is valid");
               connection.host = null; // force connectPipe
               connection.connect();
               return promise.resolve();
             },
 
@@ -83,65 +91,58 @@
 
             get name() {
               return "prolongedRuntime";
             }
           });
 
           win.AppManager.update("runtime-list");
 
-          let packagedAppLocation = getTestFilePath("app");
-
-          let onValidated = waitForUpdate(win, "project-validated");
-          let onDetails = waitForUpdate(win, "details");
-          yield winProject.projectList.importPackagedApp(packagedAppLocation);
-          yield onValidated;
-          yield onDetails;
-
           let panelNode = docRuntime.querySelector("#runtime-panel");
           let items = panelNode.querySelectorAll(".runtime-panel-item-usb");
           is(items.length, 3, "Found 3 runtime buttons");
 
           let connectionsChanged = waitForConnectionChange("opened", 2);
           items[0].click();
 
           ok(win.document.querySelector("window").className, "busy", "UI is busy");
           yield win.UI._busyPromise;
 
           yield connectionsChanged;
           is(Object.keys(DebuggerServer._connections).length, 2, "Connected");
 
           yield waitForUpdate(win, "runtime-global-actors");
 
-          ok(isPlayActive(), "play button is enabled 1");
-          ok(!isStopActive(), "stop button is disabled 1");
+          // Play button always disabled now, webapps actor removed
+          ok(!isPlayActive(), "play button is disabled");
+          ok(!isStopActive(), "stop button is disabled");
           let oldProject = win.AppManager.selectedProject;
           win.AppManager.selectedProject = null;
 
           yield nextTick();
 
-          ok(!isPlayActive(), "play button is disabled 2");
-          ok(!isStopActive(), "stop button is disabled 2");
+          ok(!isPlayActive(), "play button is disabled");
+          ok(!isStopActive(), "stop button is disabled");
           win.AppManager._selectedProject = oldProject;
           win.UI.updateCommands();
 
           yield nextTick();
 
-          ok(isPlayActive(), "play button is enabled 3");
-          ok(!isStopActive(), "stop button is disabled 3");
+          ok(!isPlayActive(), "play button is enabled");
+          ok(!isStopActive(), "stop button is disabled");
 
           connectionsChanged = waitForConnectionChange("closed", 2);
           yield win.Cmds.disconnectRuntime();
 
           yield connectionsChanged;
           is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");
 
           ok(win.AppManager.selectedProject, "A project is still selected");
-          ok(!isPlayActive(), "play button is disabled 4");
-          ok(!isStopActive(), "stop button is disabled 4");
+          ok(!isPlayActive(), "play button is disabled");
+          ok(!isStopActive(), "stop button is disabled");
 
           connectionsChanged = waitForConnectionChange("opened", 2);
           docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
 
           yield waitForUpdate(win, "runtime-targets");
 
           yield connectionsChanged;
           is(Object.keys(DebuggerServer._connections).length, 2, "Locally connected");
--- a/devtools/server/actors/moz.build
+++ b/devtools/server/actors/moz.build
@@ -54,16 +54,15 @@ DevToolsModules(
     'settings.js',
     'source.js',
     'storage.js',
     'string.js',
     'styleeditor.js',
     'styles.js',
     'stylesheets.js',
     'timeline.js',
-    'webapps.js',
     'webaudio.js',
     'webbrowser.js',
     'webconsole.js',
     'webextension.js',
     'webgl.js',
     'worker.js',
 )
deleted file mode 100644
--- a/devtools/server/actors/webapps.js
+++ /dev/null
@@ -1,1116 +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";
-
-var { Cu, Cc, Ci } = require("chrome");
-
-var { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
-var { OS } = require("resource://gre/modules/osfile.jsm");
-var { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
-
-var promise = require("promise");
-var DevToolsUtils = require("devtools/shared/DevToolsUtils");
-var { ActorPool } = require("devtools/server/actors/common");
-var { DebuggerServer } = require("devtools/server/main");
-var Services = require("Services");
-var FileReader = require("FileReader");
-
-// Load actor dependencies lazily as this actor require extra environnement
-// preparation to work (like have a profile setup in xpcshell tests)
-loader.lazyRequireGetter(this, "DOMApplicationRegistry", "resource://gre/modules/Webapps.jsm", true);
-loader.lazyRequireGetter(this, "AppsUtils", "resource://gre/modules/AppsUtils.jsm", true);
-loader.lazyRequireGetter(this, "ManifestHelper", "resource://gre/modules/AppsUtils.jsm", true);
-loader.lazyRequireGetter(this, "MessageBroadcaster", "resource://gre/modules/MessageBroadcaster.jsm", true);
-loader.lazyRequireGetter(this, "UserCustomizations", "resource://gre/modules/UserCustomizations.jsm", true);
-
-// Comma separated list of permissions that a sideloaded app can't ask for
-const UNSAFE_PERMISSIONS = Services.prefs.getCharPref("devtools.apps.forbidden-permissions");
-
-var FramesMock = null;
-
-exports.setFramesMock = function (mock) {
-  FramesMock = mock;
-};
-
-DevToolsUtils.defineLazyGetter(this, "Frames", () => {
-  // Offer a way for unit test to provide a mock
-  if (FramesMock) {
-    return FramesMock;
-  }
-  try {
-    return Cu.import("resource://gre/modules/Frames.jsm", {}).Frames;
-  } catch (e) {}
-  return null;
-});
-
-function debug(aMsg) {
-  /*
-  Cc["@mozilla.org/consoleservice;1"]
-    .getService(Ci.nsIConsoleService)
-    .logStringMessage("--*-- WebappsActor : " + aMsg);
-  */
-}
-
-function PackageUploadActor(file) {
-  this._file = file;
-  this._path = file.path;
-}
-
-PackageUploadActor.fromRequest = function (request, file) {
-  if (request.bulk) {
-    return new PackageUploadBulkActor(file);
-  }
-  return new PackageUploadJSONActor(file);
-};
-
-PackageUploadActor.prototype = {
-
-  /**
-   * This method isn't exposed to the client.
-   * It is meant to be called by server code, in order to get
-   * access to the temporary file out of the actor ID.
-   */
-  get filePath() {
-    return this._path;
-  },
-
-  get openedFile() {
-    if (this._openedFile) {
-      return this._openedFile;
-    }
-    this._openedFile = this._openFile();
-    return this._openedFile;
-  },
-
-  /**
-   * This method allows you to delete the temporary file,
-   * when you are done using it.
-   */
-  remove: function () {
-    this._cleanupFile();
-    return {};
-  },
-
-  _cleanupFile: function () {
-    try {
-      this._closeFile();
-    } catch (e) {}
-    try {
-      OS.File.remove(this._path);
-    } catch (e) {}
-  }
-
-};
-
-/**
- * Create a new JSON package upload actor.
- * @param file nsIFile temporary file to write to
- */
-function PackageUploadJSONActor(file) {
-  PackageUploadActor.call(this, file);
-  this._size = 0;
-}
-
-PackageUploadJSONActor.prototype = Object.create(PackageUploadActor.prototype);
-
-PackageUploadJSONActor.prototype.actorPrefix = "packageUploadJSONActor";
-
-PackageUploadJSONActor.prototype._openFile = function () {
-  return OS.File.open(this._path, { write: true, truncate: true });
-};
-
-PackageUploadJSONActor.prototype._closeFile = function () {
-  this.openedFile.then(file => file.close());
-};
-
-/**
- * This method allows you to upload a piece of file.
- * It expects a chunk argument that is the a string to write to the file.
- */
-PackageUploadJSONActor.prototype.chunk = function (aRequest) {
-  let chunk = aRequest.chunk;
-  if (!chunk || chunk.length <= 0) {
-    return {error: "parameterError",
-            message: "Missing or invalid chunk argument"};
-  }
-  // Translate the string used to transfer the chunk over JSON
-  // back to a typed array
-  let data = new Uint8Array(chunk.length);
-  for (let i = 0, l = chunk.length; i < l; i++) {
-    data[i] = chunk.charCodeAt(i);
-  }
-  return this.openedFile
-             .then(file => file.write(data))
-             .then((written) => {
-               this._size += written;
-               return {
-                 written: written,
-                 _size: this._size
-               };
-             });
-};
-
-/**
- * This method needs to be called, when you are done uploading
- * chunks, before trying to access/use the temporary file.
- * Otherwise, the file may be partially written
- * and also be locked.
- */
-PackageUploadJSONActor.prototype.done = function () {
-  this._closeFile();
-  return {};
-};
-
-/**
- * The request types this actor can handle.
- */
-PackageUploadJSONActor.prototype.requestTypes = {
-  "chunk": PackageUploadJSONActor.prototype.chunk,
-  "done": PackageUploadJSONActor.prototype.done,
-  "remove": PackageUploadJSONActor.prototype.remove
-};
-
-/**
- * Create a new bulk package upload actor.
- * @param file nsIFile temporary file to write to
- */
-function PackageUploadBulkActor(file) {
-  PackageUploadActor.call(this, file);
-}
-
-PackageUploadBulkActor.prototype = Object.create(PackageUploadActor.prototype);
-
-PackageUploadBulkActor.prototype.actorPrefix = "packageUploadBulkActor";
-
-PackageUploadBulkActor.prototype._openFile = function () {
-  return FileUtils.openSafeFileOutputStream(this._file);
-};
-
-PackageUploadBulkActor.prototype._closeFile = function () {
-  FileUtils.closeSafeFileOutputStream(this.openedFile);
-};
-
-PackageUploadBulkActor.prototype.stream = function ({copyTo}) {
-  return copyTo(this.openedFile).then(() => {
-    this._closeFile();
-    return {};
-  });
-};
-
-/**
- * The request types this actor can handle.
- */
-PackageUploadBulkActor.prototype.requestTypes = {
-  "stream": PackageUploadBulkActor.prototype.stream,
-  "remove": PackageUploadBulkActor.prototype.remove
-};
-
-/**
- * Creates a WebappsActor. WebappsActor provides remote access to
- * install apps.
- */
-function WebappsActor(aConnection) {
-  debug("init");
-  this.appsChild = {};
-  Cu.import("resource://gre/modules/AppsServiceChild.jsm", this.appsChild);
-
-  // Keep reference of already connected app processes.
-  // values: app frame message manager
-  this._connectedApps = new Set();
-
-  this.conn = aConnection;
-  this._uploads = [];
-  this._actorPool = new ActorPool(this.conn);
-  this.conn.addActorPool(this._actorPool);
-}
-
-WebappsActor.prototype = {
-  actorPrefix: "webapps",
-
-  // For now, launch and close requests are only supported on B2G products
-  // like devices, mulet/simulators, and graphene.
-  // We set that attribute on the prototype in order to allow test
-  // to enable this feature.
-  supportsLaunch: require("devtools/shared/system").constants.MOZ_B2G,
-
-  disconnect: function () {
-    try {
-      this.unwatchApps();
-    } catch (e) {}
-
-    // When we stop using this actor, we should ensure removing all files.
-    for (let upload of this._uploads) {
-      upload.remove();
-    }
-    this._uploads = null;
-
-    this.conn.removeActorPool(this._actorPool);
-    this._actorPool = null;
-    this.conn = null;
-  },
-
-  _registerApp: function wa_actorRegisterApp(aDeferred, aApp, aId, aDir) {
-    debug("registerApp");
-    let reg = DOMApplicationRegistry;
-    let self = this;
-
-    if (aId in reg.webapps && !reg.webapps[aId].sideloaded &&
-        !this._isUnrestrictedAccessAllowed()) {
-      throw new Error("Replacing non-sideloaded apps is not permitted.");
-    }
-
-    // Clean up the deprecated manifest cache if needed.
-    if (aId in reg._manifestCache) {
-      delete reg._manifestCache[aId];
-    }
-
-    aApp.installTime = Date.now();
-    aApp.installState = "installed";
-    aApp.removable = true;
-    aApp.id = aId;
-    aApp.basePath = reg.getWebAppsBasePath();
-    aApp.localId = (aId in reg.webapps) ? reg.webapps[aId].localId
-                                        : reg._nextLocalId();
-    aApp.sideloaded = true;
-    aApp.enabled = true;
-    aApp.blockedStatus = Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
-
-    reg.webapps[aId] = aApp;
-    reg.updatePermissionsForApp(aId);
-
-    reg._readManifests([{ id: aId }]).then((aResult) => {
-      let manifest = aResult[0].manifest;
-      aApp.name = manifest.name;
-      aApp.csp = manifest.csp || "";
-      aApp.role = manifest.role || "";
-      reg.updateAppHandlers(null, manifest, aApp);
-
-      reg._saveApps().then(() => {
-        aApp.manifest = manifest;
-
-        // We need the manifest to set the app kind for hosted apps,
-        // because of appcache.
-        if (aApp.kind == undefined) {
-          aApp.kind = manifest.appcache_path ? reg.kHostedAppcache
-                                             : reg.kHosted;
-        }
-
-        // Needed to evict manifest cache on content side
-        // (has to be dispatched first, otherwise other messages like
-        // Install:Return:OK are going to use old manifest version)
-        MessageBroadcaster.broadcastMessage("Webapps:UpdateState", {
-          app: aApp,
-          manifest: manifest,
-          id: aApp.id
-        });
-        MessageBroadcaster.broadcastMessage("Webapps:FireEvent", {
-          eventType: ["downloadsuccess", "downloadapplied"],
-          manifestURL: aApp.manifestURL
-        });
-        MessageBroadcaster.broadcastMessage("Webapps:AddApp", { id: aId, app: aApp });
-        MessageBroadcaster.broadcastMessage("Webapps:Install:Return:OK", {
-          app: aApp,
-          oid: "foo",
-          requestID: "bar"
-        });
-
-        Services.obs.notifyObservers(null, "webapps-installed",
-          JSON.stringify({ manifestURL: aApp.manifestURL }));
-
-        delete aApp.manifest;
-        aDeferred.resolve({ appId: aId, path: aDir.path });
-
-        // We can't have appcache for packaged apps.
-        if (!aApp.origin.startsWith("app://")) {
-          reg.startOfflineCacheDownload(
-            new ManifestHelper(manifest, aApp.origin, aApp.manifestURL), aApp);
-        }
-      });
-      // Cleanup by removing the temporary directory.
-      if (aDir.exists())
-        aDir.remove(true);
-    });
-  },
-
-  _sendError: function wa_actorSendError(aDeferred, aMsg, aId) {
-    debug("Sending error: " + aMsg);
-    aDeferred.resolve({
-      error: "installationFailed",
-      message: aMsg,
-      appId: aId
-    });
-  },
-
-  _getAppType: function wa_actorGetAppType(aType) {
-    let type = Ci.nsIPrincipal.APP_STATUS_INSTALLED;
-
-    if (aType) {
-      type = aType == "privileged" ? Ci.nsIPrincipal.APP_STATUS_PRIVILEGED
-           : aType == "certified" ? Ci.nsIPrincipal.APP_STATUS_CERTIFIED
-           : Ci.nsIPrincipal.APP_STATUS_INSTALLED;
-    }
-
-    return type;
-  },
-
-  _createTmpPackage: function () {
-    let tmpDir = FileUtils.getDir("TmpD", ["file-upload"], true, false);
-    if (!tmpDir.exists() || !tmpDir.isDirectory()) {
-      return {
-        error: "fileAccessError",
-        message: "Unable to create temporary folder"
-      };
-    }
-    let tmpFile = tmpDir;
-    tmpFile.append("package.zip");
-    tmpFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("0666", 8));
-    if (!tmpFile.exists() || !tmpDir.isFile()) {
-      return {
-        error: "fileAccessError",
-        message: "Unable to create temporary file"
-      };
-    }
-    return tmpFile;
-  },
-
-  uploadPackage: function (request) {
-    debug("uploadPackage");
-
-    let tmpFile = this._createTmpPackage();
-    if ("error" in tmpFile) {
-      return tmpFile;
-    }
-
-    let actor = PackageUploadActor.fromRequest(request, tmpFile);
-    this._actorPool.addActor(actor);
-    this._uploads.push(actor);
-    return { actor: actor.actorID };
-  },
-
-  installHostedApp: function wa_actorInstallHosted(aDir, aId, aReceipts,
-                                                   aManifest, aMetadata) {
-    debug("installHostedApp");
-    let self = this;
-    let deferred = promise.defer();
-
-    function readManifest() {
-      if (aManifest) {
-        return promise.resolve(aManifest);
-      } else {
-        let manFile = OS.Path.join(aDir.path, "manifest.webapp");
-        return AppsUtils.loadJSONAsync(manFile);
-      }
-    }
-    function writeManifest(resolution) {
-      // Move manifest.webapp to the destination directory.
-      // The destination directory for this app.
-      let installDir = DOMApplicationRegistry._getAppDir(aId);
-      if (aManifest) {
-        let manFile = OS.Path.join(installDir.path, "manifest.webapp");
-        return DOMApplicationRegistry._writeFile(manFile, JSON.stringify(aManifest)).then(() => {
-          return resolution;
-        });
-      } else {
-        let manFile = aDir.clone();
-        manFile.append("manifest.webapp");
-        manFile.moveTo(installDir, "manifest.webapp");
-      }
-      return promise.resolve(resolution);
-    }
-    function readMetadata(aAppType) {
-      if (aMetadata) {
-        return { metadata: aMetadata, appType: aAppType };
-      }
-      // Read the origin and manifest url from metadata.json
-      let metaFile = OS.Path.join(aDir.path, "metadata.json");
-      return AppsUtils.loadJSONAsync(metaFile).then((aMetadata) => {
-        if (!aMetadata) {
-          throw ("Error parsing metadata.json.");
-        }
-        if (!aMetadata.origin) {
-          throw ("Missing 'origin' property in metadata.json.");
-        }
-        return { metadata: aMetadata, appType: aAppType };
-      });
-    }
-    let runnable = {
-      run: function run() {
-        try {
-          let metadata, appType;
-          readManifest().
-            then(readMetadata).
-            then(function ({ metadata, appType }) {
-              let origin = metadata.origin;
-              let manifestURL = metadata.manifestURL ||
-                                origin + "/manifest.webapp";
-              // Create a fake app object with the minimum set of properties we need.
-              let app = {
-                origin: origin,
-                installOrigin: metadata.installOrigin || origin,
-                manifestURL: manifestURL,
-                appStatus: appType,
-                receipts: aReceipts,
-              };
-
-              return writeManifest(app);
-            }).then(function (app) {
-              self._registerApp(deferred, app, aId, aDir);
-            }, function (error) {
-              self._sendError(deferred, error, aId);
-            });
-        } catch (e) {
-          // If anything goes wrong, just send it back.
-          self._sendError(deferred, e.toString(), aId);
-        }
-      }
-    };
-
-    Services.tm.currentThread.dispatch(runnable,
-                                       Ci.nsIThread.DISPATCH_NORMAL);
-    return deferred.promise;
-  },
-
-  installPackagedApp: function wa_actorInstallPackaged(aDir, aId, aReceipts) {
-    debug("installPackagedApp");
-    let self = this;
-    let deferred = promise.defer();
-
-    let runnable = {
-      run: function run() {
-        try {
-          // Open the app zip package
-          let zipFile = aDir.clone();
-          zipFile.append("application.zip");
-          let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]
-                            .createInstance(Ci.nsIZipReader);
-          zipReader.open(zipFile);
-
-          // Prefer manifest.webapp when available
-          let hasWebappManifest = zipReader.hasEntry("manifest.webapp");
-          let hasJsonManifest = zipReader.hasEntry("manifest.json");
-
-          if (!hasWebappManifest && !hasJsonManifest) {
-            self._sendError(deferred, "Missing manifest.webapp or manifest.json", aId);
-            return;
-          }
-
-          let manifestName = hasWebappManifest ? "manifest.webapp" : "manifest.json";
-
-          // Read app manifest from `application.zip`
-          let istream = zipReader.getInputStream(manifestName);
-          let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
-                            .createInstance(Ci.nsIScriptableUnicodeConverter);
-          converter.charset = "UTF-8";
-          let jsonString = converter.ConvertToUnicode(
-            NetUtil.readInputStreamToString(istream, istream.available())
-          );
-          zipReader.close();
-
-          let manifest;
-          try {
-            manifest = JSON.parse(jsonString);
-          } catch (e) {
-            self._sendError(deferred, "Error Parsing " + manifestName + ": " + e, aId);
-            return;
-          }
-
-          if (manifestName === "manifest.json") {
-            if (!UserCustomizations.checkExtensionManifest(manifest)) {
-              self._sendError(deferred, "Invalid manifest", aId);
-              return;
-            }
-            manifest = UserCustomizations.convertManifest(manifest);
-          }
-
-          // Completely forbid pushing apps asking for unsafe permissions
-          if ("permissions" in manifest) {
-            let list = UNSAFE_PERMISSIONS.split(",");
-            let hasOne = list.some(p => p.trim() in manifest.permissions);
-            if (hasOne) {
-              self._sendError(deferred, "Installing apps with any of these " +
-                                        "permissions is forbidden: " +
-                                        UNSAFE_PERMISSIONS, aId);
-              return;
-            }
-          }
-
-          let appType = self._getAppType(manifest.type);
-
-          // Privileged and certified packaged apps can setup a custom origin
-          // via `origin` manifest property
-          let id = aId;
-          if (appType >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED &&
-              manifest.origin !== undefined) {
-            let uri;
-            try {
-              uri = Services.io.newURI(manifest.origin, null, null);
-            } catch (e) {
-              self._sendError(deferred, "Invalid origin in webapp's manifest", aId);
-            }
-
-            if (uri.scheme != "app") {
-              self._sendError(deferred, "Invalid origin in webapp's manifest", aId);
-            }
-            id = uri.prePath.substring(6);
-          }
-
-          // Prevent overriding preinstalled apps
-          if (id in DOMApplicationRegistry.webapps &&
-              DOMApplicationRegistry.webapps[id].removable === false &&
-              !self._isUnrestrictedAccessAllowed()) {
-            self._sendError(deferred, "The application " + id + " can't be overridden.");
-            return;
-          }
-
-          // Only after security checks are made and after final app id is computed
-          // we can move application.zip to the destination directory, and
-          // write manifest.webapp there.
-          let installDir = DOMApplicationRegistry._getAppDir(id);
-          zipFile.moveTo(installDir, "application.zip");
-
-          let manFile = installDir.clone();
-          manFile.append("manifest.webapp");
-          DOMApplicationRegistry._writeFile(manFile.path, JSON.stringify(manifest))
-            .then(() => {
-              let origin = "app://" + id;
-              let manifestURL = origin + "/manifest.webapp";
-
-              // Refresh application.zip content (e.g. reinstall app), as done here:
-              // http://hg.mozilla.org/mozilla-central/annotate/aaefec5d34f8/dom/apps/src/Webapps.jsm#l1125
-              // Do it in parent process for the simulator
-              let jar = installDir.clone();
-              jar.append("application.zip");
-              Services.obs.notifyObservers(jar, "flush-cache-entry", null);
-
-              // And then in app content process
-              // This function will be evaluated in the scope of the content process
-              // frame script. That will flush the jar cache for this app and allow
-              // loading fresh updated resources if we reload its document.
-              let FlushFrameScript = function (path) {
-                let jar = Cc["@mozilla.org/file/local;1"]
-                            .createInstance(Ci.nsILocalFile);
-                jar.initWithPath(path);
-                let obs = Cc["@mozilla.org/observer-service;1"]
-                            .getService(Ci.nsIObserverService);
-                obs.notifyObservers(jar, "flush-cache-entry", null);
-              };
-              for (let frame of self._appFrames()) {
-                if (frame.getAttribute("mozapp") == manifestURL) {
-                  let mm = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
-                  mm.loadFrameScript("data:," +
-                    encodeURIComponent("(" + FlushFrameScript.toString() + ")" +
-                                       "('" + jar.path + "')"), false);
-                }
-              }
-
-              // Create a fake app object with the minimum set of properties we need.
-              let app = {
-                origin: origin,
-                installOrigin: origin,
-                manifestURL: manifestURL,
-                appStatus: appType,
-                receipts: aReceipts,
-                kind: DOMApplicationRegistry.kPackaged,
-              };
-
-              self._registerApp(deferred, app, id, aDir);
-            });
-        } catch (e) {
-          // If anything goes wrong, just send it back.
-          self._sendError(deferred, e.toString(), aId);
-        }
-      }
-    };
-
-    Services.tm.currentThread.dispatch(runnable,
-                                       Ci.nsIThread.DISPATCH_NORMAL);
-    return deferred.promise;
-  },
-
-  /**
-    * @param appId   : The id of the app we want to install. We will look for
-    *                  the files for the app in $TMP/b2g/$appId :
-    *                  For packaged apps: application.zip
-    *                  For hosted apps:   metadata.json and manifest.webapp
-    */
-  install: function wa_actorInstall(aRequest) {
-    debug("install");
-
-    let appId = aRequest.appId;
-    let reg = DOMApplicationRegistry;
-    if (!appId) {
-      appId = reg.makeAppId();
-    }
-
-    // Check that we are not overriding a preinstalled application.
-    if (appId in reg.webapps &&
-        reg.webapps[appId].removable === false &&
-        !this._isUnrestrictedAccessAllowed()) {
-      return { error: "installationFailed",
-               message: "The application " + appId + " can't be overridden."
-             };
-    }
-
-    let appDir = FileUtils.getDir("TmpD", ["b2g", appId], false, false);
-
-    if (aRequest.upload) {
-      // Ensure creating the directory (recursively)
-      appDir = FileUtils.getDir("TmpD", ["b2g", appId], true, false);
-      let actor = this.conn.getActor(aRequest.upload);
-      if (!actor) {
-        return { error: "badParameter",
-                 message: "Unable to find upload actor '" + aRequest.upload
-                          + "'" };
-      }
-      let appFile = FileUtils.File(actor.filePath);
-      if (!appFile.exists()) {
-        return { error: "badParameter",
-                 message: "The uploaded file doesn't exist on device" };
-      }
-      appFile.moveTo(appDir, "application.zip");
-    } else if ((!appDir || !appDir.exists()) &&
-               !aRequest.manifest && !aRequest.metadata) {
-      return { error: "badParameterType",
-               message: "missing directory " + appDir.path
-             };
-    }
-
-    let testFile = appDir.clone();
-    testFile.append("application.zip");
-
-    let receipts = (aRequest.receipts && Array.isArray(aRequest.receipts))
-                    ? aRequest.receipts
-                    : [];
-
-    if (testFile.exists()) {
-      return this.installPackagedApp(appDir, appId, receipts);
-    }
-
-    let manifest, metadata;
-    let missing =
-      ["manifest.webapp", "metadata.json"]
-      .some(function (aName) {
-        testFile = appDir.clone();
-        testFile.append(aName);
-        return !testFile.exists();
-      });
-    if (missing) {
-      if (aRequest.manifest && aRequest.metadata &&
-          aRequest.metadata.origin) {
-        manifest = aRequest.manifest;
-        metadata = aRequest.metadata;
-      } else {
-        try {
-          appDir.remove(true);
-        } catch (e) {}
-        return { error: "badParameterType",
-                 message: "hosted app file and manifest/metadata fields " +
-                          "are missing"
-        };
-      }
-    }
-
-    return this.installHostedApp(appDir, appId, receipts, manifest, metadata);
-  },
-
-  getAll: function wa_actorGetAll(aRequest) {
-    debug("getAll");
-
-    let deferred = promise.defer();
-    this.appsChild.DOMApplicationRegistry.getAll(apps => {
-      deferred.resolve({ apps: this._filterAllowedApps(apps) });
-    });
-
-    return deferred.promise;
-  },
-
-  getApp: function wa_actorGetApp(aRequest) {
-    debug("getApp");
-
-    let manifestURL = aRequest.manifestURL;
-    if (!manifestURL) {
-      return { error: "missingParameter",
-               message: "missing parameter manifestURL" };
-    }
-
-    let reg = DOMApplicationRegistry;
-    let app = reg.getAppByManifestURL(manifestURL);
-    if (!app) {
-      return { error: "appNotFound" };
-    }
-
-    if (!this._isAppAllowedForURL(app.manifestURL)) {
-      return { error: "forbidden" };
-    }
-
-    return reg.getManifestFor(manifestURL).then(function (manifest) {
-      app.manifest = manifest;
-      return { app: app };
-    });
-  },
-
-  _isUnrestrictedAccessAllowed: function () {
-    let pref = "devtools.debugger.forbid-certified-apps";
-    return !Services.prefs.getBoolPref(pref);
-  },
-
-  _isAppAllowed: function (aApp) {
-    if (this._isUnrestrictedAccessAllowed()) {
-      return true;
-    }
-    return aApp.sideloaded;
-  },
-
-  _filterAllowedApps: function wa__filterAllowedApps(aApps) {
-    return aApps.filter(app => this._isAppAllowed(app));
-  },
-
-  _isAppAllowedForURL: function wa__isAppAllowedForURL(aManifestURL) {
-    let reg = DOMApplicationRegistry;
-    let app = reg.getAppByManifestURL(aManifestURL);
-    return this._isAppAllowed(app);
-  },
-
-  uninstall: function wa_actorUninstall(aRequest) {
-    debug("uninstall");
-
-    let manifestURL = aRequest.manifestURL;
-    if (!manifestURL) {
-      return { error: "missingParameter",
-               message: "missing parameter manifestURL" };
-    }
-
-    if (!this._isAppAllowedForURL(manifestURL)) {
-      return { error: "forbidden" };
-    }
-
-    return DOMApplicationRegistry.uninstall(manifestURL);
-  },
-
-  _findManifestByURL: function wa__findManifestByURL(aManifestURL) {
-    let deferred = promise.defer();
-
-    let reg = DOMApplicationRegistry;
-    let id = reg._appIdForManifestURL(aManifestURL);
-
-    reg._readManifests([{ id: id }]).then((aResults) => {
-      deferred.resolve(aResults[0].manifest);
-    });
-
-    return deferred.promise;
-  },
-
-  getIconAsDataURL: function (aRequest) {
-    debug("getIconAsDataURL");
-
-    let manifestURL = aRequest.manifestURL;
-    if (!manifestURL) {
-      return { error: "missingParameter",
-               message: "missing parameter manifestURL" };
-    }
-
-    let reg = DOMApplicationRegistry;
-    let app = reg.getAppByManifestURL(manifestURL);
-    if (!app) {
-      return { error: "wrongParameter",
-               message: "No application for " + manifestURL };
-    }
-
-    let deferred = promise.defer();
-
-    this._findManifestByURL(manifestURL).then(jsonManifest => {
-      let manifest = new ManifestHelper(jsonManifest, app.origin, manifestURL);
-      let iconURL = manifest.iconURLForSize(aRequest.size || 128);
-      if (!iconURL) {
-        deferred.resolve({
-          error: "noIcon",
-          message: "This app has no icon"
-        });
-        return;
-      }
-
-      // Download the URL as a blob
-      // bug 899177: there is a bug with xhr and app:// and jar:// uris
-      // that ends up forcing the content type to application/xml.
-      let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
-                  .createInstance(Ci.nsIXMLHttpRequest);
-      req.open("GET", iconURL, false);
-      req.responseType = "blob";
-
-      try {
-        req.send(null);
-      } catch (e) {
-        deferred.resolve({
-          error: "noIcon",
-          message: "The icon file '" + iconURL + "' doesn't exist"
-        });
-        return;
-      }
-
-      // Convert the blog to a base64 encoded data URI
-      let reader = new FileReader();
-      reader.onload = function () {
-        deferred.resolve({
-          url: reader.result
-        });
-      };
-      reader.onerror = function () {
-        deferred.resolve({
-          error: reader.error.name,
-          message: String(reader.error)
-        });
-      };
-      reader.readAsDataURL(req.response);
-    });
-
-    return deferred.promise;
-  },
-
-  launch: function wa_actorLaunch(aRequest) {
-    debug("launch");
-
-    let manifestURL = aRequest.manifestURL;
-    if (!manifestURL) {
-      return { error: "missingParameter",
-               message: "missing parameter manifestURL" };
-    }
-
-    let deferred = promise.defer();
-
-    if (!this.supportsLaunch) {
-      return { error: "notSupported",
-               message: "Not B2G. Can't launch app." };
-    }
-
-    DOMApplicationRegistry.launch(
-      aRequest.manifestURL,
-      aRequest.startPoint || "",
-      Date.now(),
-      function onsuccess() {
-        deferred.resolve({});
-      },
-      function onfailure(reason) {
-        deferred.resolve({ error: reason });
-      });
-
-    return deferred.promise;
-  },
-
-  close: function wa_actorLaunch(aRequest) {
-    debug("close");
-
-    let manifestURL = aRequest.manifestURL;
-    if (!manifestURL) {
-      return { error: "missingParameter",
-               message: "missing parameter manifestURL" };
-    }
-
-    let reg = DOMApplicationRegistry;
-    let app = reg.getAppByManifestURL(manifestURL);
-    if (!app) {
-      return { error: "missingParameter",
-               message: "No application for " + manifestURL };
-    }
-
-    reg.close(app);
-
-    return {};
-  },
-
-  _appFrames: function () {
-    // Try to filter on b2g and mulet
-    if (Frames) {
-      return Frames.list().filter(frame => {
-        return frame.getAttribute("mozapp");
-      });
-    } else {
-      return [];
-    }
-  },
-
-  listRunningApps: function (aRequest) {
-    debug("listRunningApps\n");
-
-    let appPromises = [];
-    let apps = [];
-
-    for (let frame of this._appFrames()) {
-      let manifestURL = frame.getAttribute("mozapp");
-
-      // _appFrames can return more than one frame with the same manifest url
-      if (apps.indexOf(manifestURL) != -1) {
-        continue;
-      }
-      if (this._isAppAllowedForURL(manifestURL)) {
-        apps.push(manifestURL);
-      }
-    }
-
-    return { apps: apps };
-  },
-
-  getAppActor: function ({ manifestURL }) {
-    debug("getAppActor\n");
-
-    // Connects to the main app frame, whose `name` attribute
-    // is set to 'main' by gaia. If for any reason, gaia doesn't set any
-    // frame as main, no frame matches, then we connect arbitrary
-    // to the first app frame...
-    let appFrame = null;
-    let frames = [];
-    for (let frame of this._appFrames()) {
-      if (frame.getAttribute("mozapp") == manifestURL) {
-        if (frame.name == "main") {
-          appFrame = frame;
-          break;
-        }
-        frames.push(frame);
-      }
-    }
-    if (!appFrame && frames.length > 0) {
-      appFrame = frames[0];
-    }
-
-    let notFoundError = {
-      error: "appNotFound",
-      message: "Unable to find any opened app whose manifest " +
-               "is '" + manifestURL + "'"
-    };
-
-    if (!appFrame) {
-      return notFoundError;
-    }
-
-    if (!this._isAppAllowedForURL(manifestURL)) {
-      return notFoundError;
-    }
-
-    // Only create a new actor, if we haven't already
-    // instanciated one for this connection.
-    let set = this._connectedApps;
-    let mm = appFrame.QueryInterface(Ci.nsIFrameLoaderOwner)
-                     .frameLoader
-                     .messageManager;
-    if (!set.has(mm)) {
-      let onConnect = actor => {
-        set.add(mm);
-        return { actor: actor };
-      };
-      let onDisconnect = mm => {
-        set.delete(mm);
-      };
-      return DebuggerServer.connectToChild(this.conn, appFrame, onDisconnect)
-                           .then(onConnect);
-    }
-
-    // We have to update the form as it may have changed
-    // if we detached the TabActor
-    let deferred = promise.defer();
-    let onFormUpdate = msg => {
-      mm.removeMessageListener("debug:form", onFormUpdate);
-      deferred.resolve({ actor: msg.json });
-    };
-    mm.addMessageListener("debug:form", onFormUpdate);
-    mm.sendAsyncMessage("debug:form");
-
-    return deferred.promise;
-  },
-
-  watchApps: function () {
-    // For now, app open/close events are only implement on b2g
-    if (Frames) {
-      Frames.addObserver(this);
-    }
-    Services.obs.addObserver(this, "webapps-installed", false);
-    Services.obs.addObserver(this, "webapps-uninstall", false);
-
-    return {};
-  },
-
-  unwatchApps: function () {
-    if (Frames) {
-      Frames.removeObserver(this);
-    }
-    Services.obs.removeObserver(this, "webapps-installed", false);
-    Services.obs.removeObserver(this, "webapps-uninstall", false);
-
-    return {};
-  },
-
-  onFrameCreated: function (frame, isFirstAppFrame) {
-    let mozapp = frame.getAttribute("mozapp");
-    if (!mozapp || !isFirstAppFrame) {
-      return;
-    }
-
-    let manifestURL = frame.appManifestURL;
-    // Only track app frames
-    if (!manifestURL) {
-      return;
-    }
-
-    if (this._isAppAllowedForURL(manifestURL)) {
-      this.conn.send({ from: this.actorID,
-                       type: "appOpen",
-                       manifestURL: manifestURL
-                     });
-    }
-  },
-
-  onFrameDestroyed: function (frame, isLastAppFrame) {
-    let mozapp = frame.getAttribute("mozapp");
-    if (!mozapp || !isLastAppFrame) {
-      return;
-    }
-
-    let manifestURL = frame.appManifestURL;
-    // Only track app frames
-    if (!manifestURL) {
-      return;
-    }
-
-    if (this._isAppAllowedForURL(manifestURL)) {
-      this.conn.send({ from: this.actorID,
-                       type: "appClose",
-                       manifestURL: manifestURL
-                     });
-    }
-  },
-
-  observe: function (subject, topic, data) {
-    let app = JSON.parse(data);
-    if (topic == "webapps-installed") {
-      this.conn.send({ from: this.actorID,
-                       type: "appInstall",
-                       manifestURL: app.manifestURL
-                     });
-    } else if (topic == "webapps-uninstall") {
-      this.conn.send({ from: this.actorID,
-                       type: "appUninstall",
-                       manifestURL: app.manifestURL
-                     });
-    }
-  }
-};
-
-/**
- * The request types this actor can handle.
- */
-WebappsActor.prototype.requestTypes = {
-  "install": WebappsActor.prototype.install,
-  "uploadPackage": WebappsActor.prototype.uploadPackage,
-  "getAll": WebappsActor.prototype.getAll,
-  "getApp": WebappsActor.prototype.getApp,
-  "launch": WebappsActor.prototype.launch,
-  "close": WebappsActor.prototype.close,
-  "uninstall": WebappsActor.prototype.uninstall,
-  "listRunningApps": WebappsActor.prototype.listRunningApps,
-  "getAppActor": WebappsActor.prototype.getAppActor,
-  "watchApps": WebappsActor.prototype.watchApps,
-  "unwatchApps": WebappsActor.prototype.unwatchApps,
-  "getIconAsDataURL": WebappsActor.prototype.getIconAsDataURL
-};
-
-exports.WebappsActor = WebappsActor;
--- a/devtools/server/docs/actor-registration.md
+++ b/devtools/server/docs/actor-registration.md
@@ -18,19 +18,19 @@ DebuggerServer.registerModule("devtools/
   constructor: "WebConsoleActor",
   type: { tab: true }
 });
 ```
 
 To register a global actor:
 
 ```
-DebuggerServer.registerModule("devtools/server/actors/webapps", {
-  prefix: "webapps",
-  constructor: "WebappsActor",
+DebuggerServer.registerModule("devtools/server/actors/addons", {
+  prefix: "addons",
+  constructor: "AddonsActor",
   type: { global: true }
 });
 ```
 
 If you are adding a new built-in devtools actor, you should be registering it using `DebuggerServer.registerModule` in `addBrowserActors` or `addTabActors` in `/devtools/server/main.js`.
 
 If you are adding a new actor from an add-on, you should call `DebuggerServer.registerModule` directly from your add-on code.
 
--- a/devtools/server/main.js
+++ b/devtools/server/main.js
@@ -397,21 +397,16 @@ var DebuggerServer = {
         type: { global: true }
       });
     }
     this.registerModule("devtools/server/actors/addons", {
       prefix: "addons",
       constructor: "AddonsActor",
       type: { global: true }
     });
-    this.registerModule("devtools/server/actors/webapps", {
-      prefix: "webapps",
-      constructor: "WebappsActor",
-      type: { global: true }
-    });
     this.registerModule("devtools/server/actors/device", {
       prefix: "device",
       constructor: "DeviceActor",
       type: { global: true }
     });
     this.registerModule("devtools/server/actors/director-registry", {
       prefix: "directorRegistry",
       constructor: "DirectorRegistryActor",
--- a/devtools/shared/apps/moz.build
+++ b/devtools/shared/apps/moz.build
@@ -1,23 +1,10 @@
 # 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/.
 
-MOCHITEST_MANIFESTS += [
-    'tests/mochitest.ini',
-]
-
-TEST_HARNESS_FILES.testing.mochitest.tests.devtools.shared.apps.tests.data += [
-    'tests/data/app-certified.zip',
-    'tests/data/app-overload.zip',
-    'tests/data/app-redirect.zip',
-    'tests/data/app-system.zip',
-    'tests/data/app-updated.zip',
-    'tests/data/app.zip',
-]
-
 DevToolsModules(
     'app-actor-front.js',
     'Devices.jsm',
     'Simulator.jsm'
 )
deleted file mode 100644
--- a/devtools/shared/apps/tests/debugger-protocol-helper.js
+++ /dev/null
@@ -1,181 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cu = Components.utils;
-
-const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
-const { DebuggerClient } = require("devtools/shared/client/main");
-const { DebuggerServer } = require("devtools/server/main");
-const Services = require("Services");
-const { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
-const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
-
-var gClient, gActor;
-
-function connect(onDone) {
-
-  if (Services.appinfo.name == "B2G") {
-    // On b2g, we try to exercice the code that launches the production debugger server
-    let settingsService = Cc["@mozilla.org/settingsService;1"].getService(Ci.nsISettingsService);
-    settingsService.createLock().set("devtools.debugger.remote-enabled", true, null);
-    // We can't use `set` callback as it is fired before shell.js code listening for this setting
-    // is actually called. Same thing applies to mozsettings-changed obs notification.
-    // So listen to a custom event until bug 942756 lands
-    let observer = {
-      observe: function (subject, topic, data) {
-        Services.obs.removeObserver(observer, "debugger-server-started");
-        DebuggerClient.socketConnect({
-          host: "127.0.0.1",
-          port: 6000
-        }).then(transport => {
-          startClient(transport, onDone);
-        }, e => dump("Connection failed: " + e + "\n"));
-      }
-    };
-    Services.obs.addObserver(observer, "debugger-server-started", false);
-  } else {
-    // Initialize a loopback remote protocol connection
-    DebuggerServer.init();
-    // We need to register browser actors to have `listTabs` working
-    // and also have a root actor
-    DebuggerServer.addBrowserActors();
-    let transport = DebuggerServer.connectPipe();
-    startClient(transport, onDone);
-  }
-}
-
-function startClient(transport, onDone) {
-  // Setup client and actor used in all tests
-  gClient = new DebuggerClient(transport);
-  gClient.connect()
-    .then(() => gClient.listTabs())
-    .then(aResponse => {
-      gActor = aResponse.webappsActor;
-      if (gActor)
-        webappActorRequest({type: "watchApps"}, onDone);
-    });
-
-  gClient.addListener("appInstall", function (aState, aType, aPacket) {
-    sendAsyncMessage("installed-event", { manifestURL: aType.manifestURL });
-  });
-
-  gClient.addListener("appUninstall", function (aState, aType, aPacket) {
-    sendAsyncMessage("uninstalled-event", { manifestURL: aType.manifestURL });
-  });
-
-  addMessageListener("appActorRequest", request => {
-    webappActorRequest(request, response => {
-      sendAsyncMessage("appActorResponse", response);
-    });
-  });
-}
-
-function webappActorRequest(request, onResponse) {
-  if (!gActor) {
-    connect(webappActorRequest.bind(null, request, onResponse));
-    return;
-  }
-
-  request.to = gActor;
-  gClient.request(request, onResponse);
-}
-
-
-function downloadURL(url, file) {
-  let channel = NetUtil.newChannel({
-    uri: url,
-    loadUsingSystemPrincipal: true
-  });
-  let istream = channel.open2();
-  let bstream = Cc["@mozilla.org/binaryinputstream;1"]
-                  .createInstance(Ci.nsIBinaryInputStream);
-  bstream.setInputStream(istream);
-  let data = bstream.readBytes(bstream.available());
-
-  let ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"]
-                  .createInstance(Ci.nsIFileOutputStream);
-  ostream.init(file, 0x04 | 0x08 | 0x20, 0o600, 0);
-  ostream.write(data, data.length);
-  ostream.QueryInterface(Ci.nsISafeOutputStream).finish();
-}
-
-// Install a test packaged webapp from data folder
-addMessageListener("install", function (aMessage) {
-  let url = aMessage.url;
-  let appId = aMessage.appId;
-
-  try {
-    // Download its content from mochitest http server
-    // Copy our package to tmp folder, where the actor retrieves it
-    let zip = FileUtils.getDir("TmpD", ["b2g", appId], true, true);
-    zip.append("application.zip");
-    downloadURL(url, zip);
-
-    let request = {type: "install", appId: appId};
-    webappActorRequest(request, function (aResponse) {
-      sendAsyncMessage("installed", aResponse);
-    });
-  } catch (e) {
-    dump("installTestApp exception: " + e + "\n");
-  }
-});
-
-addMessageListener("getAppActor", function (aMessage) {
-  let { manifestURL } = aMessage;
-  let request = {type: "getAppActor", manifestURL: manifestURL};
-  webappActorRequest(request, function (aResponse) {
-    sendAsyncMessage("appActor", aResponse);
-  });
-});
-
-var Frames = [];
-addMessageListener("addFrame", function (aMessage) {
-  let win = Services.wm.getMostRecentWindow("navigator:browser");
-  let doc = win.document;
-  let frame = doc.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
-  frame.setAttribute("mozbrowser", "true");
-  if (aMessage.mozapp) {
-    frame.setAttribute("mozapp", aMessage.mozapp);
-  }
-  if (aMessage.remote) {
-    frame.setAttribute("remote", aMessage.remote);
-  }
-  if (aMessage.src) {
-    frame.setAttribute("src", aMessage.src);
-  }
-  doc.documentElement.appendChild(frame);
-  Frames.push(frame);
-  sendAsyncMessage("frameAdded");
-});
-
-addMessageListener("tweak-app-object", function (aMessage) {
-  let appId = aMessage.appId;
-  let { DOMApplicationRegistry } = Cu.import("resource://gre/modules/Webapps.jsm", {});
-  let reg = DOMApplicationRegistry;
-  if ("removable" in aMessage) {
-    reg.webapps[appId].removable = aMessage.removable;
-  }
-  if ("sideloaded" in aMessage) {
-    reg.webapps[appId].sideloaded = aMessage.sideloaded;
-  }
-});
-
-addMessageListener("cleanup", function () {
-  webappActorRequest({type: "unwatchApps"}, function () {
-    gClient.close();
-  });
-});
-
-var FramesMock = {
-  list: function () {
-    return Frames;
-  },
-  addObserver: function () {},
-  removeObserver: function () {}
-};
-
-require("devtools/server/actors/webapps").setFramesMock(FramesMock);
deleted file mode 100644
--- a/devtools/shared/apps/tests/mochitest.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[DEFAULT]
-skip-if = true ### Bug 1255339: blacklist because no more mozApps
-support-files =
-  debugger-protocol-helper.js
-  redirect.sjs
-
-[test_webapps_actor.html]
deleted file mode 100644
--- a/devtools/shared/apps/tests/redirect.sjs
+++ /dev/null
@@ -1,7 +0,0 @@
-const REDIRECTION_URL = "http://example.com/redirection-target.html";
-
-function handleRequest(request, response) {
-  response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
-  response.setHeader("Location", REDIRECTION_URL, false);
-}
-
deleted file mode 100644
--- a/devtools/shared/apps/tests/test_webapps_actor.html
+++ /dev/null
@@ -1,413 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id={821589}
--->
-<head>
-  <title>Test for Bug {821589} Packaged apps installation and update</title>
-  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={821589}">Mozilla Bug {821589}</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.8">
-
-"use strict";
-
-var index = -1;
-
-function debug(aMsg) {
-  //dump("== Tests debug == " + aMsg + "\n");
-}
-
-function next() {
-  index += 1;
-  if (index >= steps.length) {
-    ok(false, "Shouldn't get here!");
-    return;
-  }
-  try {
-    steps[index]();
-  } catch(ex) {
-    ok(false, "Caught exception", ex);
-  }
-}
-
-function start() {
-  next();
-}
-
-function finish() {
-  SpecialPowers.removePermission("webapps-manage", document);
-  SimpleTest.finish();
-}
-
-function cbError(aError) {
-  ok(false, "Error callback invoked " + aError);
-  finish();
-}
-
-
-SimpleTest.waitForExplicitFinish();
-
-var installTestApp, mm;
-
-const PACKAGED_APP_ID = "test-app-id";
-const PACKAGED_APP_ORIGIN = "app://" + PACKAGED_APP_ID;
-const PACKAGED_APP_MANIFEST = PACKAGED_APP_ORIGIN + "/manifest.webapp";
-const CERTIFIED_APP_ID = "test-certified-id";
-const CERTIFIED_APP_ORIGIN = "app://" + CERTIFIED_APP_ID;
-const CERTIFIED_APP_MANIFEST = CERTIFIED_APP_ORIGIN + "/manifest.webapp";
-const SYSTEM_APP_ID = "test-system-id";
-
-var steps = [
-  function() {
-    info("== SETUP ==");
-    // Set up
-    SpecialPowers.addPermission("webapps-manage", true, document);
-    SpecialPowers.addPermission("browser", true, document);
-    SpecialPowers.addPermission("embed-apps", true, document);
-
-    // Required on firefox as these prefs are only set on b2g:
-    SpecialPowers.pushPrefEnv({
-      set: [["dom.mozBrowserFramesEnabled", true],
-            ["security.apps.privileged.CSP.default",
-             "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'"],
-            ["devtools.debugger.unix-domain-socket", 6000],
-            ["devtools.debugger.prompt-connection", false],
-            ["devtools.debugger.forbid-certified-apps", true]
-           ]
-    }, next);
-  },
-  function () {
-    // Load a chrome script in order to dispatch devtool debugger requests.
-    // Because of wrapping issues, we can't use SpecialPowers.Cu.import to load
-    // devtools jsm into mochitest scope. We end up not receiving
-    // DebuggerClient.addListener callback arguments...
-    let scriptUrl = SimpleTest.getTestFileURL("debugger-protocol-helper.js");
-    mm = SpecialPowers.loadChromeScript(scriptUrl);
-    installTestApp = function (url, appId, callback) {
-      let installResponse, appObject;
-      let installedEvent = false;
-      function onInstalled(aResponse) {
-        ok(true, "install request replied");
-        installResponse = aResponse;
-        checkEnd();
-      }
-      mm.addMessageListener("installed", onInstalled);
-      function onInstalledEvent(aResponse) {
-        ok(true, "received appInstall actor event");
-        installedEvent = true;
-        checkEnd();
-      }
-      mm.addMessageListener("installed-event", onInstalledEvent);
-      navigator.mozApps.mgmt.oninstall = function(evt) {
-        appObject = evt.application;
-        ok(true, "mozApps.mgmt install event fired");
-        checkEnd();
-      };
-      function checkEnd() {
-        if ( (appObject && installResponse && installedEvent) ||
-             (installResponse && installResponse.error) ) {
-          mm.removeMessageListener("installed", onInstalled);
-          mm.removeMessageListener("installed-event", onInstalledEvent);
-          navigator.mozApps.mgmt.oninstall = null;
-          callback(installResponse, appObject);
-        }
-      }
-      mm.sendAsyncMessage("install", {url: url, appId: appId});
-    };
-    SpecialPowers.autoConfirmAppInstall(next);
-  },
-  function() {
-    info("== TEST == Install packaged app");
-    let url = SimpleTest.getTestFileURL("data/app.zip");
-    installTestApp(url, PACKAGED_APP_ID,
-      function (aResponse, aApp) {
-        ok(true, "Installed");
-        is(aResponse.appId, PACKAGED_APP_ID, "Got same app id");
-        if ("error" in aResponse) {
-          ok(false, "Error: " + aResponse.error);
-        }
-        if ("message" in aResponse) {
-          ok(false, "Error message: " + aResponse.message);
-        }
-        ok(!("error" in aResponse), "app installed without any error");
-        is(aApp.manifest.name, "Test app", "app name is correct");
-        next();
-      }
-    );
-  },
-  function () {
-    info("== TEST == Reinstall packaged app");
-    let url = SimpleTest.getTestFileURL("data/app-updated.zip");
-    installTestApp(url, PACKAGED_APP_ID,
-      function (aResponse, aApp) {
-        ok(true, "Reinstalled");
-        is(aResponse.appId, PACKAGED_APP_ID, "Got same app id");
-        if ("error" in aResponse) {
-          ok(false, "Error: " + aResponse.error);
-        }
-        if ("message" in aResponse) {
-          ok(false, "Error message: " + aResponse.message);
-        }
-        ok(!("error" in aResponse), "app installed without any error");
-        is(aApp.manifest.name, "updated-name", "app name on update is correct");
-        next();
-      }
-    );
-  },
-  function() {
-    info("== TEST == Install certified app");
-    let url = SimpleTest.getTestFileURL("data/app-certified.zip");
-    installTestApp(url, CERTIFIED_APP_ID,
-      function (aResponse, aApp) {
-        ok(true, "Installed");
-        is(aResponse.appId, CERTIFIED_APP_ID, "Got same app id");
-        if ("error" in aResponse) {
-          ok(false, "Error: " + aResponse.error);
-        }
-        if ("message" in aResponse) {
-          ok(false, "Error message: " + aResponse.message);
-        }
-        ok(!("error" in aResponse), "app installed without any error");
-        is(aApp.manifest.name, "Certified app", "app name is correct");
-        next();
-      }
-    );
-  },
-  function() {
-    info("== TEST == Try overloading non-removable app");
-    let url = SimpleTest.getTestFileURL("data/app-overload.zip");
-    installTestApp(url, CERTIFIED_APP_ID,
-      function (aResponse, aApp) {
-        // First time we install the app, it works just fine
-        ok(true, "Installed");
-        is(aResponse.appId, "overload.gaiamobile.org", "Got overloaded app id");
-        if ("error" in aResponse) {
-          ok(false, "Error: " + aResponse.error);
-        }
-        if ("message" in aResponse) {
-          ok(false, "Error message: " + aResponse.message);
-        }
-        ok(!("error" in aResponse), "app installed without any error");
-        is(aApp.manifest.name, "System app", "app name is correct");
-
-        // Then use some magic to make it non-removable
-        mm.sendAsyncMessage("tweak-app-object", {appId: CERTIFIED_APP_ID, removable: false});
-
-        // Then when trying to install it again, it will be rejected
-        installTestApp(url, CERTIFIED_APP_ID,
-          function (aResponse, aApp) {
-            is(aResponse.error, "installationFailed", "Overloading non-removable app without the pref is rejected");
-            is(aResponse.message, "The application " + CERTIFIED_APP_ID + " can't be overridden.");
-            next();
-          });
-
-      }
-    );
-  },
-  function() {
-    info("== TEST == Get all apps");
-    getAll(true);
-  },
-  function() {
-    info("== TEST == Get packaged app");
-    getApp({
-      id: PACKAGED_APP_ID,
-      manifestURL: PACKAGED_APP_MANIFEST
-    }, true);
-  },
-  function() {
-    info("== TEST == Get certified app");
-    getApp({
-      id: CERTIFIED_APP_ID,
-      manifestURL: CERTIFIED_APP_MANIFEST
-    }, true);
-  },
-  function() {
-    info("== SETUP == Enable certified app access");
-    SpecialPowers.pushPrefEnv({
-      "set": [["devtools.debugger.forbid-certified-apps", false]]
-    }, next);
-  },
-  function() {
-    info("== TEST == Get all apps (CERTIFIED ENABLED)");
-    getAll(true);
-  },
-  function() {
-    info("== TEST == Get packaged app (CERTIFIED ENABLED)");
-    getApp({
-      id: PACKAGED_APP_ID,
-      manifestURL: PACKAGED_APP_MANIFEST
-    }, true);
-  },
-  function() {
-    info("== TEST == Get certified app (CERTIFIED ENABLED)");
-    getApp({
-      id: CERTIFIED_APP_ID,
-      manifestURL: CERTIFIED_APP_MANIFEST
-    }, true);
-  },
-  function() {
-    info("== TEST == Overload of non-removable apps is allowed with CERTIFIED ENABLE");
-    let url = SimpleTest.getTestFileURL("data/app-overload.zip");
-    installTestApp(url, SYSTEM_APP_ID,
-      function (aResponse, aApp) {
-        ok(true, "Installed");
-        is(aResponse.appId, "overload.gaiamobile.org", "Got overloaded app id");
-        if ("error" in aResponse) {
-          ok(false, "Error: " + aResponse.error);
-        }
-        if ("message" in aResponse) {
-          ok(false, "Error message: " + aResponse.message);
-        }
-        ok(!("error" in aResponse), "app installed without any error");
-        is(aApp.manifest.name, "System app", "app name is correct");
-        next();
-      }
-    );
-  },
-  function() {
-    info("== SETUP == Disable certified app access");
-    SpecialPowers.popPrefEnv(next);
-  },
-  function() {
-    info("== TEST == Get packaged app actor");
-    addFrame(
-      { mozapp: PACKAGED_APP_MANIFEST, remote: true },
-      function () {
-        getAppActor(PACKAGED_APP_MANIFEST, function (response) {
-          let tabActor = response.actor;
-          ok(!!tabActor, "TabActor is correctly instanciated in child.js");
-          ok("actor" in tabActor, "Tab actor is available in child");
-          ok("consoleActor" in tabActor, "Console actor is available in child");
-          next();
-        });
-      });
-
-  },
-  function() {
-    info("== TEST == Uninstall packaged app");
-    uninstall(PACKAGED_APP_MANIFEST);
-  },
-  function() {
-    info("== TEST == Uninstall certified app");
-    // Make the app removable again, but make it appear as a regular app (not being pushed via devtools)
-    mm.sendAsyncMessage("tweak-app-object", {appId: CERTIFIED_APP_ID, removable: true, sideloaded: false});
-
-    mm.addMessageListener("appActorResponse", function onResponse(response) {
-      mm.removeMessageListener("appActorResponse", onResponse);
-      is(response.error, "forbidden", "Uninstalling apps that have not being sideloaded is forbidden");
-      next();
-    });
-
-    mm.sendAsyncMessage("appActorRequest", {
-      type: "uninstall",
-      manifestURL: CERTIFIED_APP_MANIFEST
-    });
-  },
-  function() {
-    ok(true, "all done!\n");
-    mm.sendAsyncMessage("cleanup");
-    SpecialPowers.flushPrefEnv(finish);
-  }
-];
-
-addLoadEvent(start);
-
-function getAll(expectCertified) {
-  mm.addMessageListener("appActorResponse", function onResponse(response) {
-    mm.removeMessageListener("appActorResponse", onResponse);
-
-    ok("apps" in response, "Apps found in getAll reply");
-    let apps = response.apps;
-    let packagedApp, certifiedApp;
-    for (let app of apps) {
-      switch (app.id) {
-        case PACKAGED_APP_ID:
-          packagedApp = app;
-          break;
-        case CERTIFIED_APP_ID:
-          certifiedApp = app;
-          break;
-      }
-    }
-
-    ok(packagedApp, "Packaged app found via getAll");
-    is(!!certifiedApp, expectCertified, "Certified app matches expectation");
-
-    next();
-  });
-
-  mm.sendAsyncMessage("appActorRequest", {
-    type: "getAll"
-  });
-}
-
-function getApp(appInfo, expected) {
-  mm.addMessageListener("appActorResponse", function onResponse(response) {
-    mm.removeMessageListener("appActorResponse", onResponse);
-
-    is("app" in response, expected, "App existence matches expectation");
-    is("error" in response, !expected, "Error existence matches expectation");
-    if (!expected) {
-      is(response.error, "forbidden", "Error message is correct");
-      next();
-      return;
-    }
-
-    let app = response.app;
-    for (let key in appInfo) {
-      is(app[key], appInfo[key], "Value for " + key + " matches");
-    }
-
-    next();
-  });
-
-  mm.sendAsyncMessage("appActorRequest", {
-    type: "getApp",
-    manifestURL: appInfo.manifestURL
-  });
-}
-
-function uninstall(manifestURL) {
-  mm.addMessageListener("appActorResponse", function onResponse(response) {
-    mm.removeMessageListener("appActorResponse", onResponse);
-    ok(!("error" in response), "App uninstalled successfully");
-    next();
-  });
-
-  mm.sendAsyncMessage("appActorRequest", {
-    type: "uninstall",
-    manifestURL: manifestURL
-  });
-}
-
-function getAppActor(manifestURL, callback) {
-  mm.addMessageListener("appActor", function onAppActor(aResponse) {
-    mm.removeMessageListener("appActor", onAppActor);
-    callback(aResponse);
-  });
-  mm.sendAsyncMessage("getAppActor", { manifestURL: manifestURL });
-}
-
-function addFrame(options, callback) {
-  mm.addMessageListener("frameAdded", function onFrameAdded() {
-    mm.removeMessageListener("frameAdded", onFrameAdded);
-    callback();
-  });
-  mm.sendAsyncMessage("addFrame", options);
-}
-
-</script>
-</pre>
-</body>
-</html>