Bug 1024513 - JavaScript Error: "NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS: [JavaScript Error: "targetElement is null" r=smaug a=2.0+
☠☠ backed out by 94047c419c3f ☠ ☠
authorFabrice Desré <fabrice@mozilla.com>
Mon, 07 Jul 2014 21:45:23 -0700
changeset 208858 49ae43e813ce83b2bbabfda702078361d82f8cc8
parent 208857 4cf4838bd5e1907e15e4354da76a94aca3604c17
child 208859 94047c419c3f81b9054d56d3256e855fcef58fdf
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, 2
bugs1024513
milestone32.0a2
Bug 1024513 - JavaScript Error: "NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS: [JavaScript Error: "targetElement is null" r=smaug a=2.0+
b2g/chrome/content/shell.js
dom/base/nsContentPermissionHelper.cpp
dom/base/nsContentPermissionHelper.h
dom/base/nsDOMWindowUtils.cpp
dom/contacts/ContactManager.js
dom/contacts/tests/shared.js
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/ipc/PCOMContentPermissionRequestChild.h
dom/media/MediaPermissionGonk.cpp
dom/permission/PermissionPromptHelper.jsm
dom/permission/moz.build
mobile/android/chrome/content/WebappRT.js
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -4,17 +4,16 @@
  * 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/. */
 
 Cu.import('resource://gre/modules/ContactService.jsm');
 Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
 Cu.import('resource://gre/modules/DataStoreChangeNotifier.jsm');
 Cu.import('resource://gre/modules/AlarmService.jsm');
 Cu.import('resource://gre/modules/ActivitiesService.jsm');
-Cu.import('resource://gre/modules/PermissionPromptHelper.jsm');
 Cu.import('resource://gre/modules/NotificationDB.jsm');
 Cu.import('resource://gre/modules/Payment.jsm');
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 Cu.import('resource://gre/modules/UserAgentOverrides.jsm');
 Cu.import('resource://gre/modules/Keyboard.jsm');
 Cu.import('resource://gre/modules/ErrorPage.jsm');
 Cu.import('resource://gre/modules/AlertsHelper.jsm');
 #ifdef MOZ_WIDGET_GONK
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -8,16 +8,17 @@
 #endif // MOZ_WIDGET_GONK
 #include "nsCOMPtr.h"
 #include "nsIDOMElement.h"
 #include "nsIPrincipal.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/PContentPermission.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/PContentPermissionRequestParent.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/unused.h"
 #include "nsComponentManagerUtils.h"
 #include "nsArrayUtils.h"
 #include "nsIMutableArray.h"
 #include "nsContentPermissionHelper.h"
 #include "nsCxPusher.h"
 #include "nsJSUtils.h"
@@ -351,8 +352,134 @@ nsContentPermissionRequestProxy::Allow(J
     MOZ_ASSERT(false, "SelectedChoices should be undefined or an JS object");
     return NS_ERROR_FAILURE;
   }
 
   unused << ContentPermissionRequestParent::Send__delete__(mParent, true, choices);
   mParent = nullptr;
   return NS_OK;
 }
+
+// RemotePermissionRequest
+
+// static
+uint32_t
+RemotePermissionRequest::ConvertArrayToPermissionRequest(
+                                nsIArray* aSrcArray,
+                                nsTArray<PermissionRequest>& aDesArray)
+{
+  uint32_t len = 0;
+  aSrcArray->GetLength(&len);
+  for (uint32_t i = 0; i < len; i++) {
+    nsCOMPtr<nsIContentPermissionType> cpt = do_QueryElementAt(aSrcArray, i);
+    nsAutoCString type;
+    nsAutoCString access;
+    cpt->GetType(type);
+    cpt->GetAccess(access);
+
+    nsCOMPtr<nsIArray> optionArray;
+    cpt->GetOptions(getter_AddRefs(optionArray));
+    uint32_t optionsLength = 0;
+    if (optionArray) {
+      optionArray->GetLength(&optionsLength);
+    }
+    nsTArray<nsString> options;
+    for (uint32_t j = 0; j < optionsLength; ++j) {
+      nsCOMPtr<nsISupportsString> isupportsString = do_QueryElementAt(optionArray, j);
+      if (isupportsString) {
+        nsString option;
+        isupportsString->GetData(option);
+        options.AppendElement(option);
+      }
+    }
+
+    aDesArray.AppendElement(PermissionRequest(type, access, options));
+  }
+  return len;
+}
+
+NS_IMPL_ISUPPORTS(RemotePermissionRequest, nsIContentPermissionRequest)
+
+RemotePermissionRequest::RemotePermissionRequest(
+  nsIContentPermissionRequest* aRequest,
+  nsPIDOMWindow* aWindow)
+  : mRequest(aRequest)
+  , mWindow(aWindow)
+{
+}
+
+// nsIContentPermissionRequest methods
+NS_IMETHODIMP
+RemotePermissionRequest::GetTypes(nsIArray** aTypes)
+{
+  NS_ASSERTION(mRequest, "We need a request");
+  return mRequest->GetTypes(aTypes);
+}
+
+NS_IMETHODIMP
+RemotePermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
+{
+  NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
+
+  return mRequest->GetPrincipal(aRequestingPrincipal);
+}
+
+NS_IMETHODIMP
+RemotePermissionRequest::GetWindow(nsIDOMWindow** aRequestingWindow)
+{
+  NS_ENSURE_ARG_POINTER(aRequestingWindow);
+
+  return mRequest->GetWindow(aRequestingWindow);
+}
+
+NS_IMETHODIMP
+RemotePermissionRequest::GetElement(nsIDOMElement** aRequestingElement)
+{
+  NS_ENSURE_ARG_POINTER(aRequestingElement);
+  *aRequestingElement = nullptr;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+RemotePermissionRequest::Cancel()
+{
+  NS_ASSERTION(mRequest, "We need a request");
+  return mRequest->Cancel();
+}
+
+NS_IMETHODIMP
+RemotePermissionRequest::Allow(JS::HandleValue aChoices)
+{
+  NS_ASSERTION(mRequest, "We need a request");
+  return mRequest->Allow(aChoices);
+}
+
+// PCOMContentPermissionRequestChild
+bool
+RemotePermissionRequest::Recv__delete__(const bool& aAllow,
+                                        const nsTArray<PermissionChoice>& aChoices)
+{
+  if (aAllow && mWindow->IsCurrentInnerWindow()) {
+    // Convert choices to a JS val if any.
+    // {"type1": "choice1", "type2": "choiceA"}
+    AutoJSAPI jsapi;
+    if (NS_WARN_IF(!jsapi.Init(mWindow))) {
+      return true; // This is not an IPC error.
+    }
+    JSContext* cx = jsapi.cx();
+    JS::Rooted<JSObject*> obj(cx);
+    obj = JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr());
+    for (uint32_t i = 0; i < aChoices.Length(); ++i) {
+      const nsString& choice = aChoices[i].choice();
+      const nsCString& type = aChoices[i].type();
+      JS::Rooted<JSString*> jChoice(cx, JS_NewUCStringCopyN(cx, choice.get(), choice.Length()));
+      JS::Rooted<JS::Value> vChoice(cx, StringValue(jChoice));
+      if (!JS_SetProperty(cx, obj, type.get(), vChoice)) {
+        return false;
+      }
+    }
+    JS::RootedValue val(cx, JS::ObjectValue(*obj));
+    (void) Allow(val);
+  } else {
+    (void) Cancel();
+  }
+  return true;
+}
--- a/dom/base/nsContentPermissionHelper.h
+++ b/dom/base/nsContentPermissionHelper.h
@@ -3,17 +3,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsContentPermissionHelper_h
 #define nsContentPermissionHelper_h
 
 #include "nsIContentPermissionPrompt.h"
 #include "nsTArray.h"
 #include "nsIMutableArray.h"
+#include "PCOMContentPermissionRequestChild.h"
 
+class nsPIDOMWindow;
 class nsContentPermissionRequestProxy;
 
 // Forward declare IPC::Principal here which is defined in
 // PermissionMessageUtils.h. Include this file will transitively includes
 // "windows.h" and it defines
 //   #define CreateEvent CreateEventW
 //   #define LoadImage LoadImageW
 // That will mess up windows build.
@@ -76,9 +78,37 @@ class nsContentPermissionRequestProxy : 
   void OnParentDestroyed();
 
  private:
   // Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
   mozilla::dom::ContentPermissionRequestParent* mParent;
   nsTArray<mozilla::dom::PermissionRequest> mPermissionRequests;
 };
 
+/**
++ * RemotePermissionRequest will send a prompt ipdl request to b2g process.
++ */
+class RemotePermissionRequest : public nsIContentPermissionRequest
+                              , public PCOMContentPermissionRequestChild
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICONTENTPERMISSIONREQUEST
+
+  RemotePermissionRequest(nsIContentPermissionRequest* aRequest,
+                          nsPIDOMWindow* aWindow);
+
+  // It will be called when prompt dismissed.
+  virtual bool Recv__delete__(const bool &aAllow,
+                              const nsTArray<PermissionChoice>& aChoices) MOZ_OVERRIDE;
+  virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
+
+  static uint32_t ConvertArrayToPermissionRequest(
+                                nsIArray* aSrcArray,
+                                nsTArray<PermissionRequest>& aDesArray);
+private:
+  virtual ~RemotePermissionRequest() {}
+
+  nsCOMPtr<nsIContentPermissionRequest> mRequest;
+  nsCOMPtr<nsPIDOMWindow>               mWindow;
+};
+
 #endif // nsContentPermissionHelper_h
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -65,16 +65,17 @@
 #include "mozilla/layers/ShadowLayers.h"
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FileHandle.h"
 #include "mozilla/dom/FileHandleBinding.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/IDBFactoryBinding.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
+#include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/quota/PersistenceType.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "nsDOMBlobBuilder.h"
 #include "nsPrintfCString.h"
 #include "nsViewportInfo.h"
 #include "nsIFormControl.h"
 #include "nsIScriptError.h"
 #include "nsIAppShell.h"
@@ -83,16 +84,17 @@
 #include "nsDisplayList.h"
 #include "nsROCSSPrimitiveValue.h"
 #include "nsIBaseWindow.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "GeckoProfiler.h"
 #include "mozilla/Preferences.h"
 #include "nsIContentIterator.h"
+#include "nsContentPermissionHelper.h"
 
 #ifdef XP_WIN
 #undef GetClassName
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
@@ -3781,16 +3783,59 @@ nsDOMWindowUtils::SetAudioVolume(float a
 
 NS_IMETHODIMP
 nsDOMWindowUtils::XpconnectArgument(nsIDOMWindowUtils* aThis)
 {
   // Do nothing.
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDOMWindowUtils::AskPermission(nsIContentPermissionRequest* aRequest)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  nsRefPtr<RemotePermissionRequest> req =
+    new RemotePermissionRequest(aRequest, window->GetCurrentInnerWindow());
+
+    // for content process
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    MOZ_ASSERT(NS_IsMainThread()); // IPC can only be execute on main thread.
+
+    dom::TabChild* child = dom::TabChild::GetFrom(window->GetDocShell());
+    NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
+
+    nsCOMPtr<nsIArray> typeArray;
+    nsresult rv = req->GetTypes(getter_AddRefs(typeArray));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsTArray<PermissionRequest> permArray;
+    RemotePermissionRequest::ConvertArrayToPermissionRequest(typeArray, permArray);
+
+    nsCOMPtr<nsIPrincipal> principal;
+    rv = req->GetPrincipal(getter_AddRefs(principal));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    req->AddRef();
+    child->SendPContentPermissionRequestConstructor(req,
+                                                    permArray,
+                                                    IPC::Principal(principal));
+
+    req->Sendprompt();
+    return NS_OK;
+  }
+
+  // for chrome process
+  nsCOMPtr<nsIContentPermissionPrompt> prompt =
+    do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
+  if (prompt) {
+    prompt->Prompt(req);
+  }
+  return NS_OK;
+}
+
 NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsTranslationNodeList)
 NS_IMPL_RELEASE(nsTranslationNodeList)
 
--- a/dom/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -180,29 +180,16 @@ ContactManager.prototype = {
         }
         break;
       case "Contacts:GetAll:Return:KO":
         req = this.getRequest(msg.requestID);
         if (req) {
           Services.DOMRequest.fireError(req.cursor, msg.errorMsg);
         }
         break;
-      case "PermissionPromptHelper:AskPermission:OK":
-        if (DEBUG) debug("id: " + msg.requestID);
-        req = this.getRequest(msg.requestID);
-        if (!req) {
-          break;
-        }
-
-        if (msg.result == Ci.nsIPermissionManager.ALLOW_ACTION) {
-          req.allow();
-        } else {
-          req.cancel();
-        }
-        break;
       case "Contact:Changed":
         // Fire oncontactchange event
         if (DEBUG) debug("Contacts:ContactChanged: " + msg.contactID + ", " + msg.reason);
         let event = new this._window.MozContactChangeEvent("contactchange", {
           contactID: msg.contactID,
           reason: msg.reason
         });
         this.dispatchEvent(event);
@@ -230,16 +217,17 @@ ContactManager.prototype = {
   dispatchEvent: function(event) {
     if (this.hasListenPermission) {
       this.__DOM_IMPL__.dispatchEvent(event);
     }
   },
 
   askPermission: function (aAccess, aRequest, aAllowCallback, aCancelCallback) {
     if (DEBUG) debug("askPermission for contacts");
+
     let access;
     switch(aAccess) {
       case "create":
         access = "create";
         break;
       case "update":
       case "remove":
         access = "write";
@@ -250,48 +238,52 @@ ContactManager.prototype = {
       case "count":
         access = "read";
         break;
       default:
         access = "unknown";
       }
 
     // Shortcut for ALLOW_ACTION so we avoid a parent roundtrip
+    let principal = this._window.document.nodePrincipal;
     let type = "contacts-" + access;
     let permValue =
-      Services.perms.testExactPermissionFromPrincipal(this._window.document.nodePrincipal, type);
+      Services.perms.testExactPermissionFromPrincipal(principal, type);
     if (permValue == Ci.nsIPermissionManager.ALLOW_ACTION) {
       aAllowCallback();
       return;
+    } else if (permValue == Ci.nsIPermissionManager.DENY_ACTION) {
+      aCancelCallback();
     }
 
-    let requestID = this.getRequestId({
-      request: aRequest,
-      allow: function() {
-        aAllowCallback();
-      }.bind(this),
-      cancel : function() {
-        if (aCancelCallback) {
-          aCancelCallback()
-        } else if (aRequest) {
-          Services.DOMRequest.fireError(aRequest, "Not Allowed");
-        }
-      }.bind(this)
-    });
-
-    let principal = this._window.document.nodePrincipal;
-    cpmm.sendAsyncMessage("PermissionPromptHelper:AskPermission", {
+    // Create an array with a single nsIContentPermissionType element.
+    let type = {
       type: "contacts",
       access: access,
-      requestID: requestID,
-      origin: principal.origin,
-      appID: principal.appId,
-      browserFlag: principal.isInBrowserElement,
-      windowID: this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID
-    });
+      options: null,
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionType])
+    };
+    let typeArray = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+    typeArray.appendElement(type, false);
+
+    // create a nsIContentPermissionRequest
+    let request = {
+      types: typeArray,
+      principal: principal,
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionRequest]),
+      allow: aAllowCallback,
+      cancel: aCancelCallback,
+      window: this._window
+    };
+
+    // Using askPermission from nsIDOMWindowUtils that takes care of the
+    // remoting if needed.
+    let windowUtils = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
+                          .getInterface(Ci.nsIDOMWindowUtils);
+    windowUtils.askPermission(request);
   },
 
   save: function save(aContact) {
     // We have to do a deep copy of the contact manually here because
     // nsFrameMessageManager doesn't know how to create a structured clone of a
     // mozContact object.
     let newContact = {properties: {}};
 
@@ -459,17 +451,16 @@ ContactManager.prototype = {
 
   init: function(aWindow) {
     // DOMRequestIpcHelper.initHelper sets this._window
     this.initDOMRequestHelper(aWindow, ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
                               "Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO",
                               "Contact:Save:Return:OK", "Contact:Save:Return:KO",
                               "Contact:Remove:Return:OK", "Contact:Remove:Return:KO",
                               "Contact:Changed",
-                              "PermissionPromptHelper:AskPermission:OK",
                               "Contacts:GetAll:Next", "Contacts:GetAll:Return:KO",
                               "Contacts:Count",
                               "Contacts:Revision", "Contacts:GetRevision:Return:KO",]);
 
 
     let allowCallback = function() {
       cpmm.sendAsyncMessage("Contacts:RegisterForMessages");
       this.hasListenPermission = true;
--- a/dom/contacts/tests/shared.js
+++ b/dom/contacts/tests/shared.js
@@ -1,14 +1,13 @@
 "use strict";
 
 // Fix the environment to run Contacts tests
 if (SpecialPowers.isMainProcess()) {
   SpecialPowers.Cu.import("resource://gre/modules/ContactService.jsm");
-  SpecialPowers.Cu.import("resource://gre/modules/PermissionPromptHelper.jsm");
 }
 
 SpecialPowers.addPermission("contacts-write", true, document);
 SpecialPowers.addPermission("contacts-read", true, document);
 SpecialPowers.addPermission("contacts-create", true, document);
 
 // Some helpful global vars
 var isAndroid = (navigator.userAgent.indexOf("Android") !== -1);
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -42,18 +42,19 @@ interface nsIDOMBlob;
 interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
 interface nsICompositionStringSynthesizer;
 interface nsITranslationNodeList;
+interface nsIContentPermissionRequest;
 
-[scriptable, uuid(8435ca79-517f-40ba-acd9-55201a2a119d)]
+[scriptable, uuid(ca202fa7-7b8f-4814-acc3-a8545f67320b)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1682,16 +1683,22 @@ interface nsIDOMWindowUtils : nsISupport
      */
     attribute float audioVolume;
 
     /**
      * This method doesn't do anything useful.  It was solely added for the
      * purpose of the test for bug 503926.
      */
     void xpconnectArgument(in nsIDOMWindowUtils aThis);
+
+    /**
+     * Helper for JS components that need to send permission requests with
+     * e10s support properly.
+     */
+     void askPermission(in nsIContentPermissionRequest aRequest);
 };
 
 [scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)]
 interface nsITranslationNodeList : nsISupports {
   readonly attribute unsigned long length;
   nsIDOMNode item(in unsigned long index);
 
   // A translation root is a block element, or an inline element
--- a/dom/ipc/PCOMContentPermissionRequestChild.h
+++ b/dom/ipc/PCOMContentPermissionRequestChild.h
@@ -5,16 +5,17 @@
 #ifndef PCOMContentPermissionRequestChild_h
 #define PCOMContentPermissionRequestChild_h
 
 #include "mozilla/dom/PContentPermissionRequestChild.h"
 // Microsoft's API Name hackery sucks
 // XXXbz Doing this in a header is a gigantic footgun.  See
 // https://bugzilla.mozilla.org/show_bug.cgi?id=932421#c3 for why.
 #undef CreateEvent
+#undef LoadImage
 
 /*
   PContentPermissionRequestChild implementations also are
   XPCOM objects.  Addref() is called on their implementation
   before SendPContentPermissionRequestConstructor is called.
   When Dealloc is called, IPDLRelease() is called.
   Implementations of this method are expected to call
   Release() on themselves.  See Bug 594261 for more
--- a/dom/media/MediaPermissionGonk.cpp
+++ b/dom/media/MediaPermissionGonk.cpp
@@ -30,48 +30,16 @@
 #define VIDEO_PERMISSION_NAME "video-capture"
 
 using namespace mozilla::dom;
 
 namespace mozilla {
 
 static MediaPermissionManager *gMediaPermMgr = nullptr;
 
-static uint32_t
-ConvertArrayToPermissionRequest(nsIArray* aSrcArray,
-                                nsTArray<PermissionRequest>& aDesArray)
-{
-  uint32_t len = 0;
-  aSrcArray->GetLength(&len);
-  for (uint32_t i = 0; i < len; i++) {
-    nsCOMPtr<nsIContentPermissionType> cpt = do_QueryElementAt(aSrcArray, i);
-    nsAutoCString type;
-    nsAutoCString access;
-    cpt->GetType(type);
-    cpt->GetAccess(access);
-
-    nsCOMPtr<nsIArray> optionArray;
-    cpt->GetOptions(getter_AddRefs(optionArray));
-    uint32_t optionsLength = 0;
-    optionArray->GetLength(&optionsLength);
-    nsTArray<nsString> options;
-    for (uint32_t j = 0; j < optionsLength; ++j) {
-      nsCOMPtr<nsISupportsString> isupportsString = do_QueryElementAt(optionArray, j);
-      if (isupportsString) {
-        nsString option;
-        isupportsString->GetData(option);
-        options.AppendElement(option);
-      }
-    }
-
-    aDesArray.AppendElement(PermissionRequest(type, access, options));
-  }
-  return len;
-}
-
 static void
 CreateDeviceNameList(nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices,
                      nsTArray<nsString> &aDeviceNameList)
 {
   for (uint32_t i = 0; i < aDevices.Length(); ++i) {
      nsString name;
      nsresult rv = aDevices[i]->GetName(name);
      NS_ENSURE_SUCCESS_VOID(rv);
@@ -440,17 +408,17 @@ MediaDeviceSuccessCallback::DoPrompt(nsR
     dom::TabChild* child = dom::TabChild::GetFrom(window->GetDocShell());
     NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
 
     nsCOMPtr<nsIArray> typeArray;
     rv = req->GetTypes(getter_AddRefs(typeArray));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsTArray<PermissionRequest> permArray;
-    ConvertArrayToPermissionRequest(typeArray, permArray);
+    RemotePermissionRequest::ConvertArrayToPermissionRequest(typeArray, permArray);
 
     nsCOMPtr<nsIPrincipal> principal;
     rv = req->GetPrincipal(getter_AddRefs(principal));
     NS_ENSURE_SUCCESS(rv, rv);
 
     req->AddRef();
     child->SendPContentPermissionRequestConstructor(req,
                                                     permArray,
deleted file mode 100644
--- a/dom/permission/PermissionPromptHelper.jsm
+++ /dev/null
@@ -1,146 +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/. */
-
-/* PermissionPromptHelper checks the permissionDB for a given permission
- * name and performs prompting if needed.
- * Usage: send PermissionPromptHelper:AskPermission via the FrameMessageManager with:
- * |origin|, |appID|, |browserFlag| -> used for getting the principal and
- * |type| and |access| to call testExactPermissionFromPrincipal.
- * Note that |access| isn't currently used.
- * Other arugments are:
- * requestID: ID that gets returned with the result message.
- *
- * Once the permission is checked, it returns with the message
- * "PermissionPromptHelper:AskPermission:OK"
- * The result contains the |result| e.g.Ci.nsIPermissionManager.ALLOW_ACTION
- * and a requestID that
- */
-
-"use strict";
-
-let DEBUG = 0;
-let debug;
-if (DEBUG)
-  debug = function (s) { dump("-*- Permission Prompt Helper component: " + s + "\n"); }
-else
-  debug = function (s) {}
-
-const Cu = Components.utils;
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-
-this.EXPORTED_SYMBOLS = ["PermissionPromptHelper"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
-                                   "@mozilla.org/parentprocessmessagemanager;1",
-                                   "nsIMessageListenerManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "permissionPromptService",
-                                   "@mozilla.org/permission-prompt-service;1",
-                                   "nsIPermissionPromptService");
-
-let appsService = Cc["@mozilla.org/AppsService;1"].getService(Ci.nsIAppsService);
-
-this.PermissionPromptHelper = {
-  init: function init() {
-    debug("Init");
-    ppmm.addMessageListener("PermissionPromptHelper:AskPermission", this);
-    Services.obs.addObserver(this, "profile-before-change", false);
-  },
-
-  askPermission: function askPermission(aMessage, aCallbacks) {
-    let msg = aMessage.json;
-
-    let access = msg.type;
-    if (msg.access) {
-      access = access + "-" + msg.access;
-    }
-
-    let uri = Services.io.newURI(msg.origin, null, null);
-    let principal =
-      Services.scriptSecurityManager.getAppCodebasePrincipal(uri, msg.appID, msg.browserFlag);
-
-    let permValue =
-      Services.perms.testExactPermissionFromPrincipal(principal, access);
-
-    if (permValue == Ci.nsIPermissionManager.DENY_ACTION ||
-        permValue == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
-      aCallbacks.cancel();
-      return;
-    }
-
-    if (permValue == Ci.nsIPermissionManager.PROMPT_ACTION) {
-
-      // create the options from permission request.
-      let options = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
-      if (msg.options) {
-        for (let option of options) {
-          options.appendElement(option);
-        }
-      }
-
-      // create an array with a nsIContentPermissionType element
-      let type = {
-        type: msg.type,
-        access: msg.access ? msg.access : "unused",
-        options: options,
-        QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionType])
-      };
-      let typeArray = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
-      typeArray.appendElement(type, false);
-
-      // create a nsIContentPermissionRequest
-      let request = {
-        types: typeArray,
-        principal: principal,
-        QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionRequest]),
-        allow: aCallbacks.allow,
-        cancel: aCallbacks.cancel,
-        window: Services.wm.getOuterWindowWithId(msg.windowID)
-      };
-
-      permissionPromptService.getPermission(request);
-      return;
-    }
-
-    if (permValue == Ci.nsIPermissionManager.ALLOW_ACTION) {
-      aCallbacks.allow();
-      return;
-    }
-  },
-
-  observe: function observe(aSubject, aTopic, aData) {
-    ppmm.removeMessageListener("PermissionPromptHelper:AskPermission", this);
-    Services.obs.removeObserver(this, "profile-before-change");
-    ppmm = null;
-  },
-
-  receiveMessage: function receiveMessage(aMessage) {
-    debug("PermissionPromptHelper::receiveMessage " + aMessage.name);
-    let mm = aMessage.target;
-    let msg = aMessage.data;
-
-    let result;
-    if (aMessage.name == "PermissionPromptHelper:AskPermission") {
-      this.askPermission(aMessage, {
-        cancel: function() {
-          mm.sendAsyncMessage("PermissionPromptHelper:AskPermission:OK",
-                              { result: Ci.nsIPermissionManager.DENY_ACTION,
-                                requestID: msg.requestID });
-        },
-        allow: function(aChoice) {
-          mm.sendAsyncMessage("PermissionPromptHelper:AskPermission:OK",
-                              { result: Ci.nsIPermissionManager.ALLOW_ACTION,
-                                choice: aChoice,
-                                requestID: msg.requestID });
-        }
-      });
-    }
-  }
-}
-
-PermissionPromptHelper.init();
--- a/dom/permission/moz.build
+++ b/dom/permission/moz.build
@@ -9,11 +9,10 @@ TEST_DIRS += ['tests']
 EXTRA_COMPONENTS += [
     'PermissionPromptService.js',
     'PermissionPromptService.manifest',
     'PermissionSettings.js',
     'PermissionSettings.manifest',
 ]
 
 EXTRA_JS_MODULES += [
-    'PermissionPromptHelper.jsm',
     'PermissionSettings.jsm',
 ]
--- a/mobile/android/chrome/content/WebappRT.js
+++ b/mobile/android/chrome/content/WebappRT.js
@@ -4,17 +4,16 @@
 let Cc = Components.classes;
 let Ci = Components.interfaces;
 let Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
-Cu.import("resource://gre/modules/PermissionPromptHelper.jsm");
 Cu.import("resource://gre/modules/ContactService.jsm");
 #ifdef MOZ_ANDROID_SYNTHAPKS
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Notifications", "resource://gre/modules/Notifications.jsm");
 #endif
 
 function pref(name, value) {