/* 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.h" #include "mozilla/dom/DOMRequest.h" #include "mozilla/dom/IccInfo.h" #include "mozilla/dom/MozStkCommandEvent.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/ScriptSettings.h" #include "nsIIccInfo.h" #include "nsIIccProvider.h" #include "nsJSON.h" #include "nsRadioInterfaceLayer.h" #include "nsServiceManagerUtils.h" namespace mozilla { namespace dom { namespace { bool IsPukCardLockType(IccLockType aLockType) { switch(aLockType) { case IccLockType::Puk: case IccLockType::Puk2: case IccLockType::NckPuk: case IccLockType::Nck1Puk: case IccLockType::Nck2Puk: case IccLockType::HnckPuk: case IccLockType::CckPuk: case IccLockType::SpckPuk: case IccLockType::RcckPuk: case IccLockType::RspckPuk: return true; default: return false; } } } // anonymous namespace NS_IMPL_CYCLE_COLLECTION_INHERITED(Icc, DOMEventTargetHelper, mIccInfo) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Icc) NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(Icc, DOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(Icc, DOMEventTargetHelper) Icc::Icc(nsPIDOMWindow* aWindow, long aClientId, nsIIccInfo* aIccInfo) : mLive(true) , mClientId(aClientId) { BindToOwner(aWindow); mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID); if (aIccInfo) { aIccInfo->GetIccid(mIccId); UpdateIccInfo(aIccInfo); } // Not being able to acquire the provider isn't fatal since we check // for it explicitly below. if (!mProvider) { NS_WARNING("Could not acquire nsIIccProvider!"); } } void Icc::Shutdown() { mIccInfo.SetNull(); mProvider = nullptr; mLive = false; } nsresult Icc::NotifyEvent(const nsAString& aName) { return DispatchTrustedEvent(aName); } nsresult Icc::NotifyStkEvent(const nsAString& aName, const nsAString& aMessage) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(GetOwner()))) { return NS_ERROR_UNEXPECTED; } JSContext* cx = jsapi.cx(); JS::Rooted value(cx); if (!aMessage.IsEmpty()) { nsCOMPtr json(new nsJSON()); nsresult rv = json->DecodeToJSVal(aMessage, cx, &value); NS_ENSURE_SUCCESS(rv, rv); } else { value = JS::NullValue(); } MozStkCommandEventInit init; init.mBubbles = false; init.mCancelable = false; init.mCommand = value; nsRefPtr event = MozStkCommandEvent::Constructor(this, aName, init); return DispatchTrustedEvent(event); } void Icc::UpdateIccInfo(nsIIccInfo* aIccInfo) { if (!aIccInfo) { mIccInfo.SetNull(); return; } nsCOMPtr gsmIccInfo(do_QueryInterface(aIccInfo)); if (gsmIccInfo) { if (mIccInfo.IsNull() || !mIccInfo.Value().IsMozGsmIccInfo()) { mIccInfo.SetValue().SetAsMozGsmIccInfo() = new GsmIccInfo(GetOwner()); } mIccInfo.Value().GetAsMozGsmIccInfo().get()->Update(gsmIccInfo); return; } nsCOMPtr cdmaIccInfo(do_QueryInterface(aIccInfo)); if (cdmaIccInfo) { if (mIccInfo.IsNull() || !mIccInfo.Value().IsMozCdmaIccInfo()) { mIccInfo.SetValue().SetAsMozCdmaIccInfo() = new CdmaIccInfo(GetOwner()); } mIccInfo.Value().GetAsMozCdmaIccInfo().get()->Update(cdmaIccInfo); return; } if (mIccInfo.IsNull() || !mIccInfo.Value().IsMozIccInfo()) { mIccInfo.SetValue().SetAsMozIccInfo() = new IccInfo(GetOwner()); } mIccInfo.Value().GetAsMozIccInfo().get()->Update(aIccInfo); } // WrapperCache JSObject* Icc::WrapObject(JSContext* aCx) { return MozIccBinding::Wrap(aCx, this); } // MozIcc WebIDL void Icc::GetIccInfo(Nullable& aIccInfo) const { aIccInfo = mIccInfo; } Nullable Icc::GetCardState() const { Nullable result; uint32_t cardState = nsIIccProvider::CARD_STATE_UNDETECTED; if (mProvider && NS_SUCCEEDED(mProvider->GetCardState(mClientId, &cardState)) && cardState != nsIIccProvider::CARD_STATE_UNDETECTED) { MOZ_ASSERT(cardState < static_cast(IccCardState::EndGuard_)); result.SetValue(static_cast(cardState)); } return result; } void Icc::SendStkResponse(const JSContext* aCx, JS::Handle aCommand, JS::Handle aResponse, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return; } nsresult rv = mProvider->SendStkResponse(mClientId, GetOwner(), aCommand, aResponse); if (NS_FAILED(rv)) { aRv.Throw(rv); } } void Icc::SendStkMenuSelection(uint16_t aItemIdentifier, bool aHelpRequested, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return; } nsresult rv = mProvider->SendStkMenuSelection(mClientId, GetOwner(), aItemIdentifier, aHelpRequested); if (NS_FAILED(rv)) { aRv.Throw(rv); } } void Icc::SendStkTimerExpiration(const JSContext* aCx, JS::Handle aTimer, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return; } nsresult rv = mProvider->SendStkTimerExpiration(mClientId, GetOwner(), aTimer); if (NS_FAILED(rv)) { aRv.Throw(rv); } } void Icc::SendStkEventDownload(const JSContext* aCx, JS::Handle aEvent, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return; } nsresult rv = mProvider->SendStkEventDownload(mClientId, GetOwner(), aEvent); if (NS_FAILED(rv)) { aRv.Throw(rv); } } already_AddRefed Icc::GetCardLock(IccLockType aLockType, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr request; nsresult rv = mProvider->GetCardLockEnabled(mClientId, GetOwner(), static_cast(aLockType), getter_AddRefs(request)); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget().downcast(); } already_AddRefed Icc::UnlockCardLock(const IccUnlockCardLockOptions& aOptions, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr request; const nsString& password = IsPukCardLockType(aOptions.mLockType) ? aOptions.mPuk : aOptions.mPin; nsresult rv = mProvider->UnlockCardLock(mClientId, GetOwner(), static_cast(aOptions.mLockType), password, aOptions.mNewPin, getter_AddRefs(request)); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget().downcast(); } already_AddRefed Icc::SetCardLock(const IccSetCardLockOptions& aOptions, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsresult rv; nsRefPtr request; if (aOptions.mEnabled.WasPassed()) { // Enable card lock. const nsString& password = (aOptions.mLockType == IccLockType::Fdn) ? aOptions.mPin2 : aOptions.mPin; rv = mProvider->SetCardLockEnabled(mClientId, GetOwner(), static_cast(aOptions.mLockType), password, aOptions.mEnabled.Value(), getter_AddRefs(request)); } else { // Change card lock password. rv = mProvider->ChangeCardLockPassword(mClientId, GetOwner(), static_cast(aOptions.mLockType), aOptions.mPin, aOptions.mNewPin, getter_AddRefs(request)); } if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget().downcast(); } already_AddRefed Icc::GetCardLockRetryCount(IccLockType aLockType, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr request; nsresult rv = mProvider->GetCardLockRetryCount(mClientId, GetOwner(), static_cast(aLockType), getter_AddRefs(request)); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget().downcast(); } already_AddRefed Icc::ReadContacts(IccContactType aContactType, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr request; nsresult rv = mProvider->ReadContacts(mClientId, GetOwner(), static_cast(aContactType), getter_AddRefs(request)); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget().downcast(); } already_AddRefed Icc::UpdateContact(const JSContext* aCx, IccContactType aContactType, JS::Handle aContact, const nsAString& aPin2, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr request; nsresult rv = mProvider->UpdateContact(mClientId, GetOwner(), static_cast(aContactType), aContact, aPin2, getter_AddRefs(request)); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget().downcast(); } already_AddRefed Icc::MatchMvno(IccMvnoType aMvnoType, const nsAString& aMvnoData, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr request; nsresult rv = mProvider->MatchMvno(mClientId, GetOwner(), static_cast(aMvnoType), aMvnoData, getter_AddRefs(request)); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return request.forget().downcast(); } already_AddRefed Icc::GetServiceState(IccService aService, ErrorResult& aRv) { if (!mProvider) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsCOMPtr supports; nsresult rv = mProvider->GetServiceState(mClientId, GetOwner(), static_cast(aService), getter_AddRefs(supports)); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } nsCOMPtr promise = do_QueryInterface(supports); return promise.forget(); } } // namespace dom } // namespace mozilla