Bug 1114935 - Part 4.2: Add IPC Implementation of nsIIccService. r=echen
authorBevis Tseng <btseng@mozilla.com>
Wed, 07 Jan 2015 16:58:35 +0800
changeset 234082 3e960b045db421c4b6cc05ed0ef68ba1eb0c5de8
parent 234081 396d108f30b54b10cac21a8e454b3cae386885f5
child 234083 7ea28b23e8877b139ac7ffe6b6957e741916f415
push id28429
push userryanvm@gmail.com
push dateTue, 17 Mar 2015 18:25:14 +0000
treeherdermozilla-central@e965a1a534ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechen
bugs1114935
milestone39.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 1114935 - Part 4.2: Add IPC Implementation of nsIIccService. r=echen
dom/icc/ipc/IccChild.cpp
dom/icc/ipc/IccChild.h
dom/icc/ipc/IccIPCService.cpp
dom/icc/ipc/IccIPCService.h
dom/icc/ipc/IccParent.cpp
dom/icc/ipc/IccParent.h
dom/icc/moz.build
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccChild.cpp
@@ -0,0 +1,310 @@
+/* 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 "mozilla/dom/icc/IccChild.h"
+#include "IccInfo.h"
+
+using mozilla::dom::IccInfo;
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+/**
+ * PIccChild Implementation.
+ */
+
+IccChild::IccChild()
+  : mCardState(nsIIcc::CARD_STATE_UNKNOWN)
+  , mIsAlive(true)
+{
+  MOZ_COUNT_CTOR(IccChild);
+}
+
+IccChild::~IccChild()
+{
+  MOZ_COUNT_DTOR(IccChild);
+}
+
+void
+IccChild::Init()
+{
+  OptionalIccInfoData infoData;
+
+  bool rv = SendInit(&infoData, &mCardState);
+  NS_ENSURE_TRUE_VOID(rv);
+
+  UpdateIccInfo(infoData);
+}
+
+void
+IccChild::Shutdown(){
+  if (mIsAlive) {
+    mIsAlive = false;
+    Send__delete__(this);
+  }
+
+  mListeners.Clear();
+  mIccInfo = nullptr;
+  mCardState = nsIIcc::CARD_STATE_UNKNOWN;
+}
+
+void
+IccChild::ActorDestroy(ActorDestroyReason why)
+{
+  mIsAlive = false;
+}
+
+bool
+IccChild::RecvNotifyCardStateChanged(const uint32_t& aCardState)
+{
+  mCardState = aCardState;
+
+  for (int32_t i = 0; i < mListeners.Count(); i++) {
+    mListeners[i]->NotifyCardStateChanged();
+  }
+
+  return true;
+}
+
+bool
+IccChild::RecvNotifyIccInfoChanged(const OptionalIccInfoData& aInfoData)
+{
+  UpdateIccInfo(aInfoData);
+
+  for (int32_t i = 0; i < mListeners.Count(); i++) {
+    mListeners[i]->NotifyIccInfoChanged();
+  }
+
+  return true;
+}
+
+PIccRequestChild*
+IccChild::AllocPIccRequestChild(const IccRequest& aRequest)
+{
+  MOZ_CRASH("Caller is supposed to manually construct a request!");
+}
+
+bool
+IccChild::DeallocPIccRequestChild(PIccRequestChild* aActor)
+{
+  delete aActor;
+  return true;
+}
+
+bool
+IccChild::SendRequest(const IccRequest& aRequest, nsIIccCallback* aRequestReply)
+{
+  NS_ENSURE_TRUE(mIsAlive, false);
+
+  // Deallocated in IccChild::DeallocPIccRequestChild().
+  IccRequestChild* actor = new IccRequestChild(aRequestReply);
+  SendPIccRequestConstructor(actor, aRequest);
+
+  return true;
+}
+
+void
+IccChild::UpdateIccInfo(const OptionalIccInfoData& aInfoData) {
+  if (aInfoData.type() == OptionalIccInfoData::Tvoid_t) {
+    mIccInfo = nullptr;
+    return;
+  }
+
+  NS_ENSURE_TRUE_VOID(aInfoData.type() == OptionalIccInfoData::TIccInfoData);
+
+  nsRefPtr<IccInfo> iccInfo;
+  const IccInfoData& infoData = aInfoData.get_IccInfoData();
+  if (infoData.iccType().EqualsLiteral("sim")
+      || infoData.iccType().EqualsLiteral("usim")) {
+    iccInfo = new GsmIccInfo(infoData);
+  } else if (infoData.iccType().EqualsLiteral("ruim")
+             || infoData.iccType().EqualsLiteral("csim")){
+    iccInfo = new CdmaIccInfo(infoData);
+  } else {
+    iccInfo = new IccInfo(infoData);
+  }
+
+  // We update the orignal one instead of replacing with a new one
+  // if the IccType is the same.
+  if (mIccInfo) {
+    nsString oldIccType;
+    nsString newIccType;
+    mIccInfo->GetIccType(oldIccType);
+    iccInfo->GetIccType(newIccType);
+
+    if (oldIccType.Equals(newIccType)) {
+      mIccInfo->Update(iccInfo);
+      return;
+    }
+  }
+
+  mIccInfo = iccInfo;
+}
+
+/**
+ * nsIIcc Implementation.
+ */
+
+NS_IMPL_ISUPPORTS(IccChild, nsIIcc)
+
+NS_IMETHODIMP
+IccChild::RegisterListener(nsIIccListener *aListener)
+{
+  NS_ENSURE_TRUE(!mListeners.Contains(aListener), NS_ERROR_UNEXPECTED);
+
+  mListeners.AppendObject(aListener);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccChild::UnregisterListener(nsIIccListener *aListener)
+{
+  NS_ENSURE_TRUE(mListeners.Contains(aListener), NS_ERROR_UNEXPECTED);
+
+  mListeners.RemoveObject(aListener);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccChild::GetIccInfo(nsIIccInfo** aIccInfo)
+{
+  nsCOMPtr<nsIIccInfo> info(mIccInfo);
+  info.forget(aIccInfo);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccChild::GetCardState(uint32_t* aCardState)
+{
+  *aCardState = mCardState;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccChild::GetCardLockEnabled(uint32_t aLockType,
+                             nsIIccCallback* aRequestReply)
+{
+  return SendRequest(GetCardLockEnabledRequest(aLockType), aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::UnlockCardLock(uint32_t aLockType,
+                         const nsAString& aPassword,
+                         const nsAString& aNewPin,
+                         nsIIccCallback* aRequestReply)
+{
+  return SendRequest(UnlockCardLockRequest(aLockType,
+                                           nsString(aPassword),
+                                           nsString(aNewPin)),
+                     aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::SetCardLockEnabled(uint32_t aLockType,
+                             const nsAString& aPassword,
+                             bool aEnabled,
+                             nsIIccCallback* aRequestReply)
+{
+  return SendRequest(SetCardLockEnabledRequest(aLockType,
+                                               nsString(aPassword),
+                                               aEnabled),
+                     aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::ChangeCardLockPassword(uint32_t aLockType,
+                                 const nsAString& aPassword,
+                                 const nsAString& aNewPassword,
+                                 nsIIccCallback* aRequestReply)
+{
+  return SendRequest(ChangeCardLockPasswordRequest(aLockType,
+                                                   nsString(aPassword),
+                                                   nsString(aNewPassword)),
+                     aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::GetCardLockRetryCount(uint32_t aLockType,
+                                nsIIccCallback* aRequestReply)
+{
+  return SendRequest(GetCardLockRetryCountRequest(aLockType), aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::MatchMvno(uint32_t aMvnoType,
+                    const nsAString& aMvnoData,
+                    nsIIccCallback* aRequestReply)
+{
+  return SendRequest(MatchMvnoRequest(aMvnoType, nsString(aMvnoData)),
+                     aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::GetServiceStateEnabled(uint32_t aService,
+                                 nsIIccCallback* aRequestReply)
+{
+  return SendRequest(GetServiceStateEnabledRequest(aService),
+                     aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/**
+ * PIccRequestChild Implementation.
+ */
+
+IccRequestChild::IccRequestChild(nsIIccCallback* aRequestReply)
+  : mRequestReply(aRequestReply)
+{
+  MOZ_COUNT_CTOR(IccRequestChild);
+  MOZ_ASSERT(aRequestReply);
+}
+
+bool
+IccRequestChild::Recv__delete__(const IccReply& aResponse)
+{
+  MOZ_ASSERT(mRequestReply);
+
+  switch(aResponse.type()) {
+    case IccReply::TIccReplySuccess:
+      return NS_SUCCEEDED(mRequestReply->NotifySuccess());
+    case IccReply::TIccReplySuccessWithBoolean: {
+      const IccReplySuccessWithBoolean& resultWithBoolean
+        = aResponse.get_IccReplySuccessWithBoolean();
+      return NS_SUCCEEDED(
+        mRequestReply->NotifySuccessWithBoolean(resultWithBoolean.result()));
+    }
+    case IccReply::TIccReplyCardLockRetryCount: {
+      const IccReplyCardLockRetryCount& retryCount
+        = aResponse.get_IccReplyCardLockRetryCount();
+      return NS_SUCCEEDED(
+        mRequestReply->NotifyGetCardLockRetryCount(retryCount.count()));
+    }
+    case IccReply::TIccReplyError: {
+      const IccReplyError& error = aResponse.get_IccReplyError();
+      return NS_SUCCEEDED(mRequestReply->NotifyError(error.message()));
+    }
+    case IccReply::TIccReplyCardLockError: {
+      const IccReplyCardLockError& error
+        = aResponse.get_IccReplyCardLockError();
+      return NS_SUCCEEDED(
+        mRequestReply->NotifyCardLockError(error.message(),
+                                           error.retryCount()));
+    }
+    default:
+      MOZ_CRASH("Received invalid response type!");
+  }
+
+  return true;
+}
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccChild.h
@@ -0,0 +1,88 @@
+/* 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_icc_IccChild_h
+#define mozilla_dom_icc_IccChild_h
+
+#include "mozilla/dom/icc/PIccChild.h"
+#include "mozilla/dom/icc/PIccRequestChild.h"
+#include "nsIIccService.h"
+
+namespace mozilla {
+namespace dom {
+
+class IccInfo;
+
+namespace icc {
+
+class IccChild MOZ_FINAL : public PIccChild
+                         , public nsIIcc
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIICC
+
+  explicit IccChild();
+
+  void
+  Init();
+
+  void
+  Shutdown();
+
+protected:
+  virtual void
+  ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
+
+  virtual PIccRequestChild*
+  AllocPIccRequestChild(const IccRequest& aRequest) MOZ_OVERRIDE;
+
+  virtual bool
+  DeallocPIccRequestChild(PIccRequestChild* aActor) MOZ_OVERRIDE;
+
+  virtual bool
+  RecvNotifyCardStateChanged(const uint32_t& aCardState) MOZ_OVERRIDE;
+
+  virtual bool
+  RecvNotifyIccInfoChanged(const OptionalIccInfoData& aInfoData) MOZ_OVERRIDE;
+
+private:
+  // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
+  ~IccChild();
+
+  void
+  UpdateIccInfo(const OptionalIccInfoData& aInfoData);
+
+  bool
+  SendRequest(const IccRequest& aRequest, nsIIccCallback* aRequestReply);
+
+  nsCOMArray<nsIIccListener> mListeners;
+  nsRefPtr<IccInfo> mIccInfo;
+  uint32_t mCardState;
+  bool mIsAlive;
+};
+
+class IccRequestChild MOZ_FINAL : public PIccRequestChild
+{
+public:
+  explicit IccRequestChild(nsIIccCallback* aRequestReply);
+
+protected:
+  virtual bool
+  Recv__delete__(const IccReply& aReply) MOZ_OVERRIDE;
+
+private:
+  // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
+  virtual ~IccRequestChild() {
+    MOZ_COUNT_DTOR(IccRequestChild);
+  }
+
+  nsCOMPtr<nsIIccCallback> mRequestReply;
+};
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_icc_IccChild_h
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccIPCService.cpp
@@ -0,0 +1,56 @@
+/* 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 "IccIPCService.h"
+
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/Preferences.h"
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+NS_IMPL_ISUPPORTS(IccIPCService, nsIIccService)
+
+IccIPCService::IccIPCService()
+{
+  int32_t numRil = Preferences::GetInt("ril.numRadioInterfaces", 1);
+  mIccs.SetLength(numRil);
+}
+
+IccIPCService::~IccIPCService()
+{
+  uint32_t count = mIccs.Length();
+  for (uint32_t i = 0; i < count; i++) {
+    if (mIccs[i]) {
+      mIccs[i]->Shutdown();
+    }
+  }
+}
+
+NS_IMETHODIMP
+IccIPCService::GetIccByServiceId(uint32_t aServiceId, nsIIcc** aIcc)
+{
+  NS_ENSURE_TRUE(aServiceId < mIccs.Length(), NS_ERROR_INVALID_ARG);
+
+  if (!mIccs[aServiceId]) {
+    nsRefPtr<IccChild> child = new IccChild();
+
+    // |SendPIccConstructor| adds another reference to the child
+    // actor and removes in |DeallocPIccChild|.
+    ContentChild::GetSingleton()->SendPIccConstructor(child, aServiceId);
+    child->Init();
+
+    mIccs[aServiceId] = child;
+  }
+
+  nsCOMPtr<nsIIcc> icc(mIccs[aServiceId]);
+  icc.forget(aIcc);
+
+  return NS_OK;
+}
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccIPCService.h
@@ -0,0 +1,36 @@
+/* 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_icc_IccIPCService_h
+#define mozilla_dom_icc_IccIPCService_h
+
+#include "nsCOMPtr.h"
+#include "nsIIccService.h"
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+class IccChild;
+
+class IccIPCService MOZ_FINAL : public nsIIccService
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIICCSERVICE
+
+  IccIPCService();
+
+private:
+  // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
+  ~IccIPCService();
+
+  nsTArray<nsRefPtr<IccChild>> mIccs;
+};
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_icc_IccIPCService_h
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccParent.cpp
@@ -0,0 +1,320 @@
+/* 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 "mozilla/dom/icc/IccParent.h"
+#include "nsIIccService.h"
+#include "IccInfo.h"
+
+using mozilla::dom::IccInfo;
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+namespace {
+
+static void
+GetIccInfoDataFromIccInfo(nsIIccInfo* aInInfo, IccInfoData& aOutData) {
+  aInInfo->GetIccType(aOutData.iccType());
+  aInInfo->GetIccid(aOutData.iccid());
+  aInInfo->GetMcc(aOutData.mcc());
+  aInInfo->GetMnc(aOutData.mnc());
+  aInInfo->GetSpn(aOutData.spn());
+  aInInfo->GetIsDisplayNetworkNameRequired(
+    &aOutData.isDisplayNetworkNameRequired());
+  aInInfo->GetIsDisplaySpnRequired(
+    &aOutData.isDisplaySpnRequired());
+
+  nsCOMPtr<nsIGsmIccInfo> gsmIccInfo(do_QueryInterface(aInInfo));
+  if (gsmIccInfo) {
+    gsmIccInfo->GetMsisdn(aOutData.phoneNumber());
+  }
+
+  nsCOMPtr<nsICdmaIccInfo> cdmaIccInfo(do_QueryInterface(aInInfo));
+  if (cdmaIccInfo) {
+    cdmaIccInfo->GetMdn(aOutData.phoneNumber());
+    cdmaIccInfo->GetPrlVersion(&aOutData.prlVersion());
+  }
+}
+
+} // anonymous namespace
+
+/**
+ * PIccParent Implementation.
+ */
+
+IccParent::IccParent(uint32_t aServiceId)
+{
+  MOZ_COUNT_CTOR(IccParent);
+
+  nsCOMPtr<nsIIccService> service =
+    do_GetService(ICC_SERVICE_CONTRACTID);
+
+  NS_ASSERTION(service, "Failed to get IccService!");
+
+  service->GetIccByServiceId(aServiceId, getter_AddRefs(mIcc));
+
+  NS_ASSERTION(mIcc, "Failed to get Icc with specified serviceId.");
+
+  mIcc->RegisterListener(this);
+}
+
+void
+IccParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  if (mIcc) {
+    mIcc->UnregisterListener(this);
+    mIcc = nullptr;
+  }
+}
+
+bool
+IccParent::RecvInit(OptionalIccInfoData* aInfoData,
+                    uint32_t* aCardState)
+{
+  NS_ENSURE_TRUE(mIcc, false);
+
+  nsresult rv = mIcc->GetCardState(aCardState);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  nsCOMPtr<nsIIccInfo> iccInfo;
+  rv = mIcc->GetIccInfo(getter_AddRefs(iccInfo));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  if (iccInfo) {
+    IccInfoData data;
+    GetIccInfoDataFromIccInfo(iccInfo, data);
+    *aInfoData = OptionalIccInfoData(data);
+
+    return true;
+  }
+
+  *aInfoData = OptionalIccInfoData(void_t());
+
+  return true;
+}
+
+PIccRequestParent*
+IccParent::AllocPIccRequestParent(const IccRequest& aRequest)
+{
+  NS_ASSERTION(mIcc, "AllocPIccRequestParent after actor was destroyed!");
+
+  IccRequestParent* actor = new IccRequestParent(mIcc);
+  // Add an extra ref for IPDL. Will be released in
+  // IccParent::DeallocPIccRequestParent().
+  actor->AddRef();
+  return actor;
+}
+
+bool
+IccParent::DeallocPIccRequestParent(PIccRequestParent* aActor)
+{
+  // IccRequestParent is refcounted, must not be freed manually.
+  static_cast<IccRequestParent*>(aActor)->Release();
+  return true;
+}
+
+bool
+IccParent::RecvPIccRequestConstructor(PIccRequestParent* aActor,
+                                      const IccRequest& aRequest)
+{
+  NS_ASSERTION(mIcc, "RecvPIccRequestConstructor after actor was destroyed!");
+
+  IccRequestParent* actor = static_cast<IccRequestParent*>(aActor);
+
+  switch (aRequest.type()) {
+    case IccRequest::TGetCardLockEnabledRequest:
+      return actor->DoRequest(aRequest.get_GetCardLockEnabledRequest());
+    case IccRequest::TUnlockCardLockRequest:
+      return actor->DoRequest(aRequest.get_UnlockCardLockRequest());
+    case IccRequest::TSetCardLockEnabledRequest:
+      return actor->DoRequest(aRequest.get_SetCardLockEnabledRequest());
+    case IccRequest::TChangeCardLockPasswordRequest:
+      return actor->DoRequest(aRequest.get_ChangeCardLockPasswordRequest());
+    case IccRequest::TGetCardLockRetryCountRequest:
+      return actor->DoRequest(aRequest.get_GetCardLockRetryCountRequest());
+    case IccRequest::TMatchMvnoRequest:
+      return actor->DoRequest(aRequest.get_MatchMvnoRequest());
+    case IccRequest::TGetServiceStateEnabledRequest:
+      return actor->DoRequest(aRequest.get_GetServiceStateEnabledRequest());
+    default:
+      MOZ_CRASH("Received invalid request type!");
+  }
+
+  return true;
+}
+
+/**
+ * nsIIccListener Implementation.
+ */
+
+NS_IMPL_ISUPPORTS(IccParent, nsIIccListener)
+
+NS_IMETHODIMP
+IccParent::NotifyStkCommand(const nsAString & aMessage)
+{
+  // Bug 1114938 - [B2G][ICC] Refactor STK in MozIcc.webidl with IPDL.
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+IccParent::NotifyStkSessionEnd()
+{
+  // Bug 1114938 - [B2G][ICC] Refactor STK in MozIcc.webidl with IPDL.
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+IccParent::NotifyCardStateChanged()
+{
+  NS_ENSURE_TRUE(mIcc, NS_ERROR_FAILURE);
+
+  uint32_t cardState;
+  nsresult rv = mIcc->GetCardState(&cardState);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return SendNotifyCardStateChanged(cardState) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccParent::NotifyIccInfoChanged()
+{
+  NS_ENSURE_TRUE(mIcc, NS_ERROR_FAILURE);
+
+  nsCOMPtr<nsIIccInfo> iccInfo;
+  nsresult rv = mIcc->GetIccInfo(getter_AddRefs(iccInfo));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (!iccInfo) {
+    return SendNotifyIccInfoChanged(OptionalIccInfoData(void_t()))
+      ? NS_OK : NS_ERROR_FAILURE;
+  }
+
+  IccInfoData data;
+  GetIccInfoDataFromIccInfo(iccInfo, data);
+
+  return SendNotifyIccInfoChanged(OptionalIccInfoData(data))
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/**
+ * PIccRequestParent Implementation.
+ */
+
+IccRequestParent::IccRequestParent(nsIIcc* aIcc)
+  : mIcc(aIcc)
+{
+  MOZ_COUNT_CTOR(IccRequestParent);
+}
+
+void
+IccRequestParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  mIcc = nullptr;
+}
+
+bool
+IccRequestParent::DoRequest(const GetCardLockEnabledRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->GetCardLockEnabled(aRequest.lockType(),
+                                               this));
+}
+
+bool
+IccRequestParent::DoRequest(const UnlockCardLockRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->UnlockCardLock(aRequest.lockType(),
+                                           aRequest.password(),
+                                           aRequest.newPin(),
+                                           this));
+}
+
+bool
+IccRequestParent::DoRequest(const SetCardLockEnabledRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->SetCardLockEnabled(aRequest.lockType(),
+                                               aRequest.password(),
+                                               aRequest.enabled(),
+                                               this));
+}
+
+bool
+IccRequestParent::DoRequest(const ChangeCardLockPasswordRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->ChangeCardLockPassword(aRequest.lockType(),
+                                                   aRequest.password(),
+                                                   aRequest.newPassword(),
+                                                   this));
+}
+
+bool
+IccRequestParent::DoRequest(const GetCardLockRetryCountRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->GetCardLockRetryCount(aRequest.lockType(),
+                                                  this));
+}
+
+bool
+IccRequestParent::DoRequest(const MatchMvnoRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->MatchMvno(aRequest.mvnoType(),
+                                      aRequest.mvnoData(),
+                                      this));
+}
+
+bool
+IccRequestParent::DoRequest(const GetServiceStateEnabledRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->GetServiceStateEnabled(aRequest.service(),
+                                                   this));
+}
+
+nsresult
+IccRequestParent::SendReply(const IccReply& aReply)
+{
+  NS_ENSURE_TRUE(mIcc, NS_ERROR_FAILURE);
+
+  return Send__delete__(this, aReply) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/**
+ * nsIIccCallback Implementation.
+ */
+
+NS_IMPL_ISUPPORTS(IccRequestParent, nsIIccCallback)
+
+NS_IMETHODIMP
+IccRequestParent::NotifySuccess()
+{
+  return SendReply(IccReplySuccess());
+}
+
+NS_IMETHODIMP
+IccRequestParent::NotifySuccessWithBoolean(bool aResult)
+{
+  return SendReply(IccReplySuccessWithBoolean(aResult));
+}
+
+NS_IMETHODIMP
+IccRequestParent::NotifyGetCardLockRetryCount(int32_t aCount)
+{
+  return SendReply(IccReplyCardLockRetryCount(aCount));
+}
+
+NS_IMETHODIMP
+IccRequestParent::NotifyError(const nsAString & aErrorMsg)
+{
+  return SendReply(IccReplyError(nsString(aErrorMsg)));
+}
+
+NS_IMETHODIMP
+IccRequestParent::NotifyCardLockError(const nsAString & aErrorMsg,
+                                      int32_t aRetryCount)
+{
+  return SendReply(IccReplyCardLockError(aRetryCount, nsString(aErrorMsg)));
+}
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccParent.h
@@ -0,0 +1,109 @@
+/* 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_icc_IccParent_h
+#define mozilla_dom_icc_IccParent_h
+
+#include "mozilla/dom/icc/PIccParent.h"
+#include "mozilla/dom/icc/PIccRequestParent.h"
+#include "nsIIccService.h"
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+class IccParent MOZ_FINAL : public PIccParent
+                          , public nsIIccListener
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIICCLISTENER
+
+  explicit IccParent(uint32_t aServiceId);
+
+protected:
+  virtual
+  // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
+  ~IccParent()
+  {
+    MOZ_COUNT_DTOR(IccParent);
+  }
+
+  virtual void
+  ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
+
+  virtual bool
+  RecvInit(
+          OptionalIccInfoData* aInfoData,
+          uint32_t* aCardState) MOZ_OVERRIDE;
+
+  virtual PIccRequestParent*
+  AllocPIccRequestParent(const IccRequest& aRequest) MOZ_OVERRIDE;
+
+  virtual bool
+  DeallocPIccRequestParent(PIccRequestParent* aActor) MOZ_OVERRIDE;
+
+  virtual bool
+  RecvPIccRequestConstructor(PIccRequestParent* aActor,
+                             const IccRequest& aRequest) MOZ_OVERRIDE;
+
+private:
+  IccParent();
+  nsCOMPtr<nsIIcc> mIcc;
+};
+
+class IccRequestParent MOZ_FINAL : public PIccRequestParent
+                                 , public nsIIccCallback
+{
+  friend class IccParent;
+
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIICCCALLBACK
+
+  explicit IccRequestParent(nsIIcc* icc);
+
+protected:
+  virtual void
+  ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
+
+private:
+  // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
+  ~IccRequestParent()
+  {
+    MOZ_COUNT_DTOR(IccRequestParent);
+  }
+
+  bool
+  DoRequest(const GetCardLockEnabledRequest& aRequest);
+
+  bool
+  DoRequest(const UnlockCardLockRequest& aRequest);
+
+  bool
+  DoRequest(const SetCardLockEnabledRequest& aRequest);
+
+  bool
+  DoRequest(const ChangeCardLockPasswordRequest& aRequest);
+
+  bool
+  DoRequest(const GetCardLockRetryCountRequest& aRequest);
+
+  bool
+  DoRequest(const MatchMvnoRequest& aRequest);
+
+  bool
+  DoRequest(const GetServiceStateEnabledRequest& aRequest);
+
+  nsresult
+  SendReply(const IccReply& aReply);
+
+  nsCOMPtr<nsIIcc> mIcc;
+};
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_icc_IccParent_h
--- a/dom/icc/moz.build
+++ b/dom/icc/moz.build
@@ -8,23 +8,31 @@ DIRS += ['interfaces']
 
 EXPORTS.mozilla.dom += [
     'Icc.h',
     'IccCardLockError.h',
     'IccInfo.h',
     'IccManager.h',
 ]
 
+EXPORTS.mozilla.dom.icc += [
+    'ipc/IccChild.h',
+    'ipc/IccParent.h',
+]
+
 UNIFIED_SOURCES += [
     'Assertions.cpp',
     'Icc.cpp',
     'IccCardLockError.cpp',
     "IccInfo.cpp",
     'IccListener.cpp',
     'IccManager.cpp',
+    'ipc/IccChild.cpp',
+    'ipc/IccIPCService.cpp',
+    'ipc/IccParent.cpp',
 ]
 
 IPDL_SOURCES += [
     'ipc/PIcc.ipdl',
     'ipc/PIccRequest.ipdl',
     'ipc/PIccTypes.ipdlh',
 ]
 
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -143,16 +143,17 @@
 
 #ifdef MOZ_NUWA_PROCESS
 #include <setjmp.h>
 #include "ipc/Nuwa.h"
 #endif
 
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/cellbroadcast/CellBroadcastIPCService.h"
+#include "mozilla/dom/icc/IccChild.h"
 #include "mozilla/dom/mobileconnection/MobileConnectionChild.h"
 #include "mozilla/dom/mobilemessage/SmsChild.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
 #include "mozilla/dom/PFileSystemRequestChild.h"
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "mozilla/dom/bluetooth/PBluetoothChild.h"
 #include "mozilla/dom/PFMRadioChild.h"
 #include "mozilla/ipc/InputStreamUtils.h"
@@ -175,16 +176,17 @@
 #include "mozilla/net/NeckoMessageUtils.h"
 #include "mozilla/RemoteSpellCheckEngineChild.h"
 
 using namespace mozilla;
 using namespace mozilla::docshell;
 using namespace mozilla::dom::bluetooth;
 using namespace mozilla::dom::cellbroadcast;
 using namespace mozilla::dom::devicestorage;
+using namespace mozilla::dom::icc;
 using namespace mozilla::dom::ipc;
 using namespace mozilla::dom::mobileconnection;
 using namespace mozilla::dom::mobilemessage;
 using namespace mozilla::dom::telephony;
 using namespace mozilla::dom::voicemail;
 using namespace mozilla::embedding;
 using namespace mozilla::hal_sandbox;
 using namespace mozilla::ipc;
@@ -1448,16 +1450,41 @@ ContentChild::AllocPHalChild()
 
 bool
 ContentChild::DeallocPHalChild(PHalChild* aHal)
 {
     delete aHal;
     return true;
 }
 
+PIccChild*
+ContentChild::SendPIccConstructor(PIccChild* aActor,
+                                  const uint32_t& aServiceId)
+{
+    // Add an extra ref for IPDL. Will be released in
+    // ContentChild::DeallocPIccChild().
+    static_cast<IccChild*>(aActor)->AddRef();
+    return PContentChild::SendPIccConstructor(aActor, aServiceId);
+}
+
+PIccChild*
+ContentChild::AllocPIccChild(const uint32_t& aServiceId)
+{
+    NS_NOTREACHED("No one should be allocating PIccChild actors");
+    return nullptr;
+}
+
+bool
+ContentChild::DeallocPIccChild(PIccChild* aActor)
+{
+    // IccChild is refcounted, must not be freed manually.
+    static_cast<IccChild*>(aActor)->Release();
+    return true;
+}
+
 asmjscache::PAsmJSCacheEntryChild*
 ContentChild::AllocPAsmJSCacheEntryChild(
                                     const asmjscache::OpenMode& aOpenMode,
                                     const asmjscache::WriteParams& aWriteParams,
                                     const IPC::Principal& aPrincipal)
 {
     NS_NOTREACHED("Should never get here!");
     return nullptr;
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -167,16 +167,23 @@ public:
     AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
                              const uint32_t& processType) MOZ_OVERRIDE;
     virtual bool
     DeallocPCrashReporterChild(PCrashReporterChild*) MOZ_OVERRIDE;
 
     virtual PHalChild* AllocPHalChild() MOZ_OVERRIDE;
     virtual bool DeallocPHalChild(PHalChild*) MOZ_OVERRIDE;
 
+    PIccChild*
+    SendPIccConstructor(PIccChild* aActor, const uint32_t& aServiceId);
+    virtual PIccChild*
+    AllocPIccChild(const uint32_t& aClientId) MOZ_OVERRIDE;
+    virtual bool
+    DeallocPIccChild(PIccChild* aActor) MOZ_OVERRIDE;
+
     virtual PMemoryReportRequestChild*
     AllocPMemoryReportRequestChild(const uint32_t& aGeneration,
                                    const bool& aAnonymize,
                                    const bool& aMinimizeMemoryUsage,
                                    const MaybeFileDesc& aDMDFile) MOZ_OVERRIDE;
     virtual bool
     DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) MOZ_OVERRIDE;
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -46,16 +46,17 @@
 #include "mozilla/dom/PContentBridgeParent.h"
 #include "mozilla/dom/PCycleCollectWithLogsParent.h"
 #include "mozilla/dom/PFMRadioParent.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
 #include "mozilla/dom/asmjscache/AsmJSCache.h"
 #include "mozilla/dom/bluetooth/PBluetoothParent.h"
 #include "mozilla/dom/cellbroadcast/CellBroadcastParent.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
+#include "mozilla/dom/icc/IccParent.h"
 #include "mozilla/dom/mobileconnection/MobileConnectionParent.h"
 #include "mozilla/dom/mobilemessage/SmsParent.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/telephony/TelephonyParent.h"
 #include "mozilla/dom/time/DateCacheCleaner.h"
 #include "mozilla/dom/voicemail/VoicemailParent.h"
 #include "mozilla/embedding/printingui/PrintingParent.h"
@@ -219,16 +220,17 @@ using base::ChildPrivileges;
 using base::KillProcess;
 
 #ifdef MOZ_CRASHREPORTER
 using namespace CrashReporter;
 #endif
 using namespace mozilla::dom::bluetooth;
 using namespace mozilla::dom::cellbroadcast;
 using namespace mozilla::dom::devicestorage;
+using namespace mozilla::dom::icc;
 using namespace mozilla::dom::indexedDB;
 using namespace mozilla::dom::power;
 using namespace mozilla::dom::mobileconnection;
 using namespace mozilla::dom::mobilemessage;
 using namespace mozilla::dom::telephony;
 using namespace mozilla::dom::voicemail;
 using namespace mozilla::embedding;
 using namespace mozilla::hal;
@@ -3375,16 +3377,37 @@ ContentParent::AllocPHalParent()
 
 bool
 ContentParent::DeallocPHalParent(hal_sandbox::PHalParent* aHal)
 {
     delete aHal;
     return true;
 }
 
+PIccParent*
+ContentParent::AllocPIccParent(const uint32_t& aServiceId)
+{
+    if (!AssertAppProcessPermission(this, "mobileconnection")) {
+        return nullptr;
+    }
+    IccParent* parent = new IccParent(aServiceId);
+    // We release this ref in DeallocPIccParent().
+    parent->AddRef();
+
+    return parent;
+}
+
+bool
+ContentParent::DeallocPIccParent(PIccParent* aActor)
+{
+    // IccParent is refcounted, must not be freed manually.
+    static_cast<IccParent*>(aActor)->Release();
+    return true;
+}
+
 PMemoryReportRequestParent*
 ContentParent::AllocPMemoryReportRequestParent(const uint32_t& aGeneration,
                                                const bool &aAnonymize,
                                                const bool &aMinimizeMemoryUsage,
                                                const MaybeFileDesc &aDMDFile)
 {
     MemoryReportRequestParent* parent = new MemoryReportRequestParent();
     return parent;
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -544,16 +544,19 @@ private:
     virtual bool RecvGetRandomValues(const uint32_t& length,
                                      InfallibleTArray<uint8_t>* randomValues) MOZ_OVERRIDE;
 
     virtual bool RecvIsSecureURI(const uint32_t& aType, const URIParams& aURI,
                                  const uint32_t& aFlags, bool* aIsSecureURI) MOZ_OVERRIDE;
 
     virtual bool DeallocPHalParent(PHalParent*) MOZ_OVERRIDE;
 
+    virtual PIccParent* AllocPIccParent(const uint32_t& aServiceId) MOZ_OVERRIDE;
+    virtual bool DeallocPIccParent(PIccParent* aActor) MOZ_OVERRIDE;
+
     virtual PMemoryReportRequestParent*
     AllocPMemoryReportRequestParent(const uint32_t& aGeneration,
                                     const bool &aAnonymize,
                                     const bool &aMinimizeMemoryUsage,
                                     const MaybeFileDesc &aDMDFile) MOZ_OVERRIDE;
     virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor) MOZ_OVERRIDE;
 
     virtual PCycleCollectWithLogsParent*