Backed out changeset df960e299bcd (bug 1108096) for m1 test failures
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 12 Jan 2015 09:02:13 +0100
changeset 249072 4583ade26b7e1af024bccacfaa3bccb9a9051e1d
parent 249071 adfe0cd4c6318630b6d4381ad248054bd836fefa
child 249073 f3f06c6800fc73f0cd6bf26195529b61b69378f7
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1108096
milestone37.0a1
backs outdf960e299bcd2bf93e95368623b5973056143f7e
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset df960e299bcd (bug 1108096) for m1 test failures
dom/apps/AppsServiceChild.jsm
dom/apps/AppsUtils.jsm
dom/apps/Langpacks.jsm
dom/apps/Webapps.js
dom/apps/Webapps.jsm
dom/apps/moz.build
dom/apps/tests/langpack/event.html
dom/apps/tests/langpack/fr/app.json
dom/apps/tests/langpack/fr/app.properties
dom/apps/tests/langpack/index.html
dom/apps/tests/langpack/lang1.webapp
dom/apps/tests/langpack/lang1.webapp^headers^
dom/apps/tests/langpack/lang2.webapp
dom/apps/tests/langpack/lang2.webapp^headers^
dom/apps/tests/langpack/manifest.webapp
dom/apps/tests/langpack/manifest.webapp^headers^
dom/apps/tests/langpack/resources.html
dom/apps/tests/mochitest.ini
dom/apps/tests/test_langpacks.html
dom/tests/mochitest/webapps/test_list_api.xul
dom/webidl/Apps.webidl
--- a/dom/apps/AppsServiceChild.jsm
+++ b/dom/apps/AppsServiceChild.jsm
@@ -349,25 +349,16 @@ this.DOMApplicationRegistry = {
 
     let res = [];
     for (let id in this.webapps) {
       res.push(this.webapps[id]);
     }
     aCallback(res);
   },
 
-  getAdditionalLanguages: function(aManifestURL) {
-    for (let id in this.webapps) {
-      if (this.webapps[id].manifestURL == aManifestURL) {
-        return this.webapps[id].additionalLanguages || {};
-      }
-    }
-    return {};
-  },
-
   /**
    * nsIAppsService API
    */
   getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
     debug("getAppByManifestURL " + aManifestURL);
     return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
   },
 
--- a/dom/apps/AppsUtils.jsm
+++ b/dom/apps/AppsUtils.jsm
@@ -17,20 +17,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   "resource://gre/modules/FileUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "WebappOSUtils",
   "resource://gre/modules/WebappOSUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
   "resource://gre/modules/NetUtil.jsm");
 
-XPCOMUtils.defineLazyServiceGetter(this, "appsService",
-                                   "@mozilla.org/AppsService;1",
-                                   "nsIAppsService");
-
 // Shared code for AppsServiceChild.jsm, TrustedHostedAppsUtils.jsm,
 // Webapps.jsm and Webapps.js
 
 this.EXPORTED_SYMBOLS =
   ["AppsUtils", "ManifestHelper", "isAbsoluteURI", "mozIApplication"];
 
 function debug(s) {
   //dump("-*- AppsUtils.jsm: " + s + "\n");
@@ -484,31 +480,23 @@ this.AppsUtils = {
   },
 
   allowUnsignedAddons: false, // for testing purposes.
 
   /**
    * Checks if the app role is allowed:
    * Only certified apps can be themes.
    * Only privileged or certified apps can be addons.
-   * Langpacks need to be privileged.
    * @param aRole   : the role assigned to this app.
    * @param aStatus : the APP_STATUS_* for this app.
    */
   checkAppRole: function(aRole, aStatus) {
     if (aRole == "theme" && aStatus !== Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
       return false;
     }
-    if (aRole == "langpack" && aStatus !== Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
-      let allow = false;
-      try  {
-        allow = Services.prefs.getBoolPref("dom.apps.allow_unsigned_langpacks");
-      } catch(e) {}
-      return allow;
-    }
     if (!this.allowUnsignedAddons &&
         (aRole == "addon" &&
          aStatus !== Ci.nsIPrincipal.APP_STATUS_CERTIFIED &&
          aStatus !== Ci.nsIPrincipal.APP_STATUS_PRIVILEGED)) {
       return false;
     }
     return true;
   },
@@ -739,26 +727,17 @@ this.AppsUtils = {
 
     // Convert the binary hash data to a hex string.
     return [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
   },
 
   // Returns the hash for a JS object.
   computeObjectHash: function(aObject) {
     return this.computeHash(JSON.stringify(aObject));
-  },
-
-  getAppManifestURLFromWindow: function(aWindow) {
-    let appId = aWindow.document.nodePrincipal.appId;
-    if (appId === Ci.nsIScriptSecurityManager.NO_APP_ID) {
-      return null;
-    }
-
-    return appsService.getManifestURLByLocalId(appId);
-  },
+  }
 }
 
 /**
  * Helper object to access manifest information with locale support
  */
 this.ManifestHelper = function(aManifest, aOrigin, aManifestURL) {
   // If the app is packaged, we resolve uris against the origin.
   // If it's not, against the manifest url.
deleted file mode 100644
--- a/dom/apps/Langpacks.jsm
+++ /dev/null
@@ -1,315 +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 Cu = Components.utils;
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/AppsUtils.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
-                                   "@mozilla.org/parentprocessmessagemanager;1",
-                                   "nsIMessageBroadcaster");
-
-this.EXPORTED_SYMBOLS = ["Langpacks"];
-
-let debug = Services.prefs.getBoolPref("dom.mozApps.debug")
-  ? (aMsg) => {
-      dump("-*-*- Langpacks: " + aMsg + "\n");
-    }
-  : (aMsg) => {};
-
-/**
-  * Langpack support
-  *
-  * Manifest format is:
-  *
-  * "languages-target" : { "app://*.gaiamobile.org/manifest.webapp": "2.2" },
-  * "languages-provided": {
-  * "de": {
-  *   "version": 201411051234,
-  *   "name": "Deutsch",
-  *   "apps": {
-  *     "app://calendar.gaiamobile.org/manifest.webapp": "/de/calendar",
-  *     "app://email.gaiamobile.org/manifest.webapp": "/de/email"
-  *    }
-  *  },
-  *  "role" : "langpack"
-  */
-
-this.Langpacks = {
-
-  _data: {},
-  _broadcaster: null,
-  _appIdFromManifestURL: null,
-
-  init: function() {
-    ppmm.addMessageListener("Webapps:GetLocalizationResource", this);
-  },
-
-  registerRegistryFunctions: function(aBroadcaster, aIdGetter) {
-    this._broadcaster = aBroadcaster;
-    this._appIdFromManifestURL = aIdGetter;
-  },
-
-  receiveMessage: function(aMessage) {
-    let data = aMessage.data;
-    let mm = aMessage.target;
-    switch (aMessage.name) {
-      case "Webapps:GetLocalizationResource":
-        this.getLocalizationResource(data, mm);
-        break;
-      default:
-        debug("Unexpected message: " + aMessage.name);
-    }
-  },
-
-  getAdditionalLanguages: function(aManifestURL) {
-    debug("getAdditionalLanguages " + aManifestURL);
-    let res = { langs: {} };
-    let langs = res.langs;
-    if (this._data[aManifestURL]) {
-      res.appId = this._data[aManifestURL].appId;
-      for (let lang in this._data[aManifestURL].langs) {
-        if (!langs[lang]) {
-          langs[lang] = [];
-        }
-        let current = this._data[aManifestURL].langs[lang];
-        langs[lang].push({
-          version: current.version,
-          name: current.name,
-          target: current.target
-        });
-      }
-    }
-    debug("Languages found: " + uneval(res));
-    return res;
-  },
-
-  sendAppUpdate: function(aManifestURL) {
-    debug("sendAppUpdate " + aManifestURL);
-    if (!this._broadcaster) {
-      debug("No broadcaster!");
-      return;
-    }
-
-    let res = this.getAdditionalLanguages(aManifestURL);
-    let message = {
-      id: res.appId,
-      app: {
-        additionalLanguages: res.langs
-      }
-    }
-    this._broadcaster("Webapps:UpdateState", message);
-  },
-
-  getLocalizationResource: function(aData, aMm) {
-    debug("getLocalizationResource " + uneval(aData));
-
-    function sendError(aMsg, aCode) {
-      debug(aMsg);
-      aMm.sendAsyncMessage("Webapps:GetLocalizationResource:Return",
-        { requestID: aData.requestID, oid: aData.oid, error: aCode });
-    }
-
-    // No langpack available for this app.
-    if (!this._data[aData.manifestURL]) {
-      return sendError("No langpack for this app.", "NoLangpack");
-    }
-
-    // We have langpack(s) for this app, but not for this language.
-    if (!this._data[aData.manifestURL].langs[aData.lang]) {
-      return sendError("No language " + aData.lang + " for this app.",
-                       "UnavailableLanguage");
-    }
-
-    // Check that we have the right version.
-    let item = this._data[aData.manifestURL].langs[aData.lang];
-    if (item.target != aData.version) {
-      return sendError("No version " + aData.version + " for this app.",
-                       "UnavailableVersion");
-    }
-
-    // The path can't be an absolute uri.
-    if (isAbsoluteURI(aData.path)) {
-      return sendError("url can't be absolute.", "BadUrl");
-    }
-
-    let href = item.url + aData.path;
-    debug("Will load " + href);
-
-    let xhr =  Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
-                 .createInstance(Ci.nsIXMLHttpRequest);
-    xhr.mozBackgroundRequest = true;
-    xhr.open("GET", href);
-
-    // Default to text response type, but the webidl binding takes care of
-    // validating the dataType value.
-    xhr.responseType = "text";
-    if (aData.dataType === "json") {
-      xhr.responseType = "json";
-    } else if (aData.dataType === "binary") {
-      xhr.responseType = "blob";
-    }
-
-    xhr.addEventListener("load", function() {
-      debug("Success loading " + href);
-      if (xhr.status >= 200 && xhr.status < 400) {
-        aMm.sendAsyncMessage("Webapps:GetLocalizationResource:Return",
-          { requestID: aData.requestID, oid: aData.oid, data: xhr.response });
-      } else {
-        sendError("Error loading " + href, "UnavailableResource");
-      }
-    });
-    xhr.addEventListener("error", function() {
-      sendError("Error loading " + href, "UnavailableResource");
-    });
-    xhr.send(null);
-  },
-
-  // Validates the langpack part of a manifest.
-  checkManifest: function(aManifest) {
-    if (!("languages-target" in aManifest)) {
-      debug("Error: no 'languages-target' property.")
-      return false;
-    }
-
-    if (!("languages-provided" in aManifest)) {
-      debug("Error: no 'languages-provided' property.")
-      return false;
-    }
-
-    for (let lang in aManifest["languages-provided"]) {
-      let item = aManifest["languages-provided"][lang];
-
-      if (!item.version) {
-        debug("Error: missing 'version' in languages-provided." + lang);
-        return false;
-      }
-
-      if (typeof item.version !== "number") {
-        debug("Error: languages-provided." + lang +
-              ".version must be a number but is a " + (typeof item.version));
-        return false;
-      }
-
-      if (!item.apps) {
-        debug("Error: missing 'apps' in languages-provided." + lang);
-        return false;
-      }
-
-      for (let app in item.apps) {
-        // Keys should be manifest urls, ie. absolute urls.
-        if (!isAbsoluteURI(app)) {
-          debug("Error: languages-provided." + lang + "." + app +
-                " must be an absolute manifest url.");
-          return false;
-        }
-
-        if (typeof item.apps[app] !== "string") {
-          debug("Error: languages-provided." + lang + ".apps." + app +
-                " value must be a string but is " + (typeof item.apps[app]) +
-                " : " + item.apps[app]);
-          return false;
-        }
-      }
-    }
-    return true;
-  },
-
-  // Check if this app is a langpack and update registration if needed.
-  register: function(aApp, aManifest) {
-    debug("register app " + aApp.manifestURL + " role=" + aApp.role);
-
-    if (aApp.role !== "langpack") {
-      debug("Not a langpack.");
-      // Not a langpack, but that's fine.
-      return;
-    }
-
-    if (!this.checkManifest(aManifest)) {
-      debug("Invalid langpack manifest.");
-      return;
-    }
-
-    let platformVersion = aManifest["languages-target"]
-                                   ["app://*.gaiamobile.org/manifest.webapp"];
-    let origin = Services.io.newURI(aApp.origin, null, null);
-
-    for (let lang in aManifest["languages-provided"]) {
-      let item = aManifest["languages-provided"][lang];
-      let version = item.version;   // The langpack version, not the platform.
-      let name = item.name || lang; // If no name specified, default to lang.
-      for (let app in item.apps) {
-        let sendEvent = false;
-        if (!this._data[app] ||
-            !this._data[app].langs[lang] ||
-            this._data[app].langs[lang].version > version) {
-          if (!this._data[app]) {
-            this._data[app] = {
-              appId: this._appIdFromManifestURL(app),
-              langs: {}
-            };
-          }
-          this._data[app].langs[lang] = {
-            version: version,
-            target: platformVersion,
-            name: name,
-            url: origin.resolve(item.apps[app]),
-            from: aApp.manifestURL
-          }
-          sendEvent = true;
-          debug("Registered " + app + " -> " + uneval(this._data[app].langs[lang]));
-        }
-
-        // Fire additionallanguageschange event.
-        // This will only be dispatched to documents using the langpack api.
-        if (sendEvent) {
-          this.sendAppUpdate(app);
-          ppmm.broadcastAsyncMessage(
-            "Webapps:AdditionalLanguageChange",
-            { manifestURL: app,
-              languages: this.getAdditionalLanguages(app).langs });
-        }
-      }
-    }
-  },
-
-  // Check if this app is a langpack and update registration by removing all
-  // the entries from this app.
-  unregister: function(aApp, aManifest) {
-    debug("unregister app " + aApp.manifestURL + " role=" + aApp.role);
-
-      if (aApp.role !== "langpack") {
-        debug("Not a langpack.");
-        // Not a langpack, but that's fine.
-        return;
-      }
-
-      for (let app in this._data) {
-        let sendEvent = false;
-        for (let lang in this._data[app].langs) {
-          if (this._data[app].langs[lang].from == aApp.manifestURL) {
-            sendEvent = true;
-            delete this._data[app].langs[lang];
-          }
-        }
-        // Fire additionallanguageschange event.
-        // This will only be dispatched to documents using the langpack api.
-        if (sendEvent) {
-          this.sendAppUpdate(app);
-          ppmm.broadcastAsyncMessage(
-              "Webapps:AdditionalLanguageChange",
-              { manifestURL: app,
-                languages: this.getAdditionalLanguages(app).langs });
-        }
-      }
-  }
-}
-
-Langpacks.init();
\ No newline at end of file
--- a/dom/apps/Webapps.js
+++ b/dom/apps/Webapps.js
@@ -39,28 +39,21 @@ function convertAppsArray(aApps, aWindow
 function WebappsRegistry() {
 }
 
 WebappsRegistry.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
 
   receiveMessage: function(aMessage) {
     let msg = aMessage.json;
-    let req;
-    if (msg.oid === this._id) {
-      if (aMessage.name == "Webapps:GetLocalizationResource:Return") {
-        req = this.takePromiseResolver(msg.requestID);
-      } else {
-        req = this.getRequest(msg.requestID);
-      }
-      if (!req) {
-        return;
-      }
-    }
-
+    if (msg.oid != this._id)
+      return
+    let req = this.getRequest(msg.requestID);
+    if (!req)
+      return;
     let app = msg.app;
     switch (aMessage.name) {
       case "Webapps:Install:Return:OK":
         this.removeMessageListeners("Webapps:Install:Return:KO");
         Services.DOMRequest.fireSuccess(req, createContentApplicationObject(this._window, app));
         cpmm.sendAsyncMessage("Webapps:Install:Return:Ack",
                               { manifestURL : app.manifestURL });
         break;
@@ -80,36 +73,16 @@ WebappsRegistry.prototype = {
       case "Webapps:CheckInstalled:Return:OK":
         this.removeMessageListeners(aMessage.name);
         Services.DOMRequest.fireSuccess(req, msg.app);
         break;
       case "Webapps:GetInstalled:Return:OK":
         this.removeMessageListeners(aMessage.name);
         Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
         break;
-      case "Webapps:AdditionalLanguageChange":
-        // Check if the current page is from the app receiving the event.
-        let manifestURL = AppsUtils.getAppManifestURLFromWindow(this._window);
-        if (manifestURL && manifestURL == msg.manifestURL) {
-          // Let's dispatch an "additionallanguageschange" event on the document.
-          let doc = this._window.document;
-          let event = doc.createEvent("CustomEvent");
-          event.initCustomEvent("additionallanguageschange", true, true,
-                                Cu.cloneInto(msg.languages, this._window));
-          doc.dispatchEvent(event);
-        }
-        break;
-      case "Webapps:GetLocalizationResource:Return":
-        this.removeMessageListeners(["Webapps:GetLocalizationResource:Return"]);
-        if (msg.error) {
-          req.reject(new this._window.DOMError(msg.error));
-        } else {
-          req.resolve(Cu.cloneInto(msg.data, this._window));
-        }
-        break;
     }
     this.removeRequest(msg.requestID);
   },
 
   _getOrigin: function(aURL) {
     let uri = Services.io.newURI(aURL, null, null);
     return uri.prePath;
   },
@@ -253,97 +226,46 @@ WebappsRegistry.prototype = {
         : this._window.DOMApplicationsManager._create(this._window, mgmt.wrappedJSObject);
     }
     return this._mgmt;
   },
 
   uninit: function() {
     this._mgmt = null;
     cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
-                          ["Webapps:Install:Return:OK",
-                           "Webapps:AdditionalLanguageChange"]);
+                          ["Webapps:Install:Return:OK"]);
   },
 
   installPackage: function(aURL, aParams) {
     let request = this.createRequest();
 
     let uri = this._validateURL(aURL, request);
 
     if (uri && this._ensureForeground(request)) {
       this.addMessageListeners("Webapps:Install:Return:KO");
       cpmm.sendAsyncMessage("Webapps:InstallPackage",
                             this._prepareInstall(uri, request, aParams, true));
     }
 
     return request;
   },
 
-  _getCurrentAppManifestURL: function() {
-    let appId = this._window.document.nodePrincipal.appId;
-    if (appId === Ci.nsIScriptSecurityManager.NO_APP_ID) {
-      return null;
-    }
-
-    return appsService.getManifestURLByLocalId(appId);
-  },
-
-  getAdditionalLanguages: function() {
-    let manifestURL = AppsUtils.getAppManifestURLFromWindow(this._window);
-
-    return new this._window.Promise((aResolve, aReject) => {
-      if (!manifestURL) {
-        aReject("NotInApp");
-      } else {
-        let langs = DOMApplicationRegistry.getAdditionalLanguages(manifestURL);
-        aResolve(Cu.cloneInto(langs, this._window));
-      }
-    });
-  },
-
-  getLocalizationResource: function(aLanguage, aVersion, aPath, aType) {
-    let manifestURL = AppsUtils.getAppManifestURLFromWindow(this._window);
-
-    if (!manifestURL) {
-      return new Promise((aResolve, aReject) => {
-        aReject("NotInApp");
-      });
-    }
-
-    this.addMessageListeners(["Webapps:GetLocalizationResource:Return"]);
-    return this.createPromise((aResolve, aReject) => {
-      cpmm.sendAsyncMessage("Webapps:GetLocalizationResource", {
-        manifestURL: manifestURL,
-        lang: aLanguage,
-        version: aVersion,
-        path: aPath,
-        dataType: aType,
-        oid: this._id,
-        requestID: this.getPromiseResolverId({
-          resolve: aResolve,
-          reject: aReject
-        })
-      });
-    });
-  },
-
   // nsIDOMGlobalPropertyInitializer implementation
   init: function(aWindow) {
     const prefs = new Preferences();
 
     this._window = aWindow;
 
-    this.initDOMRequestHelper(aWindow, ["Webapps:Install:Return:OK",
-                                        "Webapps:AdditionalLanguageChange"]);
+    this.initDOMRequestHelper(aWindow, "Webapps:Install:Return:OK");
 
     let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindowUtils);
     this._id = util.outerWindowID;
     cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
-                          { messages: ["Webapps:Install:Return:OK",
-                                       "Webapps:AdditionalLanguageChange"]});
+                          { messages: ["Webapps:Install:Return:OK"]});
 
     let principal = aWindow.document.nodePrincipal;
     let appId = principal.appId;
     let app = appId && appsService.getAppByLocalId(appId);
 
     let isCurrentHomescreen = app &&
       app.manifestURL == prefs.get("dom.mozApps.homescreenURL") &&
       app.appStatus != Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED;
--- a/dom/apps/Webapps.jsm
+++ b/dom/apps/Webapps.jsm
@@ -76,19 +76,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   "resource://gre/modules/WebappOSUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
   "resource://gre/modules/NetUtil.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ScriptPreloader",
                                   "resource://gre/modules/ScriptPreloader.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "Langpacks",
-                                  "resource://gre/modules/Langpacks.jsm");
-
 XPCOMUtils.defineLazyModuleGetter(this, "TrustedHostedAppsUtils",
                                   "resource://gre/modules/TrustedHostedAppsUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ImportExport",
                                   "resource://gre/modules/ImportExport.jsm");
 
 #ifdef MOZ_WIDGET_GONK
 XPCOMUtils.defineLazyGetter(this, "libcutils", function() {
@@ -241,19 +238,16 @@ this.DOMApplicationRegistry = {
     Services.obs.addObserver(this, "memory-pressure", false);
 
     AppDownloadManager.registerCancelFunction(this.cancelDownload.bind(this));
 
     this.appsFile = FileUtils.getFile(DIRECTORY_NAME,
                                       ["webapps", "webapps.json"], true).path;
 
     this.loadAndUpdateApps();
-
-    Langpacks.registerRegistryFunctions(this.broadcastMessage.bind(this),
-                                        this._appIdForManifestURL.bind(this));
   },
 
   // loads the current registry, that could be empty on first run.
   loadCurrentRegistry: function() {
     return AppsUtils.loadJSONAsync(this.appsFile).then((aData) => {
       if (!aData) {
         return;
       }
@@ -425,17 +419,16 @@ this.DOMApplicationRegistry = {
         let localeManifest = new ManifestHelper(aResult.manifest, app.origin, app.manifestURL);
         this._saveWidgetsFullPath(localeManifest, app);
 
         if (app.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
           app.redirects = this.sanitizeRedirects(aResult.redirects);
         }
         app.kind = this.appKind(app, aResult.manifest);
         UserCustomizations.register(aResult.manifest, app);
-        Langpacks.register(app, aResult.manifest);
       });
 
       // Nothing else to do but notifying we're ready.
       this.notifyAppsRegistryReady();
     }
   }),
 
   updateDataStoreForApp: Task.async(function*(aId) {
@@ -1151,17 +1144,16 @@ this.DOMApplicationRegistry = {
         if (app.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
           app.redirects = this.sanitizeRedirects(manifest.redirects);
         }
         app.kind = this.appKind(app, aResult.manifest);
         this._registerSystemMessages(manifest, app);
         this._registerInterAppConnections(manifest, app);
         appsToRegister.push({ manifest: manifest, app: app });
         UserCustomizations.register(manifest, app);
-        Langpacks.register(app, manifest);
       });
       this._safeToClone.resolve();
       this._registerActivitiesForApps(appsToRegister, aRunUpdate);
     });
   },
 
   observe: function(aSubject, aTopic, aData) {
     if (aTopic == "xpcom-shutdown") {
@@ -1523,18 +1515,16 @@ this.DOMApplicationRegistry = {
 
     let res = {};
     let done = false;
 
     // We allow cloning the registry when the local processing has been done.
     this.safeToClone.then( () => {
       for (let id in this.webapps) {
         tmp.push({ id: id });
-        this.webapps[id].additionalLanguages =
-          Langpacks.getAdditionalLanguages(this.webapps[id].manifestURL).langs;
       }
       this._readManifests(tmp).then(
         function(manifests) {
           manifests.forEach((item) => {
             res[item.id] = item.manifest;
           });
           done = true;
         }
@@ -1969,20 +1959,16 @@ this.DOMApplicationRegistry = {
       }
       delete app.staged;
     }
 
     delete app.retryingDownload;
 
     // Update the asm.js scripts we need to compile.
     yield ScriptPreloader.preload(app, newManifest);
-
-    // Update langpack information.
-    Langpacks.register(app, newManifest);
-
     yield this._saveApps();
     // Update the handlers and permissions for this app.
     this.updateAppHandlers(oldManifest, newManifest, app);
 
     let updateManifest = yield AppsUtils.loadJSONAsync(staged.path);
     let appObject = AppsUtils.cloneAppObject(app);
     appObject.updateManifest = updateManifest;
     this.notifyUpdateHandlers(appObject, newManifest, appFile.path);
@@ -2090,23 +2076,21 @@ this.DOMApplicationRegistry = {
       this._registerSystemMessages(aNewManifest, aApp);
       this._registerActivities(aNewManifest, aApp, true);
       this._registerInterAppConnections(aNewManifest, aApp);
     } else {
       // Nothing else to do but notifying we're ready.
       this.notifyAppsRegistryReady();
     }
 
-    // Update user customizations and langpacks.
+    // Update user customizations.
     if (aOldManifest) {
       UserCustomizations.unregister(aOldManifest, aApp);
-      Langpacks.unregister(aApp, aOldManifest);
     }
     UserCustomizations.register(aNewManifest, aApp);
-    Langpacks.register(aApp, aNewManifest);
   },
 
   checkForUpdate: function(aData, aMm) {
     debug("checkForUpdate for " + aData.manifestURL);
 
     function sendError(aError) {
       debug("checkForUpdate error " + aError);
       aData.error = aError;
@@ -3196,19 +3180,16 @@ this.DOMApplicationRegistry = {
       app: app,
       manifest: aManifest,
       manifestURL: aNewApp.manifestURL
     });
 
     // Check if we have asm.js code to preload for this application.
     yield ScriptPreloader.preload(aNewApp, aManifest);
 
-    // Update langpack information.
-    yield Langpacks.register(aNewApp, aManifest);
-
     this.broadcastMessage("Webapps:FireEvent", {
       eventType: ["downloadsuccess", "downloadapplied"],
       manifestURL: aNewApp.manifestURL
     });
   }),
 
   _nextLocalId: function() {
     let id = Services.prefs.getIntPref("dom.mozApps.maxLocalId") + 1;
@@ -4108,17 +4089,16 @@ this.DOMApplicationRegistry = {
 
     // Then notify observers.
     Services.obs.notifyObservers(null, "webapps-uninstall", JSON.stringify(aApp));
 
     if (supportSystemMessages()) {
       this._unregisterActivities(aApp.manifest, aApp);
     }
     UserCustomizations.unregister(aApp.manifest, aApp);
-    Langpacks.unregister(aApp, aApp.manifest);
 
     let dir = this._getAppDir(id);
     try {
       dir.remove(true);
     } catch (e) {}
 
     delete this.webapps[id];
 
--- a/dom/apps/moz.build
+++ b/dom/apps/moz.build
@@ -29,17 +29,16 @@ EXTRA_COMPONENTS += [
     'Webapps.manifest',
 ]
 
 EXTRA_JS_MODULES += [
     'AppDownloadManager.jsm',
     'AppsServiceChild.jsm',
     'FreeSpaceWatcher.jsm',
     'InterAppCommService.jsm',
-    'Langpacks.jsm',
     'OfflineCacheInstaller.jsm',
     'PermissionsInstaller.jsm',
     'PermissionsTable.jsm',
     'StoreTrustAnchor.jsm',
     'UserCustomizations.jsm',
 ]
 
 EXTRA_PP_JS_MODULES += [
deleted file mode 100644
--- a/dom/apps/tests/langpack/event.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <title>Langpack Test : event</title>
-    <script>
-var baseURL = "http://mochi.test:8888/tests/dom/apps/tests/langpack/";
-var eventCount = 0;
-
-function languageChanged(evt) {
-  eventCount++;
-  alert(JSON.stringify(evt.detail));
-  if (eventCount == 1) {
-    var req = navigator.mozApps.install(baseURL + "lang2.webapp");
-  }
-}
-
-// Set up the event handler, and install an app.
-function run() {
-  document.addEventListener("additionallanguageschange", languageChanged);
-
-  navigator.mozApps.install(baseURL + "lang1.webapp");
-}
-    </script>
-  </head>
-  <body onload="run()">
-    <h1>Langpack Test : event</h1>
-  </body>
-</html>
\ No newline at end of file
deleted file mode 100644
--- a/dom/apps/tests/langpack/fr/app.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{ "hello" : "Bonjour" }
\ No newline at end of file
deleted file mode 100644
--- a/dom/apps/tests/langpack/fr/app.properties
+++ /dev/null
@@ -1,1 +0,0 @@
-hello=Bonjour
\ No newline at end of file
deleted file mode 100644
--- a/dom/apps/tests/langpack/index.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <title>Langpack Test : getAdditionalLanguages()</title>
-    <script>
-function run() {
-  navigator.mozApps.getAdditionalLanguages().then(languages => {
-    alert(JSON.stringify(languages));
-  });
-}
-    </script>
-  </head>
-  <body onload="run()">
-    <h1>Langpack Test : getAdditionalLanguages()</h1>
-  </body>
-</html>
\ No newline at end of file
deleted file mode 100644
--- a/dom/apps/tests/langpack/lang1.webapp
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "name": "French locale",
-  "languages-target" : { "app://*.gaiamobile.org/manifest.webapp": "2.2" },
-  "languages-provided": {
-    "fr": {
-      "version": 201411051234,
-      "name": "Français",
-      "apps": {
-        "http://mochi.test:8888/tests/dom/apps/tests/langpack/manifest.webapp": "tests/dom/apps/tests/langpack/fr/"
-       }
-     }
-   },
-   "role" : "langpack"
-}
deleted file mode 100644
--- a/dom/apps/tests/langpack/lang1.webapp^headers^
+++ /dev/null
@@ -1,1 +0,0 @@
-Content-Type: application/manifest+json
\ No newline at end of file
deleted file mode 100644
--- a/dom/apps/tests/langpack/lang2.webapp
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "name": "German an Polish locales",
-  "languages-target" : { "app://*.gaiamobile.org/manifest.webapp": "2.2" },
-  "languages-provided": {
-    "de": {
-      "version": 201411051234,
-      "name": "Deutsch",
-      "apps": {
-        "http://mochi.test:8888/tests/dom/apps/tests/langpack/manifest.webapp": "tests/dom/apps/tests/langpack/de/"
-       }
-     },
-     "pl": {
-      "version": 201411051234,
-      "name": "Polski",
-      "apps": {
-        "http://mochi.test:8888/tests/dom/apps/tests/langpack/manifest.webapp": "tests/dom/apps/tests/langpack/pl/"
-       }
-     }
-   },
-   "role" : "langpack"
-}
deleted file mode 100644
--- a/dom/apps/tests/langpack/lang2.webapp^headers^
+++ /dev/null
@@ -1,1 +0,0 @@
-Content-Type: application/manifest+json
\ No newline at end of file
deleted file mode 100644
--- a/dom/apps/tests/langpack/manifest.webapp
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "name": "Localization test app"
-}
deleted file mode 100644
--- a/dom/apps/tests/langpack/manifest.webapp^headers^
+++ /dev/null
@@ -1,1 +0,0 @@
-Content-Type: application/manifest+json
\ No newline at end of file
deleted file mode 100644
--- a/dom/apps/tests/langpack/resources.html
+++ /dev/null
@@ -1,92 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <title>Langpack Test : resources</title>
-    <script>
-function success(data) {
-  return new Promise(function(resolve, reject) {
-    if (typeof data === "object") {
-      // Read what's inside the blob.
-      var reader = new FileReader();
-      reader.onload = function(e) {
-        alert(e.target.result);
-        resolve();
-      };
-      reader.readAsText(data);
-    } else {
-      alert(data);
-      resolve();
-    }
-  });
-}
-
-function successJSON(data) {
-  return new Promise(function(resolve, reject) {
-    alert(JSON.stringify(data));
-    resolve();
-  });
-}
-
-function error(domError) {
-  return new Promise(function(resolve, reject) {
-    alert(domError.name);
-    resolve();
-  });
-}
-
-// Error: Bad resource.
-function test1() {
-  return navigator.mozApps.getLocalizationResource("fr", "2.2", "./foo.html", "binary")
-                          .then(success, error);
-}
-
-// Error: Unknown locale.
-function test2() {
-  return navigator.mozApps.getLocalizationResource("es", "2.2", "./foo.html", "binary")
-                          .then(success, error);
-}
-
-// Error: Bad version.
-function test3() {
-  return navigator.mozApps.getLocalizationResource("fr", "2.0", "./foo.html", "binary")
-                          .then(success, error);
-}
-
-// Error: Absolute url.
-function test4() {
-  return navigator.mozApps.getLocalizationResource("fr", "2.2", "http://example.com/foo.html", "binary")
-                          .then(success, error);
-}
-
-// Ok, binary data.
-function test5() {
-  return navigator.mozApps.getLocalizationResource("fr", "2.2", "./app.properties", "binary")
-                          .then(success, error);
-}
-
-// Ok, text data.
-function test6() {
-  return navigator.mozApps.getLocalizationResource("fr", "2.2", "./app.properties", "text")
-                          .then(success, error);
-}
-
-// Ok, json data.
-function test7() {
-  return navigator.mozApps.getLocalizationResource("fr", "2.2", "./app.json", "json")
-                          .then(successJSON, error);
-}
-
-function run() {
-  test1().then(test2)
-         .then(test3)
-         .then(test4)
-         .then(test5)
-         .then(test6)
-         .then(test7);
-}
-    </script>
-  </head>
-  <body onload="run()">
-    <h1>Langpack Test : resources</h1>
-  </body>
-</html>
\ No newline at end of file
--- a/dom/apps/tests/mochitest.ini
+++ b/dom/apps/tests/mochitest.ini
@@ -17,34 +17,32 @@ support-files =
   file_trusted_app.template.webapp
   file_invalidWidget_app.template.webapp
   file_packaged_app.sjs
   file_packaged_app.template.html
   file_packaged_app.template.webapp
   file_widget_app.template.webapp
   file_widget_app.template.html
   file_test_widget.js
-  langpack/*
   signed_app.sjs
   signed_app_template.webapp
   signed/*
   test_packaged_app_common.js
   marketplace/*
   pkg_install_iframe.html
 
 [test_app_addons.html]
 skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app
 [test_app_enabled.html]
 [test_app_update.html]
 skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app
 [test_bug_795164.html]
 [test_import_export.html]
 [test_install_multiple_apps_origin.html]
 [test_install_receipts.html]
-[test_langpacks.html]
 [test_marketplace_pkg_install.html]
 skip-if = buildapp == "b2g" || toolkit == "android" # see bug 989806
 [test_packaged_app_install.html]
 skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
 [test_packaged_app_update.html]
 skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
 [test_receipt_operations.html]
 [test_signed_pkg_install.html]
deleted file mode 100644
--- a/dom/apps/tests/test_langpacks.html
+++ /dev/null
@@ -1,221 +0,0 @@
-<!DOCTYPE HTML><!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1108096
--->
-<html>
-  <head>
-  <meta charset="utf-8">
-  <title>Test for Bug 1108096 - Langpack support</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" />
-  <script type="application/javascript;version=1.7">
-/**
-  * Test for Bug 1108096
-  * This file covers testing langpacks.
-  *
-  * The setup is as follows:
-  * - app is the localizable application.
-  * - langpack1 provides the French locale.
-  * - langpack2 provides the German and Polish locales.
-  */
-
-SimpleTest.waitForExplicitFinish();
-
-const uriPrefix = "http://mochi.test:8888/tests/dom/apps/tests/langpack/";
-
-let appManifestURL = uriPrefix + "manifest.webapp";
-let lang1ManifestURL = uriPrefix + "lang1.webapp";
-let lang2ManifestURL = uriPrefix + "lang2.webapp";
-
-let gGenerator = runTest();
-
-function go() {
-  gGenerator.next();
-}
-
-function continueTest() {
-  try {
-    gGenerator.next();
-  } catch (e if e instanceof StopIteration) {
-    SimpleTest.finish();
-  }
-}
-
-function mozAppsError() {
-  ok(false, "mozApps error: " + this.error.name);
-  SimpleTest.finish();
-}
-
-// Triggers one navigation test to the given page.
-// Waits for alert() messages before tearing down the iframe.
-function openPage(pageURL, messages) {
-  info("Navigating to " + pageURL);
-  let ifr = document.createElement("iframe");
-  let listener = function(event) {
-    let message = messages.shift();
-    is(event.detail.message, message, "Checking alert message for " + pageURL);
-    if (messages.length == 0) {
-      ifr.removeEventListener("mozbrowsershowmodalprompt", listener);
-      ifr.parentNode.removeChild(ifr);
-      continueTest();
-    }
-  }
-
-  ifr.addEventListener("mozbrowsershowmodalprompt", listener, false);
-
-  // Open the app url in an iframe.
-  ifr.setAttribute("mozapp", appManifestURL);
-  ifr.setAttribute("mozbrowser", "true");
-  ifr.setAttribute("src", uriPrefix + pageURL);
-  document.getElementById("container").appendChild(ifr);
-}
-
-let apps = [];
-
-function installApp(manifestURL) {
-  info("About to install app at " + manifestURL);
-  let req = navigator.mozApps.install(manifestURL);
-  req.onsuccess = function() {
-    is(req.result.manifestURL, manifestURL, "app installed");
-    if (req.result.installState == "installed") {
-      is(req.result.installState, "installed", "app downloaded");
-      continueTest();
-    } else {
-      req.result.ondownloadapplied = function() {
-        is(req.result.installState, "installed", "app downloaded");
-        continueTest();
-      }
-    }
-  }
-  req.onerror = mozAppsError;
-}
-
-function runTest() {
-  // Set up.
-  SpecialPowers.setAllAppsLaunchable(true);
-  SpecialPowers.pushPrefEnv({'set': [
-    ["dom.mozBrowserFramesEnabled", true],
-    ["dom.apps.allow_unsigned_langpacks", true] ]},continueTest);
-  yield undefined;
-
-  SpecialPowers.pushPermissions(
-    [{ "type": "webapps-manage", "allow": 1, "context": document },
-     { "type": "embed-apps", "allow": 1, "context": document },
-     { "type": "browser", "allow": 1, "context": document } ],
-    continueTest);
-  yield undefined;
-
-  navigator.mozApps.mgmt.oninstall = function(evt) {
-    apps.push(evt.application);
-  };
-
-  let _ = JSON.stringify;
-
-  SpecialPowers.autoConfirmAppInstall(continueTest);
-  yield undefined;
-
-  SpecialPowers.autoConfirmAppUninstall(continueTest);
-  yield undefined;
-
-  // Install test app.
-  installApp(appManifestURL);
-  yield undefined;
-
-  // Opens the iframe to the test page, initial state.
-  // No locale is available.
-  openPage("index.html", [_({})]);
-  yield undefined;
-
-  // Install the fr langpack.
-  installApp(lang1ManifestURL);
-  yield undefined;
-
-  // Opens the iframe to the test page.
-  // Only the French locale is available.
-  openPage("index.html",
-    [_({"fr":[{"version":201411051234,"name":"Français","target":"2.2"}]})]);
-  yield undefined;
-
-  // Install the de and pl langpack.
-  installApp(lang2ManifestURL);
-  yield undefined;
-
-  // Opens the iframe to the test page.
-  // French, German and Polish locales are available.
-  openPage("index.html",
-    [_({"fr":[{"version":201411051234,"name":"Français","target":"2.2"}],"de":[{"version":201411051234,"name":"Deutsch","target":"2.2"}],"pl":[{"version":201411051234,"name":"Polski","target":"2.2"}]})]);
-  yield undefined;
-
-  // Uninstall the second langpack.
-  {
-    let app = apps.pop();
-    info("Uninstalling " + app.manifestURL);
-    req = navigator.mozApps.mgmt.uninstall(app);
-    req.onsuccess = continueTest;
-    req.onerror = mozAppsError;
-    yield undefined;
-  }
-
-  // Opens the iframe to the test page.
-  // Only the French locale is available.
-  openPage("index.html",
-    [_({"fr":[{"version":201411051234,"name":"Français","target":"2.2"}]})]);
-  yield undefined;
-
-  // Uninstall the first langpack.
-  {
-    let app = apps.pop();
-    info("Uninstalling " + app.manifestURL);
-    req = navigator.mozApps.mgmt.uninstall(app);
-    req.onsuccess = continueTest;
-    req.onerror = mozAppsError;
-    yield undefined;
-  }
-
-  // Opens the iframe to the test page, initial state.
-  // No locale is available.
-  openPage("index.html",
-    ["{}"]);
-  yield undefined;
-
-  // Opens the iframe to the event test page.
-  // Will get additionallanguageschange events.
-  openPage("event.html",
-    [_({"fr":[{"version":201411051234,"name":"Français","target":"2.2"}]}),
-     _({"fr":[{"version":201411051234,"name":"Français","target":"2.2"}],"de":[{"version":201411051234,"name":"Deutsch","target":"2.2"}]}),
-     _({"fr":[{"version":201411051234,"name":"Français","target":"2.2"}],"de":[{"version":201411051234,"name":"Deutsch","target":"2.2"}],"pl":[{"version":201411051234,"name":"Polski","target":"2.2"}]})]);
-  yield undefined;
-
-  // Opens the iframe to the resource test page.
-  openPage("resources.html",
-    ["UnavailableResource",
-     "UnavailableLanguage",
-     "UnavailableVersion",
-     "BadUrl",
-     "hello=Bonjour",
-     "hello=Bonjour",
-     _({"hello":"Bonjour"})]);
-  yield undefined;
-
-  // Clean up after ourselves by uninstalling apps.
-  info(apps.length + " applications to uninstall.");
-  while (apps.length) {
-    let app = apps.pop();
-    req = navigator.mozApps.mgmt.uninstall(app);
-    req.onsuccess = continueTest;
-    req.onerror = mozAppsError;
-    yield undefined;
-  }
-}
-
-  </script>
-  </head>
-<body onload="go()">
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-</pre>
-<div id="container"></div>
-</body>
-</html>
--- a/dom/tests/mochitest/webapps/test_list_api.xul
+++ b/dom/tests/mochitest/webapps/test_list_api.xul
@@ -15,19 +15,17 @@
   <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=741549"
      target="_blank">Mozilla Bug 741549</a>
   </body>
 
 <script>
 
 var props = {
   checkInstalled: "function",
-  getAdditionalLanguages: "function",
   getInstalled: "function",
-  getLocalizationResource: "function",
   getSelf: "function",
   install: "function",
   installPackage: "function",
   mgmt: "object",
 };
 
 isDeeply([p for (p in navigator.mozApps)].sort(), Object.keys(props).sort(),
          "navigator.mozApps has only the expected properties");
--- a/dom/webidl/Apps.webidl
+++ b/dom/webidl/Apps.webidl
@@ -4,49 +4,26 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 dictionary InstallParameters {
   sequence<DOMString> receipts = [];
   sequence<DOMString> categories = [];
 };
 
-dictionary LanguageDesc {
-  DOMString target;
-  DOMString version;
-  DOMString name;
-};
-
-enum LocaleResourceType {
-  "binary",
-  "json",
-  "text"
-};
-
 [NoInterfaceObject, NavigatorProperty="mozApps",
  JSImplementation="@mozilla.org/webapps;1"]
 interface DOMApplicationsRegistry {
   [CheckPermissions="webapps-manage"]
   readonly attribute DOMApplicationsManager mgmt;
   DOMRequest install(DOMString url, optional InstallParameters params);
   DOMRequest installPackage(DOMString url, optional InstallParameters params);
   DOMRequest getSelf();
   DOMRequest getInstalled();
   DOMRequest checkInstalled(DOMString manifestUrl);
-
-  // Language pack API.
-  // These promises will be rejected if the page is not in an app context,
-  // i.e. they are implicitely acting on getSelf().
-  Promise<MozMap<sequence<LanguageDesc>>> getAdditionalLanguages();
-  // Resolves to a different object depending on the dataType value.
-  Promise<any>
-    getLocalizationResource(DOMString language,
-                            DOMString version,
-                            DOMString path,
-                            LocaleResourceType dataType);
 };
 
 [JSImplementation="@mozilla.org/webapps/application;1", ChromeOnly]
 interface DOMApplication : EventTarget {
   // manifest and updateManifest will be turned into dictionaries once
   // in bug 1053033 once bug 963382 is fixed.
   readonly attribute any manifest;
   readonly attribute any updateManifest;
@@ -89,28 +66,28 @@ interface DOMApplication : EventTarget {
   DOMRequest checkForUpdate();
 
   /**
    * Inter-App Communication APIs.
    *
    * https://wiki.mozilla.org/WebAPI/Inter_App_Communication_Alt_proposal
    *
    */
-  Promise<MozInterAppConnection> connect(DOMString keyword, optional any rules);
+   Promise<MozInterAppConnection> connect(DOMString keyword, optional any rules);
 
-  Promise<sequence<MozInterAppMessagePort>> getConnections();
+   Promise<sequence<MozInterAppMessagePort>> getConnections();
 
-  // Receipts handling functions.
-  DOMRequest addReceipt(optional DOMString receipt);
-  DOMRequest removeReceipt(optional DOMString receipt);
-  DOMRequest replaceReceipt(optional DOMString oldReceipt,
-                            optional DOMString newReceipt);
+    // Receipts handling functions.
+    DOMRequest addReceipt(optional DOMString receipt);
+    DOMRequest removeReceipt(optional DOMString receipt);
+    DOMRequest replaceReceipt(optional DOMString oldReceipt,
+                              optional DOMString newReceipt);
 
-  // Export this app as a shareable Blob.
-  Promise<Blob> export();
+    // Export this app as a shareable Blob.
+    Promise<Blob> export();
 };
 
 [JSImplementation="@mozilla.org/webapps/manager;1",
  ChromeOnly,
  CheckPermissions="webapps-manage"]
 interface DOMApplicationsManager : EventTarget {
   DOMRequest getAll();
   DOMRequest getNotInstalled();