Bug 1045975 - Use nsIDOMWindowUtils.askPermission in all types of permission request. r=smaug
☠☠ backed out by fcedb0c795f7 ☠ ☠
authorShih-Chiang Chien <schien@mozilla.com>
Fri, 01 Aug 2014 15:22:20 +0800
changeset 198338 8b44017765ac721f3f3fe8420f5246a43d06e12c
parent 198337 827276e298e8691b2a99d755518f13d7b710ad5a
child 198339 596bd716d4f8dcb2f929b2d012aff0f831e3d357
push idunknown
push userunknown
push dateunknown
reviewerssmaug
bugs1045975
milestone34.0a1
Bug 1045975 - Use nsIDOMWindowUtils.askPermission in all types of permission request. r=smaug
content/base/src/nsDocument.cpp
dom/base/nsContentPermissionHelper.cpp
dom/base/nsContentPermissionHelper.h
dom/base/nsDOMWindowUtils.cpp
dom/camera/DOMCameraManager.cpp
dom/devicestorage/nsDeviceStorage.cpp
dom/devicestorage/nsDeviceStorage.h
dom/filesystem/FileSystemPermissionRequest.cpp
dom/filesystem/FileSystemPermissionRequest.h
dom/ipc/PCOMContentPermissionRequestChild.h
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/moz.build
dom/media/MediaPermissionGonk.cpp
dom/src/geolocation/nsGeolocation.cpp
dom/src/notification/DesktopNotification.cpp
dom/src/notification/Notification.cpp
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -11423,22 +11423,18 @@ public:
         doc->mCancelledPointerLockRequests > 2) {
       Handled();
       DispatchPointerLockError(d);
       return NS_OK;
     }
 
     // Handling a request from user input in non-fullscreen mode.
     // Do a normal permission check.
-    nsCOMPtr<nsIContentPermissionPrompt> prompt =
-      do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
-    if (prompt) {
-      prompt->Prompt(this);
-    }
-
+    nsCOMPtr<nsPIDOMWindow> window = doc->GetInnerWindow();
+    nsContentPermissionUtils::AskPermission(this, window);
     return NS_OK;
   }
 
   void Handled()
   {
     mElement = nullptr;
     mDocument = nullptr;
     if (gPendingPointerLockRequest == this) {
@@ -11457,20 +11453,20 @@ protected:
 NS_IMPL_ISUPPORTS_INHERITED(nsPointerLockPermissionRequest,
                             nsRunnable,
                             nsIContentPermissionRequest)
 
 NS_IMETHODIMP
 nsPointerLockPermissionRequest::GetTypes(nsIArray** aTypes)
 {
   nsTArray<nsString> emptyOptions;
-  return CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
-                               NS_LITERAL_CSTRING("unused"),
-                               emptyOptions,
-                               aTypes);
+  return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
+                                                         NS_LITERAL_CSTRING("unused"),
+                                                         emptyOptions,
+                                                         aTypes);
 }
 
 NS_IMETHODIMP
 nsPointerLockPermissionRequest::GetPrincipal(nsIPrincipal** aPrincipal)
 {
   nsCOMPtr<nsIDocument> d = do_QueryReferent(mDocument);
   if (d) {
     NS_ADDREF(*aPrincipal = d->NodePrincipal());
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -9,25 +9,27 @@
 #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/TabChild.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"
 #include "nsISupportsPrimitives.h"
+#include "nsServiceManagerUtils.h"
 
 using mozilla::unused;          // <snicker>
 using namespace mozilla::dom;
 using namespace mozilla;
 
 namespace mozilla {
 namespace dom {
 
@@ -148,55 +150,138 @@ ContentPermissionType::GetOptions(nsIArr
     rv = options->AppendElement(isupportsString, false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   NS_ADDREF(*aOptions = options);
   return NS_OK;
 }
 
-uint32_t
-ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
-                                nsIMutableArray* aDesArray)
+// nsContentPermissionUtils
+
+/* static */ uint32_t
+nsContentPermissionUtils::ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
+                                                          nsIMutableArray* aDesArray)
 {
   uint32_t len = aSrcArray.Length();
   for (uint32_t i = 0; i < len; i++) {
     nsRefPtr<ContentPermissionType> cpt =
       new ContentPermissionType(aSrcArray[i].type(),
                                 aSrcArray[i].access(),
                                 aSrcArray[i].options());
     aDesArray->AppendElement(cpt, false);
   }
   return len;
 }
 
-nsresult
-CreatePermissionArray(const nsACString& aType,
-                      const nsACString& aAccess,
-                      const nsTArray<nsString>& aOptions,
-                      nsIArray** aTypesArray)
+/* static */ uint32_t
+nsContentPermissionUtils::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;
+}
+
+
+/* static */ nsresult
+nsContentPermissionUtils::CreatePermissionArray(const nsACString& aType,
+                                                const nsACString& aAccess,
+                                                const nsTArray<nsString>& aOptions,
+                                                nsIArray** aTypesArray)
 {
   nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
   nsRefPtr<ContentPermissionType> permType = new ContentPermissionType(aType,
                                                                        aAccess,
                                                                        aOptions);
   types->AppendElement(permType, false);
   types.forget(aTypesArray);
 
   return NS_OK;
 }
 
-PContentPermissionRequestParent*
-CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
-                                     Element* element,
-                                     const IPC::Principal& principal)
+/* static */ PContentPermissionRequestParent*
+nsContentPermissionUtils::CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
+                                                               Element* element,
+                                                               const IPC::Principal& principal)
 {
   return new ContentPermissionRequestParent(aRequests, element, principal);
 }
 
+/* static */ nsresult
+nsContentPermissionUtils::AskPermission(nsIContentPermissionRequest* aRequest, nsPIDOMWindow* aWindow)
+{
+  MOZ_ASSERT(!aWindow || aWindow->IsInnerWindow());
+  NS_ENSURE_STATE(aWindow && aWindow->IsCurrentInnerWindow());
+
+  // for content process
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+
+    nsRefPtr<RemotePermissionRequest> req =
+      new RemotePermissionRequest(aRequest, aWindow);
+
+    MOZ_ASSERT(NS_IsMainThread()); // IPC can only be execute on main thread.
+
+    TabChild* child = TabChild::GetFrom(aWindow->GetDocShell());
+    NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
+
+    nsCOMPtr<nsIArray> typeArray;
+    nsresult rv = aRequest->GetTypes(getter_AddRefs(typeArray));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsTArray<PermissionRequest> permArray;
+    ConvertArrayToPermissionRequest(typeArray, permArray);
+
+    nsCOMPtr<nsIPrincipal> principal;
+    rv = aRequest->GetPrincipal(getter_AddRefs(principal));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    req->IPDLAddRef();
+    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(aRequest);
+  }
+  return NS_OK;
+}
+
 } // namespace dom
 } // namespace mozilla
 
 nsContentPermissionRequestProxy::nsContentPermissionRequestProxy()
 {
   MOZ_COUNT_CTOR(nsContentPermissionRequestProxy);
 }
 
@@ -208,17 +293,17 @@ nsContentPermissionRequestProxy::~nsCont
 nsresult
 nsContentPermissionRequestProxy::Init(const nsTArray<PermissionRequest>& requests,
                                       ContentPermissionRequestParent* parent)
 {
   NS_ASSERTION(parent, "null parent");
   mParent = parent;
   mPermissionRequests = requests;
 
-  nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
+  nsCOMPtr<nsIContentPermissionPrompt> prompt = do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
   if (!prompt) {
     return NS_ERROR_FAILURE;
   }
 
   prompt->Prompt(this);
   return NS_OK;
 }
 
@@ -229,17 +314,17 @@ nsContentPermissionRequestProxy::OnParen
 }
 
 NS_IMPL_ISUPPORTS(nsContentPermissionRequestProxy, nsIContentPermissionRequest)
 
 NS_IMETHODIMP
 nsContentPermissionRequestProxy::GetTypes(nsIArray** aTypes)
 {
   nsCOMPtr<nsIMutableArray> types = do_CreateInstance(NS_ARRAY_CONTRACTID);
-  if (ConvertPermissionRequestToArray(mPermissionRequests, types)) {
+  if (mozilla::dom::nsContentPermissionUtils::ConvertPermissionRequestToArray(mPermissionRequests, types)) {
     types.forget(aTypes);
     return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsContentPermissionRequestProxy::GetWindow(nsIDOMWindow * *aRequestingWindow)
@@ -357,131 +442,71 @@ nsContentPermissionRequestProxy::Allow(J
 
   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)
+NS_IMPL_ISUPPORTS0(RemotePermissionRequest)
 
 RemotePermissionRequest::RemotePermissionRequest(
   nsIContentPermissionRequest* aRequest,
   nsPIDOMWindow* aWindow)
   : mRequest(aRequest)
   , mWindow(aWindow)
+  , mIPCOpen(false)
 {
 }
 
-// nsIContentPermissionRequest methods
-NS_IMETHODIMP
-RemotePermissionRequest::GetTypes(nsIArray** aTypes)
+void
+RemotePermissionRequest::DoCancel()
 {
   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);
+  mRequest->Cancel();
 }
 
-NS_IMETHODIMP
-RemotePermissionRequest::GetElement(nsIDOMElement** aRequestingElement)
-{
-  NS_ENSURE_ARG_POINTER(aRequestingElement);
-  *aRequestingElement = nullptr;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-RemotePermissionRequest::Cancel()
+void
+RemotePermissionRequest::DoAllow(JS::HandleValue aChoices)
 {
   NS_ASSERTION(mRequest, "We need a request");
-  return mRequest->Cancel();
+  mRequest->Allow(aChoices);
 }
 
-NS_IMETHODIMP
-RemotePermissionRequest::Allow(JS::HandleValue aChoices)
-{
-  NS_ASSERTION(mRequest, "We need a request");
-  return mRequest->Allow(aChoices);
-}
-
-// PCOMContentPermissionRequestChild
+// PContentPermissionRequestChild
 bool
 RemotePermissionRequest::Recv__delete__(const bool& aAllow,
                                         const nsTArray<PermissionChoice>& aChoices)
 {
   if (aAllow && mWindow->IsCurrentInnerWindow()) {
+    // Use 'undefined' if no choice is provided.
+    if (aChoices.IsEmpty()) {
+      DoAllow(JS::UndefinedHandleValue);
+      return true;
+    }
+
     // 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);
+    DoAllow(val);
   } else {
-    (void) Cancel();
+    DoCancel();
   }
   return true;
 }
--- a/dom/base/nsContentPermissionHelper.h
+++ b/dom/base/nsContentPermissionHelper.h
@@ -3,17 +3,21 @@
  * 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"
+#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 LoadImage
 
 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
@@ -44,73 +48,101 @@ public:
 protected:
   virtual ~ContentPermissionType();
 
   nsCString mType;
   nsCString mAccess;
   nsTArray<nsString> mOptions;
 };
 
-uint32_t ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
-                                         nsIMutableArray* aDesArray);
+class nsContentPermissionUtils
+{
+public:
+  static uint32_t
+  ConvertPermissionRequestToArray(nsTArray<PermissionRequest>& aSrcArray,
+                                  nsIMutableArray* aDesArray);
+
+  static uint32_t
+  ConvertArrayToPermissionRequest(nsIArray* aSrcArray,
+                                  nsTArray<PermissionRequest>& aDesArray);
 
-nsresult CreatePermissionArray(const nsACString& aType,
-                               const nsACString& aAccess,
-                               const nsTArray<nsString>& aOptions,
-                               nsIArray** aTypesArray);
+  static nsresult
+  CreatePermissionArray(const nsACString& aType,
+                        const nsACString& aAccess,
+                        const nsTArray<nsString>& aOptions,
+                        nsIArray** aTypesArray);
 
-PContentPermissionRequestParent*
-CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
-                                     Element* element,
-                                     const IPC::Principal& principal);
+  static PContentPermissionRequestParent*
+  CreateContentPermissionRequestParent(const nsTArray<PermissionRequest>& aRequests,
+                                       Element* element,
+                                       const IPC::Principal& principal);
+
+  static nsresult
+  AskPermission(nsIContentPermissionRequest* aRequest, nsPIDOMWindow* aWindow);
+};
 
 } // namespace dom
 } // namespace mozilla
 
 class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
 {
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
 
   nsContentPermissionRequestProxy();
 
   nsresult Init(const nsTArray<mozilla::dom::PermissionRequest>& requests,
                 mozilla::dom::ContentPermissionRequestParent* parent);
+
   void OnParentDestroyed();
 
  private:
   virtual ~nsContentPermissionRequestProxy();
 
   // 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
+class RemotePermissionRequest MOZ_FINAL : public nsISupports
+                                        , public mozilla::dom::PContentPermissionRequestChild
 {
 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(); }
+
+  void IPDLAddRef()
+  {
+    mIPCOpen = true;
+    AddRef();
+  }
 
-  static uint32_t ConvertArrayToPermissionRequest(
-                                nsIArray* aSrcArray,
-                                nsTArray<PermissionRequest>& aDesArray);
+  void IPDLRelease()
+  {
+    mIPCOpen = false;
+    Release();
+  }
+
 private:
-  virtual ~RemotePermissionRequest() {}
+  virtual ~RemotePermissionRequest()
+  {
+    MOZ_ASSERT(!mIPCOpen, "Protocol must not be open when RemotePermissionRequest is destroyed.");
+  }
+
+  void DoAllow(JS::HandleValue aChoices);
+  void DoCancel();
 
   nsCOMPtr<nsIContentPermissionRequest> mRequest;
   nsCOMPtr<nsPIDOMWindow>               mWindow;
+  bool                                  mIPCOpen;
 };
 
 #endif // nsContentPermissionHelper_h
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -3851,53 +3851,17 @@ nsDOMWindowUtils::XpconnectArgument(nsID
   // 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;
+  return nsContentPermissionUtils::AskPermission(aRequest, window->GetCurrentInnerWindow());
 }
 
 NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsTranslationNodeList)
--- a/dom/camera/DOMCameraManager.cpp
+++ b/dom/camera/DOMCameraManager.cpp
@@ -4,26 +4,26 @@
 
 #include "DOMCameraManager.h"
 #include "nsDebug.h"
 #include "jsapi.h"
 #include "Navigator.h"
 #include "nsPIDOMWindow.h"
 #include "mozilla/Services.h"
 #include "nsContentPermissionHelper.h"
+#include "nsIContentPermissionPrompt.h"
 #include "nsIObserverService.h"
 #include "nsIPermissionManager.h"
+#include "nsIScriptObjectPrincipal.h"
 #include "DOMCameraControl.h"
 #include "nsDOMClassInfo.h"
 #include "CameraCommon.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/CameraManagerBinding.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
-#include "mozilla/dom/TabChild.h"
-#include "PCOMContentPermissionRequestChild.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsDOMCameraManager, mWindow)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCameraManager)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
@@ -117,17 +117,16 @@ nsDOMCameraManager::CreateInstance(nsPID
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   obs->AddObserver(cameraManager, "xpcom-shutdown", true);
 
   return cameraManager.forget();
 }
 
 class CameraPermissionRequest : public nsIContentPermissionRequest
-                              , public PCOMContentPermissionRequestChild
                               , public nsIRunnable
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
   NS_DECL_NSIRUNNABLE
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(CameraPermissionRequest,
                                            nsIContentPermissionRequest)
@@ -144,24 +143,16 @@ public:
     , mCameraManager(aManager)
     , mCameraId(aCameraId)
     , mInitialConfig(aInitialConfig)
     , mOnSuccess(aOnSuccess)
     , mOnError(aOnError)
   {
   }
 
-  bool Recv__delete__(const bool& aAllow,
-                      const InfallibleTArray<PermissionChoice>& choices);
-
-  void IPDLRelease()
-  {
-    Release();
-  }
-
 protected:
   virtual ~CameraPermissionRequest()
   {
   }
 
   nsresult DispatchCallback(uint32_t aPermission);
   void CallAllow();
   void CallCancel();
@@ -183,58 +174,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(CameraPermissionRequest)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(CameraPermissionRequest)
 
 NS_IMETHODIMP
 CameraPermissionRequest::Run()
 {
-  if (XRE_GetProcessType() == GeckoProcessType_Content) {
-    TabChild* child = TabChild::GetFrom(mWindow->GetDocShell());
-    if (!child) {
-      return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    // Retain a reference so the object isn't deleted without IPDL's knowledge.
-    // Corresponding release occurs in DeallocPContentPermissionRequest.
-    AddRef();
-
-    nsTArray<PermissionRequest> permArray;
-    nsTArray<nsString> emptyOptions;
-    permArray.AppendElement(PermissionRequest(
-                            NS_LITERAL_CSTRING("camera"),
-                            NS_LITERAL_CSTRING("unused"),
-                            emptyOptions));
-    child->SendPContentPermissionRequestConstructor(this, permArray,
-                                                    IPC::Principal(mPrincipal));
-
-    Sendprompt();
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIContentPermissionPrompt> prompt =
-    do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
-  if (prompt) {
-    prompt->Prompt(this);
-  }
-
-  return NS_OK;
-}
-
-bool
-CameraPermissionRequest::Recv__delete__(const bool& aAllow,
-                                        const InfallibleTArray<PermissionChoice>& choices)
-{
-  if (aAllow) {
-    Allow(JS::UndefinedHandleValue);
-  } else {
-    Cancel();
-  }
-  return true;
+  return nsContentPermissionUtils::AskPermission(this, mWindow);
 }
 
 NS_IMETHODIMP
 CameraPermissionRequest::GetPrincipal(nsIPrincipal** aRequestingPrincipal)
 {
   NS_ADDREF(*aRequestingPrincipal = mPrincipal);
   return NS_OK;
 }
@@ -289,20 +239,20 @@ CameraPermissionRequest::CallCancel()
 {
   mCameraManager->PermissionCancelled(mCameraId, mInitialConfig, mOnSuccess, mOnError);
 }
 
 NS_IMETHODIMP
 CameraPermissionRequest::GetTypes(nsIArray** aTypes)
 {
   nsTArray<nsString> emptyOptions;
-  return CreatePermissionArray(NS_LITERAL_CSTRING("camera"),
-                               NS_LITERAL_CSTRING("unused"),
-                               emptyOptions,
-                               aTypes);
+  return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("camera"),
+                                                         NS_LITERAL_CSTRING("unused"),
+                                                         emptyOptions,
+                                                         aTypes);
 }
 
 void
 nsDOMCameraManager::GetCamera(const nsAString& aCamera,
                               const CameraConfiguration& aInitialConfig,
                               GetCameraCallback& aOnSuccess,
                               const OptionalNonNullCameraErrorCallback& aOnError,
                               ErrorResult& aRv)
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -13,17 +13,16 @@
 #include "mozilla/dom/DeviceStorageBinding.h"
 #include "mozilla/dom/DeviceStorageChangeEvent.h"
 #include "mozilla/dom/DeviceStorageFileSystem.h"
 #include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
 #include "mozilla/dom/Directory.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/ipc/Blob.h"
 #include "mozilla/dom/PBrowserChild.h"
-#include "mozilla/dom/PContentPermissionRequestChild.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/LazyIdleThread.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Scoped.h"
@@ -41,17 +40,16 @@
 #include "nsDOMBlobBuilder.h"
 #include "nsNetUtil.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIPrincipal.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "nsXULAppAPI.h"
-#include "TabChild.h"
 #include "DeviceStorageFileDescriptor.h"
 #include "DeviceStorageRequestChild.h"
 #include "nsCRT.h"
 #include "nsIObserverService.h"
 #include "nsIMIMEService.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIPermissionManager.h"
 #include "nsIStringBundle.h"
@@ -1780,46 +1778,27 @@ StringToJsval(nsPIDOMWindow* aWindow, ns
     return false;
   }
 
   return true;
 }
 
 class DeviceStorageCursorRequest MOZ_FINAL
   : public nsIContentPermissionRequest
-  , public PCOMContentPermissionRequestChild
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DeviceStorageCursorRequest,
                                            nsIContentPermissionRequest)
 
   NS_FORWARD_NSICONTENTPERMISSIONREQUEST(mCursor->);
 
   DeviceStorageCursorRequest(nsDOMDeviceStorageCursor* aCursor)
     : mCursor(aCursor) { }
 
-  bool Recv__delete__(const bool& allow,
-                      const InfallibleTArray<PermissionChoice>& choices)
-  {
-    MOZ_ASSERT(choices.IsEmpty(), "DeviceStorageCursor doesn't support permission choice");
-    if (allow) {
-      Allow(JS::UndefinedHandleValue);
-    }
-    else {
-      Cancel();
-    }
-    return true;
-  }
-
-  void IPDLRelease()
-  {
-    Release();
-  }
-
 private:
   ~DeviceStorageCursorRequest() {}
 
   nsRefPtr<nsDOMDeviceStorageCursor> mCursor;
 };
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeviceStorageCursorRequest)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentPermissionRequest)
@@ -2044,20 +2023,20 @@ NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetTypes(nsIArray** aTypes)
 {
   nsCString type;
   nsresult rv =
     DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsTArray<nsString> emptyOptions;
-  return CreatePermissionArray(type,
-                               NS_LITERAL_CSTRING("read"),
-                               emptyOptions,
-                               aTypes);
+  return nsContentPermissionUtils::CreatePermissionArray(type,
+                                                         NS_LITERAL_CSTRING("read"),
+                                                         emptyOptions,
+                                                         aTypes);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
 {
   NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
   return NS_OK;
 }
@@ -2132,37 +2111,16 @@ nsDOMDeviceStorageCursor::Continue(Error
   }
 
   nsRefPtr<ContinueCursorEvent> event = new ContinueCursorEvent(this);
   event->Continue();
 
   mOkToCallContinue = false;
 }
 
-bool
-nsDOMDeviceStorageCursor::Recv__delete__(const bool& allow,
-                                         const InfallibleTArray<PermissionChoice>& choices)
-{
-  MOZ_ASSERT(choices.IsEmpty(), "DeviceStorageCursor doesn't support permission choice");
-
-  if (allow) {
-    Allow(JS::UndefinedHandleValue);
-  }
-  else {
-    Cancel();
-  }
-  return true;
-}
-
-void
-nsDOMDeviceStorageCursor::IPDLRelease()
-{
-  Release();
-}
-
 void
 nsDOMDeviceStorageCursor::RequestComplete()
 {
   MOZ_ASSERT(!mOkToCallContinue);
   mOkToCallContinue = true;
 }
 
 class PostAvailableResultEvent : public nsRunnable
@@ -2701,17 +2659,16 @@ public:
 private:
   nsRefPtr<DeviceStorageFile> mFile;
   nsRefPtr<DOMRequest> mRequest;
 };
 
 class DeviceStorageRequest MOZ_FINAL
   : public nsIContentPermissionRequest
   , public nsIRunnable
-  , public PCOMContentPermissionRequestChild
 {
 public:
 
   DeviceStorageRequest(const DeviceStorageRequestType aRequestType,
                        nsPIDOMWindow* aWindow,
                        nsIPrincipal* aPrincipal,
                        DeviceStorageFile* aFile,
                        DOMRequest* aRequest,
@@ -2769,66 +2726,26 @@ public:
     MOZ_ASSERT(mRequest);
     MOZ_ASSERT(mDSFileDescriptor);
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DeviceStorageRequest,
                                            nsIContentPermissionRequest)
 
-  NS_IMETHOD Run() {
+  NS_IMETHOD Run()
+  {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) {
       Allow(JS::UndefinedHandleValue);
       return NS_OK;
     }
 
-    if (XRE_GetProcessType() == GeckoProcessType_Content) {
-
-      // because owner implements nsITabChild, we can assume that it is
-      // the one and only TabChild.
-      TabChild* child = TabChild::GetFrom(mWindow->GetDocShell());
-      if (!child) {
-        return NS_OK;
-      }
-
-      // Retain a reference so the object isn't deleted without IPDL's
-      // knowledge. Corresponding release occurs in
-      // DeallocPContentPermissionRequest.
-      AddRef();
-
-      nsCString type;
-      nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(
-        mFile->mStorageType, type);
-      if (NS_FAILED(rv)) {
-        return rv;
-      }
-      nsCString access;
-      rv = DeviceStorageTypeChecker::GetAccessForRequest(
-        DeviceStorageRequestType(mRequestType), access);
-      if (NS_FAILED(rv)) {
-        return rv;
-      }
-      nsTArray<PermissionRequest> permArray;
-      nsTArray<nsString> emptyOptions;
-      permArray.AppendElement(PermissionRequest(type, access, emptyOptions));
-      child->SendPContentPermissionRequestConstructor(
-        this, permArray, IPC::Principal(mPrincipal));
-
-      Sendprompt();
-      return NS_OK;
-    }
-
-    nsCOMPtr<nsIContentPermissionPrompt> prompt
-      = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
-    if (prompt) {
-      prompt->Prompt(this);
-    }
-    return NS_OK;
+    return nsContentPermissionUtils::AskPermission(this, mWindow);
   }
 
   NS_IMETHODIMP GetTypes(nsIArray** aTypes)
   {
     nsCString type;
     nsresult rv =
       DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
     if (NS_FAILED(rv)) {
@@ -2838,17 +2755,17 @@ public:
     nsCString access;
     rv = DeviceStorageTypeChecker::GetAccessForRequest(
       DeviceStorageRequestType(mRequestType), access);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     nsTArray<nsString> emptyOptions;
-    return CreatePermissionArray(type, access, emptyOptions, aTypes);
+    return nsContentPermissionUtils::CreatePermissionArray(type, access, emptyOptions, aTypes);
   }
 
   NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
   {
     NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
     return NS_OK;
   }
 
@@ -3203,35 +3120,16 @@ public:
         = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
       MOZ_ASSERT(target);
       target->Dispatch(r, NS_DISPATCH_NORMAL);
     }
 
     return NS_OK;
   }
 
-  bool Recv__delete__(const bool& allow,
-                      const InfallibleTArray<PermissionChoice>& choices)
-  {
-    MOZ_ASSERT(choices.IsEmpty(), "DeviceStorage doesn't support permission choice");
-
-    if (allow) {
-      Allow(JS::UndefinedHandleValue);
-    }
-    else {
-      Cancel();
-    }
-    return true;
-  }
-
-  void IPDLRelease()
-  {
-    Release();
-  }
-
 private:
   ~DeviceStorageRequest() {}
 
   int32_t mRequestType;
   nsCOMPtr<nsPIDOMWindow> mWindow;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsRefPtr<DeviceStorageFile> mFile;
 
@@ -4227,52 +4125,17 @@ nsDOMDeviceStorage::EnumerateInternal(co
   nsRefPtr<DeviceStorageCursorRequest> r
     = new DeviceStorageCursorRequest(cursor);
 
   if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) {
     r->Allow(JS::UndefinedHandleValue);
     return cursor.forget();
   }
 
-  if (XRE_GetProcessType() == GeckoProcessType_Content) {
-    // because owner implements nsITabChild, we can assume that it is
-    // the one and only TabChild.
-    TabChild* child = TabChild::GetFrom(win->GetDocShell());
-    if (!child) {
-      return cursor.forget();
-    }
-
-    // Retain a reference so the object isn't deleted without IPDL's knowledge.
-    // Corresponding release occurs in DeallocPContentPermissionRequest.
-    r->AddRef();
-
-    nsCString type;
-    aRv = DeviceStorageTypeChecker::GetPermissionForType(mStorageType, type);
-    if (aRv.Failed()) {
-      return nullptr;
-    }
-    nsTArray<PermissionRequest> permArray;
-    nsTArray<nsString> emptyOptions;
-    permArray.AppendElement(PermissionRequest(type,
-                                              NS_LITERAL_CSTRING("read"),
-                                              emptyOptions));
-    child->SendPContentPermissionRequestConstructor(r,
-                                                    permArray,
-                                                    IPC::Principal(mPrincipal));
-
-    r->Sendprompt();
-
-    return cursor.forget();
-  }
-
-  nsCOMPtr<nsIContentPermissionPrompt> prompt
-    = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
-  if (prompt) {
-    prompt->Prompt(r);
-  }
+  nsContentPermissionUtils::AskPermission(r, win);
 
   return cursor.forget();
 }
 
 #ifdef MOZ_WIDGET_GONK
 void
 nsDOMDeviceStorage::DispatchStatusChangeEvent(nsAString& aStatus)
 {
--- a/dom/devicestorage/nsDeviceStorage.h
+++ b/dom/devicestorage/nsDeviceStorage.h
@@ -2,17 +2,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/. */
 
 #ifndef nsDeviceStorage_h
 #define nsDeviceStorage_h
 
 class nsPIDOMWindow;
 #include "mozilla/Attributes.h"
-#include "PCOMContentPermissionRequestChild.h"
 
 #include "DOMRequest.h"
 #include "DOMCursor.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIClassInfo.h"
 #include "nsIContentPermissionPrompt.h"
@@ -186,17 +185,16 @@ public:
 private:
   already_AddRefed<DeviceStorageFile> GetNextFile();
   nsRefPtr<mozilla::dom::DOMRequest> mRequest;
 };
 
 class nsDOMDeviceStorageCursor MOZ_FINAL
   : public mozilla::dom::DOMCursor
   , public nsIContentPermissionRequest
-  , public PCOMContentPermissionRequestChild
   , public mozilla::dom::devicestorage::DeviceStorageRequestChildCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSICONTENTPERMISSIONREQUEST
   NS_FORWARD_NSIDOMDOMCURSOR(mozilla::dom::DOMCursor::)
 
   // DOMCursor
@@ -207,20 +205,16 @@ public:
                            DeviceStorageFile* aFile,
                            PRTime aSince);
 
 
   nsTArray<nsRefPtr<DeviceStorageFile> > mFiles;
   bool mOkToCallContinue;
   PRTime mSince;
 
-  virtual bool Recv__delete__(const bool& allow,
-                              const InfallibleTArray<PermissionChoice>& choices) MOZ_OVERRIDE;
-  virtual void IPDLRelease() MOZ_OVERRIDE;
-
   void GetStorageType(nsAString & aType);
 
   void RequestComplete() MOZ_OVERRIDE;
 
 private:
   ~nsDOMDeviceStorageCursor();
 
   nsRefPtr<DeviceStorageFile> mFile;
--- a/dom/filesystem/FileSystemPermissionRequest.cpp
+++ b/dom/filesystem/FileSystemPermissionRequest.cpp
@@ -3,20 +3,19 @@
 /* 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/. */
 #include "FileSystemPermissionRequest.h"
 
 #include "mozilla/dom/FileSystemBase.h"
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "mozilla/dom/FileSystemUtils.h"
-#include "mozilla/dom/TabChild.h"
 #include "nsIDocument.h"
 #include "nsPIDOMWindow.h"
-#include "nsString.h"
+#include "nsContentPermissionHelper.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_ISUPPORTS(FileSystemPermissionRequest, nsIRunnable, nsIContentPermissionRequest)
 
 // static
 void
@@ -57,44 +56,24 @@ FileSystemPermissionRequest::FileSystemP
 
   mPrincipal = doc->NodePrincipal();
 }
 
 FileSystemPermissionRequest::~FileSystemPermissionRequest()
 {
 }
 
-bool
-FileSystemPermissionRequest::Recv__delete__(const bool& aAllow,
-               const InfallibleTArray<PermissionChoice>& aChoices)
-{
-  MOZ_ASSERT(aChoices.IsEmpty(),
-             "FileSystemPermissionRequest doesn't support permission choice");
-  if (aAllow) {
-    Allow(JS::UndefinedHandleValue);
-  } else {
-    Cancel();
-  }
-  return true;
-}
-
-void
-FileSystemPermissionRequest::IPDLRelease()
-{
-  Release();
-}
-
 NS_IMETHODIMP
 FileSystemPermissionRequest::GetTypes(nsIArray** aTypes)
 {
   nsTArray<nsString> emptyOptions;
-  return CreatePermissionArray(mPermissionType,
-                               mPermissionAccess,
-                               emptyOptions,
-                               aTypes);
+  return nsContentPermissionUtils::CreatePermissionArray(mPermissionType,
+                                                         mPermissionAccess,
+                                                         emptyOptions,
+                                                         aTypes);
 }
 
 NS_IMETHODIMP
 FileSystemPermissionRequest::GetPrincipal(nsIPrincipal** aRequestingPrincipal)
 {
   NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
   return NS_OK;
 }
@@ -142,49 +121,19 @@ FileSystemPermissionRequest::Run()
     return NS_OK;
   }
 
   if (filesystem->IsTesting()) {
     Allow(JS::UndefinedHandleValue);
     return NS_OK;
   }
 
-  if (FileSystemUtils::IsParentProcess()) {
-    nsCOMPtr<nsIContentPermissionPrompt> prompt
-      = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
-    if (!prompt || NS_FAILED(prompt->Prompt(this))) {
-      Cancel();
-    }
-    return NS_OK;
-  }
-
   if (!mWindow) {
     Cancel();
     return NS_OK;
   }
 
-  // because owner implements nsITabChild, we can assume that it is
-  // the one and only TabChild.
-  TabChild* child = TabChild::GetFrom(mWindow->GetDocShell());
-  if (!child) {
-    Cancel();
-    return NS_OK;
-  }
-
-  // Retain a reference so the object isn't deleted without IPDL's
-  // knowledge. Corresponding release occurs in
-  // DeallocPContentPermissionRequest.
-  AddRef();
-
-  nsTArray<PermissionRequest> permArray;
-  nsTArray<nsString> emptyOptions;
-  permArray.AppendElement(PermissionRequest(mPermissionType,
-                                            mPermissionAccess,
-                                            emptyOptions));
-  child->SendPContentPermissionRequestConstructor(
-    this, permArray, IPC::Principal(mPrincipal));
-
-  Sendprompt();
+  nsContentPermissionUtils::AskPermission(this, mWindow);
   return NS_OK;
 }
 
 } /* namespace dom */
 } /* namespace mozilla */
--- a/dom/filesystem/FileSystemPermissionRequest.h
+++ b/dom/filesystem/FileSystemPermissionRequest.h
@@ -2,48 +2,37 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_FileSystemPermissionRequest_h
 #define mozilla_dom_FileSystemPermissionRequest_h
 
-#include "PCOMContentPermissionRequestChild.h"
 #include "nsAutoPtr.h"
-#include "nsContentPermissionHelper.h"
 #include "nsIRunnable.h"
+#include "nsIContentPermissionPrompt.h"
+#include "nsString.h"
 
-class nsCString;
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
 class FileSystemTaskBase;
 
 class FileSystemPermissionRequest MOZ_FINAL
   : public nsIContentPermissionRequest
   , public nsIRunnable
-  , public PCOMContentPermissionRequestChild
 {
 public:
   // Request permission for the given task.
   static void
   RequestForTask(FileSystemTaskBase* aTask);
 
-  // Overrides PCOMContentPermissionRequestChild
-
-  virtual void
-  IPDLRelease() MOZ_OVERRIDE;
-
-  bool
-  Recv__delete__(const bool& aAllow,
-    const InfallibleTArray<PermissionChoice>& aChoices) MOZ_OVERRIDE;
-
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
   NS_DECL_NSIRUNNABLE
 private:
   FileSystemPermissionRequest(FileSystemTaskBase* aTask);
 
   virtual
   ~FileSystemPermissionRequest();
deleted file mode 100644
--- a/dom/ipc/PCOMContentPermissionRequestChild.h
+++ /dev/null
@@ -1,38 +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/. */
-
-#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
-  information.
- */
-class PCOMContentPermissionRequestChild : public mozilla::dom::PContentPermissionRequestChild {
-public:
-  virtual void IPDLRelease() = 0;
-#ifdef DEBUG
-  PCOMContentPermissionRequestChild() : mIPCOpen(false) {}
-  virtual ~PCOMContentPermissionRequestChild() {
-    // mIPCOpen is set to true in TabChild::SendPContentPermissionRequestConstructor
-    // and set to false in TabChild::DeallocPContentPermissionRequest
-    MOZ_ASSERT(!mIPCOpen, "Protocol must not be open when PCOMContentPermissionRequestChild is destroyed.");
-  }
-  bool mIPCOpen;
-#endif /* DEBUG */
-};
-
-#endif
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -63,34 +63,30 @@
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsLayoutUtils.h"
 #include "nsPrintfCString.h"
 #include "nsThreadUtils.h"
 #include "nsWeakReference.h"
 #include "nsWindowWatcher.h"
 #include "PermissionMessageUtils.h"
-#include "PCOMContentPermissionRequestChild.h"
+#include "nsContentPermissionHelper.h"
 #include "PuppetWidget.h"
 #include "StructuredCloneUtils.h"
 #include "nsViewportInfo.h"
 #include "JavaScriptChild.h"
 #include "nsILoadContext.h"
 #include "ipc/nsGUIEventIPC.h"
 #include "mozilla/gfx/Matrix.h"
 #include "UnitTransforms.h"
 #include "ClientLayerManager.h"
 #include "LayersLogging.h"
 
 #include "nsColorPickerProxy.h"
 
-#ifdef DEBUG
-#include "PCOMContentPermissionRequestChild.h"
-#endif /* DEBUG */
-
 #define BROWSER_ELEMENT_CHILD_SCRIPT \
     NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
 
 #define TABC_LOG(...)
 // #define TABC_LOG(...) printf_stderr("TABC: " __VA_ARGS__)
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -1402,29 +1398,16 @@ TabChild::SendPendingTouchPreventedRespo
 {
   if (mPendingTouchPreventedResponse) {
     MOZ_ASSERT(aGuid == mPendingTouchPreventedGuid);
     SendContentReceivedTouch(mPendingTouchPreventedGuid, aPreventDefault);
     mPendingTouchPreventedResponse = false;
   }
 }
 
-#ifdef DEBUG
-PContentPermissionRequestChild*
-TabChild:: SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
-                                                    const InfallibleTArray<PermissionRequest>& aRequests,
-                                                    const IPC::Principal& aPrincipal)
-{
-  PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
-  PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aRequests, aPrincipal);
-  child->mIPCOpen = true;
-  return request;
-}
-#endif /* DEBUG */
-
 void
 TabChild::DestroyWindow()
 {
     nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
     if (baseWindow)
         baseWindow->Destroy();
 
     // NB: the order of mWidget->Destroy() and mRemoteFrame->Destroy()
@@ -2355,23 +2338,19 @@ TabChild::AllocPContentPermissionRequest
 {
   NS_RUNTIMEABORT("unused");
   return nullptr;
 }
 
 bool
 TabChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor)
 {
-    PCOMContentPermissionRequestChild* child =
-        static_cast<PCOMContentPermissionRequestChild*>(actor);
-#ifdef DEBUG
-    child->mIPCOpen = false;
-#endif /* DEBUG */
-    child->IPDLRelease();
-    return true;
+  RemotePermissionRequest* child = static_cast<RemotePermissionRequest*>(actor);
+  child->IPDLRelease();
+  return true;
 }
 
 PFilePickerChild*
 TabChild::AllocPFilePickerChild(const nsString&, const int16_t&)
 {
   NS_RUNTIMEABORT("unused");
   return nullptr;
 }
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -381,23 +381,16 @@ public:
                                                   const uint32_t& renderFlags,
                                                   const bool& flushLayout,
                                                   const nsIntSize& renderSize) MOZ_OVERRIDE;
 
     virtual PColorPickerChild*
     AllocPColorPickerChild(const nsString& title, const nsString& initialColor) MOZ_OVERRIDE;
     virtual bool DeallocPColorPickerChild(PColorPickerChild* actor) MOZ_OVERRIDE;
 
-#ifdef DEBUG
-    virtual PContentPermissionRequestChild*
-    SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
-                                             const InfallibleTArray<PermissionRequest>& aRequests,
-                                             const IPC::Principal& aPrincipal);
-#endif /* DEBUG */
-
     virtual PContentPermissionRequestChild*
     AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
                                         const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
     virtual bool
     DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor) MOZ_OVERRIDE;
 
     virtual PFilePickerChild*
     AllocPFilePickerChild(const nsString& aTitle, const int16_t& aMode) MOZ_OVERRIDE;
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -709,17 +709,17 @@ TabParent::DeallocPDocumentRendererParen
     delete actor;
     return true;
 }
 
 PContentPermissionRequestParent*
 TabParent::AllocPContentPermissionRequestParent(const InfallibleTArray<PermissionRequest>& aRequests,
                                                 const IPC::Principal& aPrincipal)
 {
-  return CreateContentPermissionRequestParent(aRequests, mFrameElement, aPrincipal);
+  return nsContentPermissionUtils::CreateContentPermissionRequestParent(aRequests, mFrameElement, aPrincipal);
 }
 
 bool
 TabParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor)
 {
   delete actor;
   return true;
 }
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -1,17 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS += [
     'nsICachedFileDescriptorListener.h',
-    'PCOMContentPermissionRequestChild.h',
 ]
 
 EXPORTS.mozilla.dom.ipc += [
     'Blob.h',
     'nsIRemoteBlob.h',
 ]
 
 EXPORTS.mozilla.dom += [
--- a/dom/media/MediaPermissionGonk.cpp
+++ b/dom/media/MediaPermissionGonk.cpp
@@ -11,19 +11,17 @@
 #include "nsIDocument.h"
 #include "nsIDOMNavigatorUserMedia.h"
 #include "nsIStringEnumerator.h"
 #include "nsISupportsArray.h"
 #include "nsJSUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsTArray.h"
 #include "GetUserMediaRequest.h"
-#include "PCOMContentPermissionRequestChild.h"
 #include "mozilla/dom/PBrowserChild.h"
-#include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "nsISupportsPrimitives.h"
 #include "nsServiceManagerUtils.h"
 #include "nsArrayUtils.h"
 #include "nsContentPermissionHelper.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 
 #define AUDIO_PERMISSION_NAME "audio-capture"
@@ -105,30 +103,24 @@ NotifyPermissionDeny(const nsAString &aC
 
 namespace {
 
 /**
  * MediaPermissionRequest will send a prompt ipdl request to b2g process according
  * to its owned type.
  */
 class MediaPermissionRequest : public nsIContentPermissionRequest
-                             , public PCOMContentPermissionRequestChild
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
 
   MediaPermissionRequest(nsRefPtr<dom::GetUserMediaRequest> &aRequest,
                          nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices);
 
-  // It will be called when prompt dismissed.
-  virtual bool Recv__delete__(const bool &allow,
-                              const InfallibleTArray<PermissionChoice>& choices) MOZ_OVERRIDE;
-  virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
-
   already_AddRefed<nsPIDOMWindow> GetOwner();
 
 protected:
   virtual ~MediaPermissionRequest() {}
 
 private:
   nsresult DoAllow(const nsString &audioDevice, const nsString &videoDevice);
 
@@ -311,39 +303,16 @@ MediaPermissionRequest::DoAllow(const ns
 already_AddRefed<nsPIDOMWindow>
 MediaPermissionRequest::GetOwner()
 {
   nsCOMPtr<nsPIDOMWindow> window = static_cast<nsPIDOMWindow*>
       (nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID()));
   return window.forget();
 }
 
-//PCOMContentPermissionRequestChild
-bool
-MediaPermissionRequest::Recv__delete__(const bool& allow,
-                                       const InfallibleTArray<PermissionChoice>& choices)
-{
-  if (allow) {
-    // get selected device name for audio and video
-    nsString audioDevice, videoDevice;
-    for (uint32_t i = 0; i < choices.Length(); ++i) {
-      const nsString &choice = choices[i].choice();
-      if (choices[i].type().EqualsLiteral(AUDIO_PERMISSION_NAME)) {
-        audioDevice = choice;
-      } else if (choices[i].type().EqualsLiteral(VIDEO_PERMISSION_NAME)) {
-        videoDevice = choice;
-      }
-    }
-    (void) DoAllow(audioDevice, videoDevice);
-  } else {
-    (void) Cancel();
-  }
-  return true;
-}
-
 // Success callback for MediaManager::GetUserMediaDevices().
 class MediaDeviceSuccessCallback: public nsIGetUserMediaDevicesSuccessCallback
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIGETUSERMEDIADEVICESSUCCESSCALLBACK
 
   MediaDeviceSuccessCallback(nsRefPtr<dom::GetUserMediaRequest> &aRequest)
@@ -395,55 +364,18 @@ MediaDeviceSuccessCallback::OnSuccess(ns
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 // Trigger permission prompt UI
 nsresult
 MediaDeviceSuccessCallback::DoPrompt(nsRefPtr<MediaPermissionRequest> &req)
 {
-  // for content process
-  if (XRE_GetProcessType() == GeckoProcessType_Content) {
-    MOZ_ASSERT(NS_IsMainThread()); // IPC can only be execute on main thread.
-
-    nsresult rv;
-
-    nsCOMPtr<nsPIDOMWindow> window(req->GetOwner());
-    NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
-
-    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;
-    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;
+  nsCOMPtr<nsPIDOMWindow> window(req->GetOwner());
+  return dom::nsContentPermissionUtils::AskPermission(req, window);
 }
 
 // Error callback for MediaManager::GetUserMediaDevices()
 class MediaDeviceErrorCallback: public nsIDOMGetUserMediaErrorCallback
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMGETUSERMEDIAERRORCALLBACK
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -1,16 +1,15 @@
 /* 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/. */
 
 #include "nsXULAppAPI.h"
 
 #include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/TabChild.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsISettingsService.h"
 
 #include "nsGeolocation.h"
 #include "nsDOMClassInfoID.h"
 #include "nsComponentManagerUtils.h"
 #include "nsServiceManagerUtils.h"
@@ -19,17 +18,16 @@
 #include "nsIDocument.h"
 #include "nsIObserverService.h"
 #include "nsPIDOMWindow.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Services.h"
 #include "mozilla/unused.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ClearOnShutdown.h"
-#include "PCOMContentPermissionRequestChild.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 
 class nsIPrincipal;
 
 #ifdef MOZ_ENABLE_QT5GEOPOSITION
 #include "QTMLocationProvider.h"
 #endif
 
@@ -55,17 +53,16 @@ class nsIPrincipal;
 using mozilla::unused;          // <snicker>
 using namespace mozilla;
 using namespace mozilla::dom;
 
 class nsGeolocationRequest
  : public nsIContentPermissionRequest
  , public nsITimerCallback
  , public nsIGeolocationUpdate
- , public PCOMContentPermissionRequestChild
 {
  public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
   NS_DECL_NSITIMERCALLBACK
   NS_DECL_NSIGEOLOCATIONUPDATE
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGeolocationRequest, nsIContentPermissionRequest)
@@ -80,24 +77,20 @@ class nsGeolocationRequest
 
   void SendLocation(nsIDOMGeoPosition* location);
   bool WantsHighAccuracy() {return !mShutdown && mOptions && mOptions->mEnableHighAccuracy;}
   void SetTimeoutTimer();
   void StopTimeoutTimer();
   void NotifyErrorAndShutdown(uint16_t);
   nsIPrincipal* GetPrincipal();
 
-  virtual bool Recv__delete__(const bool& allow,
-                              const InfallibleTArray<PermissionChoice>& choices) MOZ_OVERRIDE;
-  virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
-
   bool IsWatch() { return mIsWatchPositionRequest; }
   int32_t WatchId() { return mWatchId; }
  private:
-  ~nsGeolocationRequest();
+  virtual ~nsGeolocationRequest();
 
   bool mIsWatchPositionRequest;
 
   nsCOMPtr<nsITimer> mTimeoutTimer;
   GeoPositionCallback mCallback;
   GeoPositionErrorCallback mErrorCallback;
   nsAutoPtr<PositionOptions> mOptions;
 
@@ -164,31 +157,32 @@ public:
   }
 };
 
 NS_IMPL_ISUPPORTS(GeolocationSettingsCallback, nsISettingsServiceCallback)
 
 class RequestPromptEvent : public nsRunnable
 {
 public:
-  RequestPromptEvent(nsGeolocationRequest* request)
-    : mRequest(request)
+  RequestPromptEvent(nsGeolocationRequest* aRequest, nsWeakPtr aWindow)
+    : mRequest(aRequest)
+    , mWindow(aWindow)
   {
   }
 
-  NS_IMETHOD Run() {
-    nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
-    if (prompt) {
-      prompt->Prompt(mRequest);
-    }
+  NS_IMETHOD Run()
+  {
+    nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+    nsContentPermissionUtils::AskPermission(mRequest, window);
     return NS_OK;
   }
 
 private:
   nsRefPtr<nsGeolocationRequest> mRequest;
+  nsWeakPtr mWindow;
 };
 
 class RequestAllowEvent : public nsRunnable
 {
 public:
   RequestAllowEvent(int allow, nsGeolocationRequest* request)
     : mAllow(allow),
       mRequest(request)
@@ -379,20 +373,20 @@ nsGeolocationRequest::GetPrincipal(nsIPr
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGeolocationRequest::GetTypes(nsIArray** aTypes)
 {
   nsTArray<nsString> emptyOptions;
-  return CreatePermissionArray(NS_LITERAL_CSTRING("geolocation"),
-                               NS_LITERAL_CSTRING("unused"),
-                               emptyOptions,
-                               aTypes);
+  return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("geolocation"),
+                                                         NS_LITERAL_CSTRING("unused"),
+                                                         emptyOptions,
+                                                         aTypes);
 }
 
 NS_IMETHODIMP
 nsGeolocationRequest::GetWindow(nsIDOMWindow * *aRequestingWindow)
 {
   NS_ENSURE_ARG_POINTER(aRequestingWindow);
 
   nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(mLocator->GetOwner());
@@ -595,28 +589,16 @@ nsGeolocationRequest::Shutdown()
   if (mOptions && mOptions->mEnableHighAccuracy) {
     nsRefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
     if (gs) {
       gs->UpdateAccuracy();
     }
   }
 }
 
-bool nsGeolocationRequest::Recv__delete__(const bool& allow,
-                                          const InfallibleTArray<PermissionChoice>& choices)
-{
-  MOZ_ASSERT(choices.IsEmpty(), "Geolocation doesn't support permission choice");
-
-  if (allow) {
-    (void) Allow(JS::UndefinedHandleValue);
-  } else {
-    (void) Cancel();
-  }
-  return true;
-}
 ////////////////////////////////////////////////////
 // nsGeolocationService
 ////////////////////////////////////////////////////
 NS_INTERFACE_MAP_BEGIN(nsGeolocationService)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGeolocationUpdate)
   NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END
@@ -1464,47 +1446,17 @@ Geolocation::RegisterRequestWithPrompt(n
   if (Preferences::GetBool("geo.prompt.testing", false)) {
     bool allow = Preferences::GetBool("geo.prompt.testing.allow", false);
     nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(allow,
 						     request);
     NS_DispatchToMainThread(ev);
     return true;
   }
 
-  if (XRE_GetProcessType() == GeckoProcessType_Content) {
-    nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mOwner);
-    if (!window) {
-      return true;
-    }
-
-    // because owner implements nsITabChild, we can assume that it is
-    // the one and only TabChild.
-    TabChild* child = TabChild::GetFrom(window->GetDocShell());
-    if (!child) {
-      return false;
-    }
-
-    nsTArray<PermissionRequest> permArray;
-    nsTArray<nsString> emptyOptions;
-    permArray.AppendElement(PermissionRequest(NS_LITERAL_CSTRING("geolocation"),
-                                              NS_LITERAL_CSTRING("unused"),
-                                              emptyOptions));
-
-    // Retain a reference so the object isn't deleted without IPDL's knowledge.
-    // Corresponding release occurs in DeallocPContentPermissionRequest.
-    request->AddRef();
-    child->SendPContentPermissionRequestConstructor(request,
-                                                    permArray,
-                                                    IPC::Principal(mPrincipal));
-
-    request->Sendprompt();
-    return true;
-  }
-
-  nsCOMPtr<nsIRunnable> ev  = new RequestPromptEvent(request);
+  nsCOMPtr<nsIRunnable> ev  = new RequestPromptEvent(request, mOwner);
   NS_DispatchToMainThread(ev);
   return true;
 }
 
 JSObject*
 Geolocation::WrapObject(JSContext *aCtx)
 {
   return GeolocationBinding::Wrap(aCtx, this);
--- a/dom/src/notification/DesktopNotification.cpp
+++ b/dom/src/notification/DesktopNotification.cpp
@@ -4,70 +4,50 @@
 #include "mozilla/dom/DesktopNotification.h"
 #include "mozilla/dom/DesktopNotificationBinding.h"
 #include "mozilla/dom/AppNotificationServiceOptionsBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "nsContentPermissionHelper.h"
 #include "nsXULAppAPI.h"
 #include "mozilla/dom/PBrowserChild.h"
 #include "nsIDOMDesktopNotification.h"
-#include "TabChild.h"
 #include "mozilla/Preferences.h"
 #include "nsGlobalWindow.h"
 #include "nsIAppsService.h"
-#include "PCOMContentPermissionRequestChild.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsServiceManagerUtils.h"
 #include "PermissionMessageUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 /*
  * Simple Request
  */
-class DesktopNotificationRequest : public nsIContentPermissionRequest,
-                                   public nsRunnable,
-                                   public PCOMContentPermissionRequestChild
-
+class DesktopNotificationRequest : public nsIContentPermissionRequest
+                                 , public nsRunnable
 {
-  ~DesktopNotificationRequest()
+  virtual ~DesktopNotificationRequest()
   {
   }
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSICONTENTPERMISSIONREQUEST
 
   DesktopNotificationRequest(DesktopNotification* notification)
     : mDesktopNotification(notification) {}
 
   NS_IMETHOD Run() MOZ_OVERRIDE
   {
-    nsCOMPtr<nsIContentPermissionPrompt> prompt =
-      do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
-    if (prompt) {
-      prompt->Prompt(this);
-    }
+    nsCOMPtr<nsPIDOMWindow> window = mDesktopNotification->GetOwner();
+    nsContentPermissionUtils::AskPermission(this, window);
     return NS_OK;
   }
 
-  virtual bool Recv__delete__(const bool& aAllow,
-                              const InfallibleTArray<PermissionChoice>& choices) MOZ_OVERRIDE
-  {
-    MOZ_ASSERT(choices.IsEmpty(), "DesktopNotification doesn't support permission choice");
-    if (aAllow) {
-      (void) Allow(JS::UndefinedHandleValue);
-    } else {
-     (void) Cancel();
-    }
-   return true;
-  }
-  virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
-
   nsRefPtr<DesktopNotification> mDesktopNotification;
 };
 
 /* ------------------------------------------------------------------------ */
 /* AlertServiceObserver                                                     */
 /* ------------------------------------------------------------------------ */
 
 NS_IMPL_ISUPPORTS(AlertServiceObserver, nsIObserver)
@@ -159,48 +139,16 @@ DesktopNotification::DesktopNotification
   }
 }
 
 void
 DesktopNotification::Init()
 {
   nsRefPtr<DesktopNotificationRequest> request = new DesktopNotificationRequest(this);
 
-  // if we are in the content process, then remote it to the parent.
-  if (XRE_GetProcessType() == GeckoProcessType_Content) {
-
-    // if for some reason mOwner is null, just silently
-    // bail.  The user will not see a notification, and that
-    // is fine.
-    if (!GetOwner())
-      return;
-
-    // because owner implements nsITabChild, we can assume that it is
-    // the one and only TabChild for this docshell.
-    TabChild* child = TabChild::GetFrom(GetOwner()->GetDocShell());
-
-    // Retain a reference so the object isn't deleted without IPDL's knowledge.
-    // Corresponding release occurs in DeallocPContentPermissionRequest.
-    nsRefPtr<DesktopNotificationRequest> copy = request;
-
-    nsTArray<PermissionRequest> permArray;
-    nsTArray<nsString> emptyOptions;
-    permArray.AppendElement(PermissionRequest(
-                            NS_LITERAL_CSTRING("desktop-notification"),
-                            NS_LITERAL_CSTRING("unused"),
-                            emptyOptions));
-    child->SendPContentPermissionRequestConstructor(copy.forget().take(),
-                                                    permArray,
-                                                    IPC::Principal(mPrincipal));
-
-    request->Sendprompt();
-    return;
-  }
-
-  // otherwise, dispatch it
   NS_DispatchToMainThread(request);
 }
 
 DesktopNotification::~DesktopNotification()
 {
   if (mObserver) {
     mObserver->Disconnect();
   }
@@ -305,17 +253,17 @@ DesktopNotificationCenter::WrapObject(JS
   return DesktopNotificationCenterBinding::Wrap(aCx, this);
 }
 
 /* ------------------------------------------------------------------------ */
 /* DesktopNotificationRequest                                               */
 /* ------------------------------------------------------------------------ */
 
 NS_IMPL_ISUPPORTS_INHERITED(DesktopNotificationRequest, nsRunnable,
-			    nsIContentPermissionRequest)
+                            nsIContentPermissionRequest)
 
 NS_IMETHODIMP
 DesktopNotificationRequest::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
 {
   if (!mDesktopNotification) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
@@ -358,16 +306,16 @@ DesktopNotificationRequest::Allow(JS::Ha
   mDesktopNotification = nullptr;
   return rv;
 }
 
 NS_IMETHODIMP
 DesktopNotificationRequest::GetTypes(nsIArray** aTypes)
 {
   nsTArray<nsString> emptyOptions;
-  return CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
-                               NS_LITERAL_CSTRING("unused"),
-                               emptyOptions,
-                               aTypes);
+  return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
+                                                         NS_LITERAL_CSTRING("unused"),
+                                                         emptyOptions,
+                                                         aTypes);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/src/notification/Notification.cpp
+++ b/dom/src/notification/Notification.cpp
@@ -1,19 +1,17 @@
 /* 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/. */
 
-#include "PCOMContentPermissionRequestChild.h"
 #include "mozilla/dom/Notification.h"
 #include "mozilla/dom/AppNotificationServiceOptionsBinding.h"
 #include "mozilla/dom/OwningNonNull.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/Preferences.h"
-#include "TabChild.h"
 #include "nsContentUtils.h"
 #include "nsIAlertsService.h"
 #include "nsIAppsService.h"
 #include "nsIContentPermissionPrompt.h"
 #include "nsIDocument.h"
 #include "nsINotificationStorage.h"
 #include "nsIPermissionManager.h"
 #include "nsIUUIDGenerator.h"
@@ -88,17 +86,17 @@ public:
   {
     JSAutoCompartment ac(aCx, mGlobal);
     JS::Rooted<JS::Value> result(aCx, JS::ObjectValue(*mNotifications));
     mPromise->MaybeResolve(aCx, result);
     return NS_OK;
   }
 
 private:
-  ~NotificationStorageCallback()
+  virtual ~NotificationStorageCallback()
   {
     DropData();
   }
 
   void HoldData()
   {
     mozilla::HoldJSObjects(this);
   }
@@ -139,36 +137,31 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NotificationStorageCallback)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
   tmp->DropData();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 class NotificationPermissionRequest : public nsIContentPermissionRequest,
-                                      public PCOMContentPermissionRequestChild,
                                       public nsIRunnable
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
   NS_DECL_NSIRUNNABLE
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(NotificationPermissionRequest,
                                            nsIContentPermissionRequest)
 
   NotificationPermissionRequest(nsIPrincipal* aPrincipal, nsPIDOMWindow* aWindow,
                                 NotificationPermissionCallback* aCallback)
     : mPrincipal(aPrincipal), mWindow(aWindow),
       mPermission(NotificationPermission::Default),
       mCallback(aCallback) {}
 
-  bool Recv__delete__(const bool& aAllow,
-                      const InfallibleTArray<PermissionChoice>& choices);
-  void IPDLRelease() { Release(); }
-
 protected:
   virtual ~NotificationPermissionRequest() {}
 
   nsresult CallCallback();
   nsresult DispatchCallback();
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsPIDOMWindow> mWindow;
   NotificationPermission mPermission;
@@ -251,48 +244,17 @@ NotificationPermissionRequest::Run()
       mPermission = NotificationPermission::Denied;
     }
   }
 
   if (mPermission != NotificationPermission::Default) {
     return DispatchCallback();
   }
 
-  if (XRE_GetProcessType() == GeckoProcessType_Content) {
-    // because owner implements nsITabChild, we can assume that it is
-    // the one and only TabChild.
-    TabChild* child = TabChild::GetFrom(mWindow->GetDocShell());
-    if (!child) {
-      return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    // Retain a reference so the object isn't deleted without IPDL's knowledge.
-    // Corresponding release occurs in DeallocPContentPermissionRequest.
-    AddRef();
-
-    nsTArray<PermissionRequest> permArray;
-    nsTArray<nsString> emptyOptions;
-    permArray.AppendElement(PermissionRequest(
-                            NS_LITERAL_CSTRING("desktop-notification"),
-                            NS_LITERAL_CSTRING("unused"),
-                            emptyOptions));
-    child->SendPContentPermissionRequestConstructor(this, permArray,
-                                                    IPC::Principal(mPrincipal));
-
-    Sendprompt();
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIContentPermissionPrompt> prompt =
-    do_GetService(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
-  if (prompt) {
-    prompt->Prompt(this);
-  }
-
-  return NS_OK;
+  return nsContentPermissionUtils::AskPermission(this, mWindow);
 }
 
 NS_IMETHODIMP
 NotificationPermissionRequest::GetPrincipal(nsIPrincipal** aRequestingPrincipal)
 {
   NS_ADDREF(*aRequestingPrincipal = mPrincipal);
   return NS_OK;
 }
@@ -347,34 +309,20 @@ NotificationPermissionRequest::CallCallb
   mCallback->Call(mPermission, rv);
   return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 NotificationPermissionRequest::GetTypes(nsIArray** aTypes)
 {
   nsTArray<nsString> emptyOptions;
-  return CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
-                               NS_LITERAL_CSTRING("unused"),
-                               emptyOptions,
-                               aTypes);
-}
-
-bool
-NotificationPermissionRequest::Recv__delete__(const bool& aAllow,
-                                              const InfallibleTArray<PermissionChoice>& choices)
-{
-  MOZ_ASSERT(choices.IsEmpty(), "Notification doesn't support permission choice");
-
-  if (aAllow) {
-    (void) Allow(JS::UndefinedHandleValue);
-  } else {
-    (void) Cancel();
-  }
-  return true;
+  return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
+                                                         NS_LITERAL_CSTRING("unused"),
+                                                         emptyOptions,
+                                                         aTypes);
 }
 
 NS_IMPL_ISUPPORTS(NotificationTask, nsIRunnable)
 
 NS_IMETHODIMP
 NotificationTask::Run()
 {
   switch (mAction) {