/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=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/. */ #include "IccInfo.h" #include "mozilla/dom/icc/IccChild.h" #include "mozilla/dom/icc/IccIPCUtils.h" #include "nsIStkCmdFactory.h" #include "nsIStkProactiveCmd.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; } bool IccChild::RecvNotifyStkCommand(const nsString& aStkProactiveCmd) { nsCOMPtr cmdFactory = do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); NS_ENSURE_TRUE(cmdFactory, false); nsCOMPtr cmd; cmdFactory->InflateCommand(aStkProactiveCmd, getter_AddRefs(cmd)); NS_ENSURE_TRUE(cmd, false); for (int32_t i = 0; i < mListeners.Count(); i++) { mListeners[i]->NotifyStkCommand(cmd); } return true; } bool IccChild::RecvNotifyStkSessionEnd() { for (int32_t i = 0; i < mListeners.Count(); i++) { mListeners[i]->NotifyStkSessionEnd(); } 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); RefPtr 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) { nsAutoString oldIccType; nsAutoString 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 info(mIccInfo); info.forget(aIccInfo); return NS_OK; } NS_IMETHODIMP IccChild::GetCardState(uint32_t* aCardState) { *aCardState = mCardState; return NS_OK; } NS_IMETHODIMP IccChild::GetImsi(nsAString & aImsi) { NS_WARNING("IMSI shall not directly be fetched in child process."); return NS_ERROR_NOT_IMPLEMENTED; } 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, nsAutoString(aPassword), nsAutoString(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, nsAutoString(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, nsAutoString(aPassword), nsAutoString(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, nsAutoString(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; } NS_IMETHODIMP IccChild::IccOpenChannel(const nsAString& aAid, nsIIccChannelCallback* aCallback) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP IccChild::IccExchangeAPDU(int32_t aChannel, uint8_t aCla, uint8_t aIns, uint8_t aP1, uint8_t aP2, int16_t aP3, const nsAString & aData, nsIIccChannelCallback* aCallback) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP IccChild::IccCloseChannel(int32_t aChannel, nsIIccChannelCallback* aCallback) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP IccChild::SendStkResponse(nsIStkProactiveCmd* aCommand, nsIStkTerminalResponse* aResponse) { nsCOMPtr cmdFactory = do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); NS_ENSURE_TRUE(cmdFactory, NS_ERROR_FAILURE); nsAutoString cmd, response; nsresult rv = cmdFactory->DeflateCommand(aCommand, cmd); NS_ENSURE_SUCCESS(rv, rv); rv = cmdFactory->DeflateResponse(aResponse, response); NS_ENSURE_SUCCESS(rv, rv); return PIccChild::SendStkResponse(cmd, response) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP IccChild::SendStkMenuSelection(uint16_t aItemIdentifier, bool aHelpRequested) { return PIccChild::SendStkMenuSelection(aItemIdentifier, aHelpRequested) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP IccChild::SendStkTimerExpiration(uint16_t aTimerId, uint32_t aTimerValue) { return PIccChild::SendStkTimerExpiration(aTimerId, aTimerValue) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP IccChild::SendStkEventDownload(nsIStkDownloadEvent* aEvent) { MOZ_ASSERT(aEvent); nsCOMPtr cmdFactory = do_GetService(ICC_STK_CMD_FACTORY_CONTRACTID); NS_ENSURE_TRUE(cmdFactory, NS_ERROR_FAILURE); nsAutoString event; nsresult rv = cmdFactory->DeflateDownloadEvent(aEvent, event); NS_ENSURE_SUCCESS(rv, rv); return PIccChild::SendStkEventDownload(event) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP IccChild::ReadContacts(uint32_t aContactType, nsIIccCallback* aRequestReply) { return SendRequest(ReadContactsRequest(aContactType), aRequestReply) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP IccChild::UpdateContact(uint32_t aContactType, nsIIccContact* aContact, const nsAString& aPin2, nsIIccCallback* aRequestReply) { MOZ_ASSERT(aContact); IccContactData contactData; IccIPCUtils::GetIccContactDataFromIccContact(aContact, contactData); return SendRequest(UpdateContactRequest(aContactType, nsAutoString(aPin2), contactData), 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())); } case IccReply::TIccReplyReadContacts: { const nsTArray& data = aResponse.get_IccReplyReadContacts().contacts(); uint32_t count = data.Length(); nsCOMArray contactList; nsresult rv; for (uint32_t i = 0; i < count; i++) { nsCOMPtr contact; rv = IccContact::Create(data[i].id(), data[i].names(), data[i].numbers(), data[i].emails(), getter_AddRefs(contact)); NS_ENSURE_SUCCESS(rv, false); contactList.AppendElement(contact); } rv = mRequestReply->NotifyRetrievedIccContacts(contactList.Elements(), count); return NS_SUCCEEDED(rv); } case IccReply::TIccReplyUpdateContact: { IccContactData data = aResponse.get_IccReplyUpdateContact().contact(); nsCOMPtr contact; IccContact::Create(data.id(), data.names(), data.numbers(), data.emails(), getter_AddRefs(contact)); return NS_SUCCEEDED( mRequestReply->NotifyUpdatedIccContact(contact)); } default: MOZ_CRASH("Received invalid response type!"); } return true; } } // namespace icc } // namespace dom } // namespace mozilla