Bug 869869 - Part 2, add PUDPSocket IPDL interface, r=jdm.
authorShih-Chiang Chien <schien@mozilla.com>
Fri, 10 May 2013 20:00:28 +0800
changeset 153941 18584f4297df60332db2deb33a2c46dc73252924
parent 153940 4021b7b381f183f84c65e62f7445fdc4366946c6
child 153942 8c6161254db5005b06f68dca2ead0bd2490eb83e
push id25615
push usercbook@mozilla.com
push dateThu, 07 Nov 2013 14:51:34 +0000
treeherdermozilla-central@7433abfef863 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
bugs869869
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 869869 - Part 2, add PUDPSocket IPDL interface, r=jdm.
dom/network/interfaces/moz.build
dom/network/interfaces/nsIUDPSocketChild.idl
dom/network/src/PUDPSocket.ipdl
dom/network/src/UDPSocketChild.cpp
dom/network/src/UDPSocketChild.h
dom/network/src/UDPSocketParent.cpp
dom/network/src/UDPSocketParent.h
dom/network/src/moz.build
dom/network/tests/unit_ipc/test_udpsocket_ipc.js
dom/network/tests/unit_ipc/udpsocket_child.js
dom/network/tests/unit_ipc/xpcshell.ini
layout/build/nsLayoutModule.cpp
netwerk/ipc/NeckoChild.cpp
netwerk/ipc/NeckoChild.h
netwerk/ipc/NeckoParent.cpp
netwerk/ipc/NeckoParent.h
netwerk/ipc/PNecko.ipdl
--- a/dom/network/interfaces/moz.build
+++ b/dom/network/interfaces/moz.build
@@ -8,16 +8,17 @@ XPIDL_SOURCES += [
     'nsIDOMConnection.idl',
     'nsIDOMTCPServerSocket.idl',
     'nsIDOMTCPSocket.idl',
     'nsIMozNavigatorNetwork.idl',
     'nsITCPServerSocketChild.idl',
     'nsITCPServerSocketParent.idl',
     'nsITCPSocketChild.idl',
     'nsITCPSocketParent.idl',
+    'nsIUDPSocketChild.idl',
 ]
 
 if CONFIG['MOZ_B2G_RIL']:
     XPIDL_SOURCES += [
         'nsIDOMCFStateChangeEvent.idl',
         'nsIDOMDataErrorEvent.idl',
         'nsIDOMMobileConnection.idl',
         'nsIDOMMozEmergencyCbModeEvent.idl',
new file mode 100644
--- /dev/null
+++ b/dom/network/interfaces/nsIUDPSocketChild.idl
@@ -0,0 +1,52 @@
+/* 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 "nsISupports.idl"
+#include "nsINetAddr.idl"
+
+interface nsIUDPSocketInternal;
+
+%{ C++
+#include "mozilla/net/DNS.h"
+%}
+native NetAddr(mozilla::net::NetAddr);
+[ptr] native NetAddrPtr(mozilla::net::NetAddr);
+
+[scriptable, uuid(B47E5A0F-D384-48EF-8885-4259793D9CF0)]
+interface nsIUDPSocketChild : nsISupports
+{
+  readonly attribute unsigned short localPort;
+  readonly attribute AUTF8String localAddress;
+  // Tell the chrome process to bind the UDP socket to a given local host and port
+  void bind(in nsIUDPSocketInternal socket, in AUTF8String host, in unsigned short port);
+
+  // Tell the chrome process to perform equivalent operations to all following methods
+  void send(in AUTF8String host, in unsigned short port,
+            [const, array, size_is(byteLength)] in uint8_t bytes,
+            in unsigned long byteLength);
+  // Send without DNS query
+  void sendWithAddr(in nsINetAddr addr,
+                    [const, array, size_is(byteLength)] in uint8_t bytes,
+                    in unsigned long byteLength);
+  [noscript] void sendWithAddress([const] in NetAddrPtr addr,
+                                  [const, array, size_is(byteLength)] in uint8_t bytes,
+                                  in unsigned long byteLength);
+  void close();
+};
+
+/*
+ * Internal interface for callback from chrome process
+ */
+[scriptable, uuid(1E27E9B3-C1C8-4B05-A415-1A2C1A641C60)]
+interface nsIUDPSocketInternal : nsISupports
+{
+  void callListenerError(in AUTF8String type, in AUTF8String message, in AUTF8String filename,
+                         in uint32_t lineNumber, in uint32_t columnNumber);
+  void callListenerReceivedData(in AUTF8String type, in AUTF8String host, in unsigned short port,
+                                [array, size_is(dataLength)] in uint8_t data,
+                                in unsigned long dataLength);
+  void callListenerVoid(in AUTF8String type);
+  void callListenerSent(in AUTF8String type, in nsresult status);
+  void updateReadyState(in AUTF8String readyState);
+};
new file mode 100644
--- /dev/null
+++ b/dom/network/src/PUDPSocket.ipdl
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+
+/* 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 protocol PNecko;
+
+include "mozilla/net/NeckoMessageUtils.h";
+include "mozilla/net/DNS.h";
+include "prio.h";
+
+using mozilla::net::NetAddr from "mozilla/net/DNS.h";
+using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
+
+struct UDPError {
+  nsCString message;
+  nsCString filename;
+  uint32_t lineNumber;
+  uint32_t columnNumber;
+};
+
+struct UDPMessage {
+  nsCString fromAddr;
+  uint16_t port;
+  uint8_t[] data;
+};
+
+struct UDPAddressInfo {
+  nsCString local;
+  uint16_t port;
+};
+
+struct UDPSendResult {
+  nsresult value;
+};
+
+union UDPCallbackData {
+  void_t;
+  UDPMessage;
+  UDPAddressInfo;
+  UDPSendResult;
+  UDPError;
+};
+
+namespace mozilla {
+namespace net {
+
+//-------------------------------------------------------------------
+protocol PUDPSocket
+{
+  manager PNecko;
+
+parent:
+  Data(uint8_t[] data, nsCString remoteAddress, uint16_t port);
+  DataWithAddress(uint8_t[] data, NetAddr addr);
+  Close();
+  RequestDelete();
+
+child:
+  Callback(nsCString type, UDPCallbackData data, nsCString aState);
+  __delete__();
+};
+
+
+} // namespace net
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/dom/network/src/UDPSocketChild.cpp
@@ -0,0 +1,192 @@
+/* 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 "UDPSocketChild.h"
+#include "mozilla/net/NeckoChild.h"
+
+using mozilla::net::gNeckoChild;
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_ISUPPORTS1(UDPSocketChildBase, nsIUDPSocketChild)
+
+UDPSocketChildBase::UDPSocketChildBase()
+: mIPCOpen(false)
+{
+}
+
+UDPSocketChildBase::~UDPSocketChildBase()
+{
+}
+void
+UDPSocketChildBase::ReleaseIPDLReference()
+{
+  MOZ_ASSERT(mIPCOpen);
+  mIPCOpen = false;
+  this->Release();
+}
+
+void
+UDPSocketChildBase::AddIPDLReference()
+{
+  MOZ_ASSERT(!mIPCOpen);
+  mIPCOpen = true;
+  this->AddRef();
+}
+
+NS_IMETHODIMP_(nsrefcnt) UDPSocketChild::Release(void)
+{
+  nsrefcnt refcnt = UDPSocketChildBase::Release();
+  if (refcnt == 1 && mIPCOpen) {
+    PUDPSocketChild::SendRequestDelete();
+    return 1;
+  }
+  return refcnt;
+}
+
+UDPSocketChild::UDPSocketChild()
+:mLocalPort(0)
+{
+}
+
+UDPSocketChild::~UDPSocketChild()
+{
+}
+
+// nsIUDPSocketChild Methods
+
+NS_IMETHODIMP
+UDPSocketChild::Bind(nsIUDPSocketInternal *aSocket,
+                     const nsACString& aHost,
+                     uint16_t aPort)
+{
+  NS_ENSURE_ARG(aSocket);
+
+  mSocket = aSocket;
+  AddIPDLReference();
+
+  gNeckoChild->SendPUDPSocketConstructor(this, nsCString(aHost), aPort);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+UDPSocketChild::Close()
+{
+  SendClose();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+UDPSocketChild::Send(const nsACString& aHost,
+                     uint16_t aPort,
+                     const uint8_t *aData,
+                     uint32_t aByteLength)
+{
+  NS_ENSURE_ARG(aData);
+
+  FallibleTArray<uint8_t> fallibleArray;
+  if (!fallibleArray.InsertElementsAt(0, aData, aByteLength)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  InfallibleTArray<uint8_t> array;
+  array.SwapElements(fallibleArray);
+  SendData(array, nsCString(aHost), aPort);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+UDPSocketChild::SendWithAddr(nsINetAddr *aAddr,
+                             const uint8_t *aData,
+                             uint32_t aByteLength)
+{
+  NS_ENSURE_ARG(aAddr);
+  NS_ENSURE_ARG(aData);
+
+  NetAddr addr;
+  aAddr->GetNetAddr(&addr);
+
+  return SendWithAddress(&addr, aData, aByteLength);
+}
+
+NS_IMETHODIMP
+UDPSocketChild::SendWithAddress(const NetAddr *aAddr,
+                                const uint8_t *aData,
+                                uint32_t aByteLength)
+{
+  NS_ENSURE_ARG(aAddr);
+  NS_ENSURE_ARG(aData);
+
+  FallibleTArray<uint8_t> fallibleArray;
+  if (!fallibleArray.InsertElementsAt(0, aData, aByteLength)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  InfallibleTArray<uint8_t> array;
+  array.SwapElements(fallibleArray);
+  SendDataWithAddress(array, *aAddr);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+UDPSocketChild::GetLocalPort(uint16_t *aLocalPort)
+{
+  NS_ENSURE_ARG_POINTER(aLocalPort);
+
+  *aLocalPort = mLocalPort;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+UDPSocketChild::GetLocalAddress(nsACString &aLocalAddress)
+{
+  aLocalAddress = mLocalAddress;
+  return NS_OK;
+}
+
+// PUDPSocketChild Methods
+bool
+UDPSocketChild::RecvCallback(const nsCString &aType,
+                             const UDPCallbackData &aData,
+                             const nsCString &aState)
+{
+  if (NS_FAILED(mSocket->UpdateReadyState(aState)))
+    NS_ERROR("Shouldn't fail!");
+
+  nsresult rv = NS_ERROR_FAILURE;
+  if (aData.type() == UDPCallbackData::Tvoid_t) {
+    rv = mSocket->CallListenerVoid(aType);
+  } else if (aData.type() == UDPCallbackData::TUDPError) {
+    const UDPError& err(aData.get_UDPError());
+    rv = mSocket->CallListenerError(aType, err.message(), err.filename(),
+                                    err.lineNumber(), err.columnNumber());
+  } else if (aData.type() == UDPCallbackData::TUDPMessage) {
+    const UDPMessage& message(aData.get_UDPMessage());
+    InfallibleTArray<uint8_t> data(message.data());
+    rv = mSocket->CallListenerReceivedData(aType, message.fromAddr(), message.port(),
+                                           data.Elements(), data.Length());
+  } else if (aData.type() == UDPCallbackData::TUDPAddressInfo) {
+    //update local address and port.
+    const UDPAddressInfo& addressInfo(aData.get_UDPAddressInfo());
+    mLocalAddress = addressInfo.local();
+    mLocalPort = addressInfo.port();
+    rv = mSocket->CallListenerVoid(aType);
+  } else if (aData.type() == UDPCallbackData::TUDPSendResult) {
+    const UDPSendResult& returnValue(aData.get_UDPSendResult());
+    rv = mSocket->CallListenerSent(aType, returnValue.value());
+  } else {
+    MOZ_ASSERT("Invalid callback type!");
+  }
+
+  NS_ENSURE_SUCCESS(rv, true);
+
+  return true;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/network/src/UDPSocketChild.h
@@ -0,0 +1,54 @@
+/* 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_UDPSocketChild_h__
+#define mozilla_dom_UDPSocketChild_h__
+
+#include "mozilla/net/PUDPSocketChild.h"
+#include "nsIUDPSocketChild.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsCOMPtr.h"
+
+#define UDPSOCKETCHILD_CID \
+  {0xb47e5a0f, 0xd384, 0x48ef, { 0x88, 0x85, 0x42, 0x59, 0x79, 0x3d, 0x9c, 0xf0 }}
+
+namespace mozilla {
+namespace dom {
+
+class UDPSocketChildBase : public nsIUDPSocketChild {
+public:
+  NS_DECL_ISUPPORTS
+
+  void AddIPDLReference();
+  void ReleaseIPDLReference();
+
+protected:
+  UDPSocketChildBase();
+  virtual ~UDPSocketChildBase();
+  nsCOMPtr<nsIUDPSocketInternal> mSocket;
+  bool mIPCOpen;
+};
+
+class UDPSocketChild : public mozilla::net::PUDPSocketChild
+                     , public UDPSocketChildBase
+{
+public:
+  NS_DECL_NSIUDPSOCKETCHILD
+  NS_IMETHOD_(nsrefcnt) Release() MOZ_OVERRIDE;
+
+  UDPSocketChild();
+  virtual ~UDPSocketChild();
+
+  virtual bool RecvCallback(const nsCString& aType,
+                            const UDPCallbackData& aData,
+                            const nsCString& aState) MOZ_OVERRIDE;
+private:
+  uint16_t mLocalPort;
+  nsCString mLocalAddress;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // !defined(mozilla_dom_UDPSocketChild_h__)
new file mode 100644
--- /dev/null
+++ b/dom/network/src/UDPSocketParent.cpp
@@ -0,0 +1,239 @@
+/* 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 "UDPSocketParent.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIUDPSocket.h"
+#include "nsINetAddr.h"
+#include "mozilla/unused.h"
+#include "mozilla/net/DNS.h"
+
+namespace mozilla {
+namespace dom {
+
+static void
+FireInternalError(mozilla::net::PUDPSocketParent *aActor, uint32_t aLineNo)
+{
+  mozilla::unused <<
+      aActor->SendCallback(NS_LITERAL_CSTRING("onerror"),
+                          UDPError(NS_LITERAL_CSTRING("Internal error"),
+                                   NS_LITERAL_CSTRING(__FILE__), aLineNo, 0),
+                          NS_LITERAL_CSTRING("connecting"));
+}
+
+static nsresult
+ConvertNetAddrToString(mozilla::net::NetAddr &netAddr, nsACString *address, uint16_t *port)
+{
+  NS_ENSURE_ARG_POINTER(address);
+  NS_ENSURE_ARG_POINTER(port);
+
+  *port = 0;
+  uint32_t bufSize = 0;
+
+  switch(netAddr.raw.family) {
+  case AF_INET:
+    *port = PR_ntohs(netAddr.inet.port);
+    bufSize = mozilla::net::kIPv4CStrBufSize;
+    break;
+  case AF_INET6:
+    *port = PR_ntohs(netAddr.inet6.port);
+    bufSize = mozilla::net::kIPv6CStrBufSize;
+    break;
+  default:
+    //impossible
+    MOZ_ASSERT("Unexpected address family");
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  address->SetCapacity(bufSize);
+  NetAddrToString(&netAddr, address->BeginWriting(), bufSize);
+  address->SetLength(strlen(address->BeginReading()));
+
+  return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS1(UDPSocketParent, nsIUDPSocketListener)
+
+UDPSocketParent::~UDPSocketParent()
+{
+}
+
+// PUDPSocketParent methods
+
+bool
+UDPSocketParent::Init(const nsCString &aHost, const uint16_t aPort)
+{
+  nsresult rv;
+
+  nsCOMPtr<nsIUDPSocket> sock =
+      do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
+  if (NS_FAILED(rv)) {
+    FireInternalError(this, __LINE__);
+    return true;
+  }
+
+  if (aHost.IsEmpty()) {
+    rv = sock->Init(aPort, false);
+  } else {
+    PRNetAddr prAddr;
+    PR_InitializeNetAddr(PR_IpAddrAny, aPort, &prAddr);
+    PRStatus status = PR_StringToNetAddr(aHost.BeginReading(), &prAddr);
+    if (status != PR_SUCCESS) {
+      FireInternalError(this, __LINE__);
+      return true;
+    }
+
+    mozilla::net::NetAddr addr;
+    PRNetAddrToNetAddr(&prAddr, &addr);
+    rv = sock->InitWithAddress(&addr);
+  }
+
+  if (NS_FAILED(rv)) {
+    FireInternalError(this, __LINE__);
+    return true;
+  }
+
+  mSocket = sock;
+
+  net::NetAddr localAddr;
+  mSocket->GetAddress(&localAddr);
+
+  uint16_t port;
+  nsCString addr;
+  rv = ConvertNetAddrToString(localAddr, &addr, &port);
+
+  if (NS_FAILED(rv)) {
+    FireInternalError(this, __LINE__);
+    return true;
+  }
+
+  // register listener
+  mSocket->AsyncListen(this);
+  mozilla::unused <<
+      PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onopen"),
+                                     UDPAddressInfo(addr, port),
+                                     NS_LITERAL_CSTRING("connected"));
+
+  return true;
+}
+
+bool
+UDPSocketParent::RecvData(const InfallibleTArray<uint8_t> &aData,
+                          const nsCString& aRemoteAddress,
+                          const uint16_t& aPort)
+{
+  NS_ENSURE_TRUE(mSocket, true);
+  uint32_t count;
+  nsresult rv = mSocket->Send(aRemoteAddress,
+                              aPort, aData.Elements(),
+                              aData.Length(), &count);
+  mozilla::unused <<
+      PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onsent"),
+                                     UDPSendResult(rv),
+                                     NS_LITERAL_CSTRING("connected"));
+  NS_ENSURE_SUCCESS(rv, true);
+  NS_ENSURE_TRUE(count > 0, true);
+  return true;
+}
+
+bool
+UDPSocketParent::RecvDataWithAddress(const InfallibleTArray<uint8_t>& aData,
+                                     const mozilla::net::NetAddr& aAddr)
+{
+  NS_ENSURE_TRUE(mSocket, true);
+  uint32_t count;
+  nsresult rv = mSocket->SendWithAddress(&aAddr, aData.Elements(),
+                                         aData.Length(), &count);
+  mozilla::unused <<
+      PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onsent"),
+                                     UDPSendResult(rv),
+                                     NS_LITERAL_CSTRING("connected"));
+  NS_ENSURE_SUCCESS(rv, true);
+  NS_ENSURE_TRUE(count > 0, true);
+  return true;
+}
+
+bool
+UDPSocketParent::RecvClose()
+{
+  NS_ENSURE_TRUE(mSocket, true);
+  nsresult rv = mSocket->Close();
+  mSocket = nullptr;
+  NS_ENSURE_SUCCESS(rv, true);
+  return true;
+}
+
+bool
+UDPSocketParent::RecvRequestDelete()
+{
+  mozilla::unused << Send__delete__(this);
+  return true;
+}
+
+void
+UDPSocketParent::ActorDestroy(ActorDestroyReason why)
+{
+  MOZ_ASSERT(mIPCOpen);
+  mIPCOpen = false;
+  if (mSocket) {
+    mSocket->Close();
+  }
+  mSocket = nullptr;
+}
+
+// nsIUDPSocketListener
+
+NS_IMETHODIMP
+UDPSocketParent::OnPacketReceived(nsIUDPSocket* aSocket, nsIUDPMessage* aMessage)
+{
+  // receiving packet from remote host, forward the message content to child process
+  if (!mIPCOpen) {
+    return NS_OK;
+  }
+
+  uint16_t port;
+  nsCString ip;
+  nsCOMPtr<nsINetAddr> fromAddr;
+  aMessage->GetFromAddr(getter_AddRefs(fromAddr));
+  fromAddr->GetPort(&port);
+  fromAddr->GetAddress(ip);
+
+  nsCString data;
+  aMessage->GetData(data);
+
+  const char* buffer = data.get();
+  uint32_t len = data.Length();
+
+  FallibleTArray<uint8_t> fallibleArray;
+  if (!fallibleArray.InsertElementsAt(0, buffer, len)) {
+    FireInternalError(this, __LINE__);
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  InfallibleTArray<uint8_t> infallibleArray;
+  infallibleArray.SwapElements(fallibleArray);
+
+  // compose callback
+  mozilla::unused <<
+      PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("ondata"),
+                                     UDPMessage(ip, port, infallibleArray),
+                                     NS_LITERAL_CSTRING("connected"));
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+UDPSocketParent::OnStopListening(nsIUDPSocket* aSocket, nsresult aStatus)
+{
+  // underlying socket is dead, send state update to child process
+  if (mIPCOpen) {
+    mozilla::unused <<
+        PUDPSocketParent::SendCallback(NS_LITERAL_CSTRING("onclose"),
+                                       mozilla::void_t(),
+                                       NS_LITERAL_CSTRING("closed"));
+  }
+  return NS_OK;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/network/src/UDPSocketParent.h
@@ -0,0 +1,45 @@
+/* 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_UDPSocketParent_h__
+#define mozilla_dom_UDPSocketParent_h__
+
+#include "mozilla/net/PUDPSocketParent.h"
+#include "nsCOMPtr.h"
+#include "nsIUDPSocket.h"
+
+namespace mozilla {
+namespace dom {
+
+class UDPSocketParent : public mozilla::net::PUDPSocketParent
+                      , public nsIUDPSocketListener
+{
+public:
+  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_NSIUDPSOCKETLISTENER
+
+  UDPSocketParent() : mIPCOpen(true) {}
+  virtual ~UDPSocketParent();
+
+  bool Init(const nsCString& aHost, const uint16_t aPort);
+
+  virtual bool RecvClose() MOZ_OVERRIDE;
+  virtual bool RecvData(const InfallibleTArray<uint8_t>& aData,
+                        const nsCString& aRemoteAddress,
+                        const uint16_t& aPort) MOZ_OVERRIDE;
+  virtual bool RecvDataWithAddress( const InfallibleTArray<uint8_t>& data,
+                                    const mozilla::net::NetAddr& addr);
+  virtual bool RecvRequestDelete() MOZ_OVERRIDE;
+
+private:
+  virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
+
+  bool mIPCOpen;
+  nsCOMPtr<nsIUDPSocket> mSocket;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // !defined(mozilla_dom_UDPSocketParent_h__)
--- a/dom/network/src/moz.build
+++ b/dom/network/src/moz.build
@@ -6,24 +6,28 @@
 
 EXPORTS.mozilla.dom.network += [
     'Constants.h',
     'TCPServerSocketChild.h',
     'TCPServerSocketParent.h',
     'TCPSocketChild.h',
     'TCPSocketParent.h',
     'Types.h',
+    'UDPSocketChild.h',
+    'UDPSocketParent.h',
 ]
 
 SOURCES += [
     'Connection.cpp',
     'TCPServerSocketChild.cpp',
     'TCPServerSocketParent.cpp',
     'TCPSocketChild.cpp',
     'TCPSocketParent.cpp',
+    'UDPSocketChild.cpp',
+    'UDPSocketParent.cpp',
 ]
 
 if CONFIG['MOZ_B2G_RIL']:
     EXPORTS.mozilla.dom.network += [
         'MobileConnection.h',
     ]
     SOURCES += [
         'MobileConnection.cpp',
@@ -51,16 +55,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
         'NetworkStatsManager.manifest',
         'NetworkStatsServiceProxy.js',
         'NetworkStatsServiceProxy.manifest',
     ]
 
 IPDL_SOURCES += [
     'PTCPServerSocket.ipdl',
     'PTCPSocket.ipdl',
+    'PUDPSocket.ipdl',
 ]
 
 FAIL_ON_WARNINGS = True
 
 LIBXUL_LIBRARY = True
 
 LIBRARY_NAME = 'dom_network_s'
 
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/unit_ipc/test_udpsocket_ipc.js
@@ -0,0 +1,9 @@
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+function run_test() {
+  Services.prefs.setBoolPref('media.peerconnection.ipc.enabled', true);
+  run_test_in_child("/udpsocket_child.js", function() {
+    Services.prefs.clearUserPref('media.peerconnection.ipc.enabled');
+    do_test_finished();
+  });
+}
new file mode 100644
--- /dev/null
+++ b/dom/network/tests/unit_ipc/udpsocket_child.js
@@ -0,0 +1,164 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+'use strict';
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+
+const SERVER_PORT = 12345;
+const DATA_ARRAY = [0, 255, 254, 0, 1, 2, 3, 0, 255, 255, 254, 0];
+
+function UDPSocketInternalImpl() {
+}
+
+UDPSocketInternalImpl.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIUDPSocketInternal]),
+  callListenerError: function(type, message, filename, lineNumber, columnNumber) {
+    if (this.onerror) {
+      this.onerror();
+    } else {
+      do_throw('Received unexpected error: ' + message + ' at ' + filename +
+                ':' + lineNumber + ':' + columnNumber);
+    }
+  },
+  callListenerReceivedData: function(type, host, port, data, dataLength) {
+    do_print('*** recv data(' + dataLength + ')=' + data.join() + '\n');
+    if (this.ondata) {
+      try {
+        this.ondata(data, dataLength);
+      } catch(ex) {
+        if (ex === Cr.NS_ERROR_ABORT)
+          throw ex;
+        do_print('Caught exception: ' + ex + '\n' + ex.stack);
+        do_throw('test is broken; bad ondata handler; see above');
+      }
+    } else {
+      do_throw('Received ' + dataLength + ' bytes of unexpected data!');
+    }
+  },
+  callListenerVoid: function(type) {
+    switch (type) {
+    case 'onopen':
+      if (this.onopen) {
+        this.onopen();
+      }
+      break;
+    case 'onclose':
+      if (this.onclose) {
+        this.onclose();
+      }
+      break;
+    }
+  },
+  callListenerSent: function(type, value) {
+    if (value != Cr.NS_OK) {
+      do_throw('Previous send was failed with cause: ' + value);
+    }
+  },
+  updateReadyState: function(readyState) {
+    do_print('*** current state: ' + readyState + '\n');
+  },
+  onopen: function() {},
+  onclose: function() {},
+};
+
+function makeSuccessCase(name) {
+  return function() {
+    do_print('got expected: ' + name);
+    run_next_test();
+  };
+}
+
+function makeJointSuccess(names) {
+  let funcs = {}, successCount = 0;
+  names.forEach(function(name) {
+    funcs[name] = function() {
+      do_print('got excepted: ' + name);
+      if (++successCount === names.length)
+        run_next_test();
+    };
+  });
+  return funcs;
+}
+
+function makeExpectedData(expectedData, callback) {
+  return function(receivedData, receivedDataLength) {
+    if (receivedDataLength != expectedData.length) {
+      do_throw('Received data size mismatched, expected ' + expectedData.length +
+               ' but got ' + receivedDataLength);
+    }
+    for (let i = 0; i < receivedDataLength; i++) {
+      if (receivedData[i] != expectedData[i]) {
+        do_throw('Received mismatched data at position ' + i);
+      }
+    }
+    if (callback) {
+      callback();
+    } else {
+      run_next_test();
+    }
+  };
+}
+
+function makeFailureCase(name) {
+  return function() {
+    let argstr;
+    if (arguments.length) {
+      argstr = '(args: ' +
+        Array.map(arguments, function(x) {return x.data + ""; }).join(" ") + ')';
+    } else {
+      argstr = '(no arguments)';
+    }
+    do_throw('got unexpected: ' + name + ' ' + argstr);
+  };
+}
+
+function createSocketChild() {
+  return Cc['@mozilla.org/udp-socket-child;1']
+           .createInstance(Ci.nsIUDPSocketChild);
+}
+
+var UDPSocket = createSocketChild();
+var callback = new UDPSocketInternalImpl();
+
+function connectSock() {
+  UDPSocket.bind(callback, '127.0.0.1', SERVER_PORT);
+  callback.onopen = makeSuccessCase('open');
+}
+
+function sendData() {
+  UDPSocket.send('127.0.0.1', SERVER_PORT, DATA_ARRAY, DATA_ARRAY.length);
+  callback.ondata = makeExpectedData(DATA_ARRAY);
+}
+
+function clientClose() {
+  UDPSocket.close();
+  callback.ondata = makeFailureCase('data');
+  callback.onclose = makeSuccessCase('close');
+}
+
+function connectError() {
+  UDPSocket = createSocketChild();
+  UDPSocket.bind(callback, 'some non-IP string', SERVER_PORT);
+  callback.onerror = makeSuccessCase('error');
+  callback.onopen = makeFailureCase('open');
+}
+
+function cleanup() {
+  UDPSocket = null;
+  run_next_test();
+}
+
+add_test(connectSock);
+add_test(sendData);
+add_test(clientClose);
+add_test(connectError);
+add_test(cleanup);
+
+function run_test() {
+  run_next_test();
+}
--- a/dom/network/tests/unit_ipc/xpcshell.ini
+++ b/dom/network/tests/unit_ipc/xpcshell.ini
@@ -1,7 +1,10 @@
 [DEFAULT]
 head =
 tail =
+support-files =
+  udpsocket_child.js
 
 [test_tcpsocket_ipc.js]
 [test_tcpserversocket_ipc.js]
+[test_udpsocket_ipc.js]
 run-sequentially = Uses hardcoded port, bug 903830.
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -87,16 +87,17 @@
 #include "mozilla/dom/Activity.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMRequest.h"
 #include "mozilla/dom/EventSource.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
 #include "mozilla/dom/network/TCPSocketChild.h"
 #include "mozilla/dom/network/TCPSocketParent.h"
 #include "mozilla/dom/network/TCPServerSocketChild.h"
+#include "mozilla/dom/network/UDPSocketChild.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/OSFileConstants.h"
 #include "mozilla/Services.h"
 
 #ifdef MOZ_WEBSPEECH
 #include "mozilla/dom/FakeSpeechRecognitionService.h"
 #include "mozilla/dom/nsSynthVoiceRegistry.h"
 #endif
@@ -246,16 +247,17 @@ using namespace mozilla::dom::mobilemess
 using namespace mozilla::dom::telephony;
 using mozilla::dom::alarm::AlarmHalService;
 using mozilla::dom::indexedDB::IndexedDatabaseManager;
 using mozilla::dom::power::PowerManagerService;
 using mozilla::dom::quota::QuotaManager;
 using mozilla::dom::TCPSocketChild;
 using mozilla::dom::TCPSocketParent;
 using mozilla::dom::TCPServerSocketChild;
+using mozilla::dom::UDPSocketChild;
 using mozilla::dom::time::TimeService;
 using mozilla::net::StreamingProtocolControllerService;
 
 // Transformiix
 /* 5d5d92cd-6bf8-11d9-bf4a-000a95dc234c */
 #define TRANSFORMIIX_NODESET_CID \
 { 0x5d5d92cd, 0x6bf8, 0x11d9, { 0xbf, 0x4a, 0x0, 0x0a, 0x95, 0xdc, 0x23, 0x4c } }
 
@@ -641,16 +643,17 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
     nsScriptSecurityManager::SystemPrincipalSingletonConstructor)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNullPrincipal, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStructuredCloneContainer)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(OSFileConstantsService)
 NS_GENERIC_FACTORY_CONSTRUCTOR(TCPSocketChild)
 NS_GENERIC_FACTORY_CONSTRUCTOR(TCPSocketParent)
 NS_GENERIC_FACTORY_CONSTRUCTOR(TCPServerSocketChild)
+NS_GENERIC_FACTORY_CONSTRUCTOR(UDPSocketChild)
 
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 
   MAKE_CTOR(CreateA11yService, nsIAccessibilityService, NS_GetAccessibilityService)
 #endif
 
 static nsresult
@@ -803,16 +806,17 @@ NS_DEFINE_NAMED_CID(MMS_SERVICE_CID);
 NS_DEFINE_NAMED_CID(MOBILE_MESSAGE_SERVICE_CID);
 NS_DEFINE_NAMED_CID(MOBILE_MESSAGE_DATABASE_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_POWERMANAGERSERVICE_CID);
 NS_DEFINE_NAMED_CID(OSFILECONSTANTSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_ALARMHALSERVICE_CID);
 NS_DEFINE_NAMED_CID(TCPSOCKETCHILD_CID);
 NS_DEFINE_NAMED_CID(TCPSOCKETPARENT_CID);
 NS_DEFINE_NAMED_CID(TCPSERVERSOCKETCHILD_CID);
+NS_DEFINE_NAMED_CID(UDPSOCKETCHILD_CID);
 NS_DEFINE_NAMED_CID(NS_TIMESERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_MEDIASTREAMCONTROLLERSERVICE_CID);
 #ifdef MOZ_WIDGET_GONK
 NS_DEFINE_NAMED_CID(GONK_GPS_GEOLOCATION_PROVIDER_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_MEDIAMANAGERSERVICE_CID);
 #ifdef MOZ_GAMEPAD
 NS_DEFINE_NAMED_CID(NS_GAMEPAD_TEST_CID);
@@ -1093,16 +1097,17 @@ static const mozilla::Module::CIDEntry k
   { &kMOBILE_MESSAGE_SERVICE_CID, false, nullptr, nsIMobileMessageServiceConstructor },
   { &kMOBILE_MESSAGE_DATABASE_SERVICE_CID, false, nullptr, nsIMobileMessageDatabaseServiceConstructor },
   { &kNS_POWERMANAGERSERVICE_CID, false, nullptr, nsIPowerManagerServiceConstructor },
   { &kOSFILECONSTANTSSERVICE_CID, true, nullptr, OSFileConstantsServiceConstructor },
   { &kNS_ALARMHALSERVICE_CID, false, nullptr, nsIAlarmHalServiceConstructor },
   { &kTCPSOCKETCHILD_CID, false, nullptr, TCPSocketChildConstructor },
   { &kTCPSOCKETPARENT_CID, false, nullptr, TCPSocketParentConstructor },
   { &kTCPSERVERSOCKETCHILD_CID, false, nullptr, TCPServerSocketChildConstructor },
+  { &kUDPSOCKETCHILD_CID, false, nullptr, UDPSocketChildConstructor },
   { &kNS_TIMESERVICE_CID, false, nullptr, nsITimeServiceConstructor },
   { &kNS_MEDIASTREAMCONTROLLERSERVICE_CID, false, nullptr, nsIStreamingProtocolControllerServiceConstructor },
 #ifdef MOZ_WIDGET_GONK
   { &kGONK_GPS_GEOLOCATION_PROVIDER_CID, false, nullptr, nsIGeolocationProviderConstructor },
 #endif
   { &kNS_MEDIAMANAGERSERVICE_CID, false, nullptr, nsIMediaManagerServiceConstructor },
 #ifdef MOZ_GAMEPAD
   { &kNS_GAMEPAD_TEST_CID, false, nullptr, GamepadServiceTestConstructor },
@@ -1250,16 +1255,17 @@ static const mozilla::Module::ContractID
   { MOBILE_MESSAGE_SERVICE_CONTRACTID, &kMOBILE_MESSAGE_SERVICE_CID },
   { MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID, &kMOBILE_MESSAGE_DATABASE_SERVICE_CID },
   { POWERMANAGERSERVICE_CONTRACTID, &kNS_POWERMANAGERSERVICE_CID },
   { OSFILECONSTANTSSERVICE_CONTRACTID, &kOSFILECONSTANTSSERVICE_CID },
   { ALARMHALSERVICE_CONTRACTID, &kNS_ALARMHALSERVICE_CID },
   { "@mozilla.org/tcp-socket-child;1", &kTCPSOCKETCHILD_CID },
   { "@mozilla.org/tcp-socket-parent;1", &kTCPSOCKETPARENT_CID },
   { "@mozilla.org/tcp-server-socket-child;1", &kTCPSERVERSOCKETCHILD_CID },
+  { "@mozilla.org/udp-socket-child;1", &kUDPSOCKETCHILD_CID },
   { TIMESERVICE_CONTRACTID, &kNS_TIMESERVICE_CID },
   { MEDIASTREAMCONTROLLERSERVICE_CONTRACTID, &kNS_MEDIASTREAMCONTROLLERSERVICE_CID },
 #ifdef MOZ_WIDGET_GONK
   { GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID, &kGONK_GPS_GEOLOCATION_PROVIDER_CID },
 #endif
 #ifdef MOZ_GAMEPAD
   { NS_GAMEPAD_TEST_CONTRACTID, &kNS_GAMEPAD_TEST_CID },
 #endif
--- a/netwerk/ipc/NeckoChild.cpp
+++ b/netwerk/ipc/NeckoChild.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
 /* vim: set sw=2 ts=8 et 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/. */
 
 #include "nsHttp.h"
 #include "mozilla/net/NeckoChild.h"
@@ -11,23 +11,25 @@
 #include "mozilla/net/HttpChannelChild.h"
 #include "mozilla/net/CookieServiceChild.h"
 #include "mozilla/net/WyciwygChannelChild.h"
 #include "mozilla/net/FTPChannelChild.h"
 #include "mozilla/net/WebSocketChannelChild.h"
 #include "mozilla/net/RemoteOpenFileChild.h"
 #include "mozilla/dom/network/TCPSocketChild.h"
 #include "mozilla/dom/network/TCPServerSocketChild.h"
+#include "mozilla/dom/network/UDPSocketChild.h"
 #ifdef MOZ_RTSP
 #include "mozilla/net/RtspControllerChild.h"
 #endif
 #include "SerializedLoadContext.h"
 
 using mozilla::dom::TCPSocketChild;
 using mozilla::dom::TCPServerSocketChild;
+using mozilla::dom::UDPSocketChild;
 
 namespace mozilla {
 namespace net {
 
 PNeckoChild *gNeckoChild = nullptr;
 
 // C++ file contents
 NeckoChild::NeckoChild()
@@ -204,16 +206,33 @@ NeckoChild::AllocPTCPServerSocketChild(c
 bool
 NeckoChild::DeallocPTCPServerSocketChild(PTCPServerSocketChild* child)
 {
   TCPServerSocketChild* p = static_cast<TCPServerSocketChild*>(child);
   p->ReleaseIPDLReference();
   return true;
 }
 
+PUDPSocketChild*
+NeckoChild::AllocPUDPSocketChild(const nsCString& aHost,
+                                 const uint16_t& aPort)
+{
+  NS_NOTREACHED("AllocPUDPSocket should not be called");
+  return nullptr;
+}
+
+bool
+NeckoChild::DeallocPUDPSocketChild(PUDPSocketChild* child)
+{
+
+  UDPSocketChild* p = static_cast<UDPSocketChild*>(child);
+  p->ReleaseIPDLReference();
+  return true;
+}
+
 PRemoteOpenFileChild*
 NeckoChild::AllocPRemoteOpenFileChild(const URIParams&, const OptionalURIParams&)
 {
   // We don't allocate here: instead we always use IPDL constructor that takes
   // an existing RemoteOpenFileChild
   NS_NOTREACHED("AllocPRemoteOpenFileChild should not be called on child");
   return nullptr;
 }
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -42,16 +42,19 @@ protected:
   virtual PWebSocketChild* AllocPWebSocketChild(PBrowserChild*, const SerializedLoadContext&);
   virtual bool DeallocPWebSocketChild(PWebSocketChild*);
   virtual PTCPSocketChild* AllocPTCPSocketChild();
   virtual bool DeallocPTCPSocketChild(PTCPSocketChild*);
   virtual PTCPServerSocketChild* AllocPTCPServerSocketChild(const uint16_t& aLocalPort,
                                                        const uint16_t& aBacklog,
                                                        const nsString& aBinaryType);
   virtual bool DeallocPTCPServerSocketChild(PTCPServerSocketChild*);
+  virtual PUDPSocketChild* AllocPUDPSocketChild(const nsCString& aHost,
+                                                const uint16_t& aPort);
+  virtual bool DeallocPUDPSocketChild(PUDPSocketChild*);
   virtual PRemoteOpenFileChild* AllocPRemoteOpenFileChild(const URIParams&,
                                                           const OptionalURIParams&);
   virtual bool DeallocPRemoteOpenFileChild(PRemoteOpenFileChild*);
   virtual PRtspControllerChild* AllocPRtspControllerChild();
   virtual bool DeallocPRtspControllerChild(PRtspControllerChild*);
 };
 
 /**
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -15,32 +15,35 @@
 #ifdef MOZ_RTSP
 #include "mozilla/net/RtspControllerParent.h"
 #endif
 #include "mozilla/net/RemoteOpenFileParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/network/TCPSocketParent.h"
 #include "mozilla/dom/network/TCPServerSocketParent.h"
+#include "mozilla/dom/network/UDPSocketParent.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/LoadContext.h"
 #include "mozilla/AppProcessChecker.h"
 #include "nsPrintfCString.h"
 #include "nsHTMLDNSPrefetch.h"
 #include "nsIAppsService.h"
 #include "nsEscape.h"
 #include "RemoteOpenFileParent.h"
 #include "SerializedLoadContext.h"
 
 using mozilla::dom::ContentParent;
 using mozilla::dom::TabParent;
 using mozilla::net::PTCPSocketParent;
 using mozilla::dom::TCPSocketParent;
 using mozilla::net::PTCPServerSocketParent;
 using mozilla::dom::TCPServerSocketParent;
+using mozilla::net::PUDPSocketParent;
+using mozilla::dom::UDPSocketParent;
 using IPC::SerializedLoadContext;
 
 namespace mozilla {
 namespace net {
 
 // C++ file contents
 NeckoParent::NeckoParent()
 {
@@ -368,16 +371,47 @@ NeckoParent::RecvPTCPServerSocketConstru
 bool
 NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor)
 {
   TCPServerSocketParent* p = static_cast<TCPServerSocketParent*>(actor);
    p->ReleaseIPDLReference();
   return true;
 }
 
+PUDPSocketParent*
+NeckoParent::AllocPUDPSocketParent(const nsCString& aHost,
+                                   const uint16_t& aPort)
+{
+  bool enabled = Preferences::GetBool("media.peerconnection.ipc.enabled", false);
+  if (!enabled) {
+    NS_WARNING("Not support UDP socket in content process, aborting subprocess");
+    return nullptr;
+  }
+  UDPSocketParent* p = new UDPSocketParent();
+  p->AddRef();
+  return p;
+
+}
+
+bool
+NeckoParent::RecvPUDPSocketConstructor(PUDPSocketParent* aActor,
+                                       const nsCString& aHost,
+                                       const uint16_t& aPort)
+{
+  return static_cast<UDPSocketParent*>(aActor)->Init(aHost, aPort);
+}
+
+bool
+NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor)
+{
+  UDPSocketParent* p = static_cast<UDPSocketParent*>(actor);
+  p->Release();
+  return true;
+}
+
 PRemoteOpenFileParent*
 NeckoParent::AllocPRemoteOpenFileParent(const URIParams& aURI,
                                         const OptionalURIParams& aAppURI)
 {
   nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
   nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(uri);
   if (!fileURL) {
     return nullptr;
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -111,16 +111,22 @@ protected:
   virtual PTCPServerSocketParent* AllocPTCPServerSocketParent(const uint16_t& aLocalPort,
                                                         const uint16_t& aBacklog,
                                                         const nsString& aBinaryType);
   virtual bool RecvPTCPServerSocketConstructor(PTCPServerSocketParent*,
                                                const uint16_t& aLocalPort,
                                                const uint16_t& aBacklog,
                                                const nsString& aBinaryType);
   virtual bool DeallocPTCPServerSocketParent(PTCPServerSocketParent*);
+  virtual PUDPSocketParent* AllocPUDPSocketParent(const nsCString& aHost,
+                                                  const uint16_t& aPort);
+  virtual bool RecvPUDPSocketConstructor(PUDPSocketParent*,
+                                         const nsCString& aHost,
+                                         const uint16_t& aPort);
+  virtual bool DeallocPUDPSocketParent(PUDPSocketParent*);
   virtual bool RecvHTMLDNSPrefetch(const nsString& hostname,
                                    const uint16_t& flags);
   virtual bool RecvCancelHTMLDNSPrefetch(const nsString& hostname,
                                          const uint16_t& flags,
                                          const nsresult& reason);
 
   virtual mozilla::ipc::IProtocol*
   CloneProtocol(Channel* aChannel,
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -9,16 +9,17 @@ include protocol PContent;
 include protocol PHttpChannel;
 include protocol PCookieService;
 include protocol PBrowser;
 include protocol PWyciwygChannel;
 include protocol PFTPChannel;
 include protocol PWebSocket;
 include protocol PTCPSocket;
 include protocol PTCPServerSocket;
+include protocol PUDPSocket;
 include protocol PRemoteOpenFile;
 include protocol PBlob; //FIXME: bug #792908
 
 include protocol PRtspController;
 include URIParams;
 include InputStreamParams;
 include NeckoChannelParams;
 
@@ -34,32 +35,35 @@ sync protocol PNecko
   manager PContent;
   manages PHttpChannel;
   manages PCookieService;
   manages PWyciwygChannel;
   manages PFTPChannel;
   manages PWebSocket;
   manages PTCPSocket;
   manages PTCPServerSocket;
+  manages PUDPSocket;
   manages PRemoteOpenFile;
   manages PRtspController;
 
 parent:
   __delete__();
 
   PCookieService();
   PHttpChannel(nullable PBrowser browser,
                SerializedLoadContext loadContext,
                HttpChannelCreationArgs args);
   PWyciwygChannel();
   PFTPChannel(PBrowser browser, SerializedLoadContext loadContext,
               FTPChannelCreationArgs args);
 
   PWebSocket(PBrowser browser, SerializedLoadContext loadContext);
   PTCPServerSocket(uint16_t localPort, uint16_t backlog, nsString binaryType);
+  PUDPSocket(nsCString host, uint16_t port);
+
   PRemoteOpenFile(URIParams fileuri, OptionalURIParams appuri);
 
   HTMLDNSPrefetch(nsString hostname, uint16_t flags);
   CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason);
   PRtspController();
 
 both:
   PTCPSocket();