/* -*- 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 "mozilla/dom/mobileconnection/MobileConnectionChild.h" #include "MobileConnectionCallback.h" #include "mozilla/dom/MozMobileConnectionBinding.h" #include "nsComponentManagerUtils.h" using namespace mozilla::dom; using namespace mozilla::dom::mobileconnection; NS_IMPL_ISUPPORTS(MobileConnectionChild, nsIMobileConnection) MobileConnectionChild::MobileConnectionChild(uint32_t aServiceId) : mServiceId(aServiceId) , mLive(true) { MOZ_COUNT_CTOR(MobileConnectionChild); } void MobileConnectionChild::Init() { nsIMobileConnectionInfo* rawVoice; nsIMobileConnectionInfo* rawData; SendInit(&rawVoice, &rawData, &mLastNetwork, &mLastHomeNetwork, &mNetworkSelectionMode, &mRadioState, &mSupportedNetworkTypes); // Use dont_AddRef here because this instances is already AddRef-ed in // MobileConnectionIPCSerializer.h nsCOMPtr voice = dont_AddRef(rawVoice); mVoice = new MobileConnectionInfo(nullptr); mVoice->Update(voice); // Use dont_AddRef here because this instances is already AddRef-ed in // MobileConnectionIPCSerializer.h nsCOMPtr data = dont_AddRef(rawData); mData = new MobileConnectionInfo(nullptr); mData->Update(data); } void MobileConnectionChild::Shutdown() { if (mLive) { mLive = false; Send__delete__(this); } mListeners.Clear(); mVoice = nullptr; mData = nullptr; } // nsIMobileConnection NS_IMETHODIMP MobileConnectionChild::GetServiceId(uint32_t* aServiceId) { *aServiceId = mServiceId; return NS_OK; } NS_IMETHODIMP MobileConnectionChild::RegisterListener(nsIMobileConnectionListener* aListener) { NS_ENSURE_TRUE(!mListeners.Contains(aListener), NS_ERROR_UNEXPECTED); mListeners.AppendObject(aListener); return NS_OK; } NS_IMETHODIMP MobileConnectionChild::UnregisterListener(nsIMobileConnectionListener* aListener) { NS_ENSURE_TRUE(mListeners.Contains(aListener), NS_ERROR_UNEXPECTED); mListeners.RemoveObject(aListener); return NS_OK; } NS_IMETHODIMP MobileConnectionChild::GetVoice(nsIMobileConnectionInfo** aVoice) { RefPtr voice(mVoice); voice.forget(aVoice); return NS_OK; } NS_IMETHODIMP MobileConnectionChild::GetData(nsIMobileConnectionInfo** aData) { RefPtr data(mData); data.forget(aData); return NS_OK; } NS_IMETHODIMP MobileConnectionChild::GetRadioState(int32_t* aRadioState) { *aRadioState = mRadioState; return NS_OK; } NS_IMETHODIMP MobileConnectionChild::GetDeviceIdentities(nsIMobileDeviceIdentities** aIdentities) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP MobileConnectionChild::GetSupportedNetworkTypes(int32_t** aTypes, uint32_t* aLength) { NS_ENSURE_ARG(aTypes); NS_ENSURE_ARG(aLength); *aLength = mSupportedNetworkTypes.Length(); *aTypes = static_cast(moz_xmalloc((*aLength) * sizeof(int32_t))); NS_ENSURE_TRUE(*aTypes, NS_ERROR_OUT_OF_MEMORY); for (uint32_t i = 0; i < *aLength; i++) { (*aTypes)[i] = mSupportedNetworkTypes[i]; } return NS_OK; } NS_IMETHODIMP MobileConnectionChild::GetLastKnownNetwork(nsAString& aNetwork) { aNetwork = mLastNetwork; return NS_OK; } NS_IMETHODIMP MobileConnectionChild::GetLastKnownHomeNetwork(nsAString& aNetwork) { aNetwork = mLastHomeNetwork; return NS_OK; } NS_IMETHODIMP MobileConnectionChild::GetNetworkSelectionMode(int32_t* aMode) { *aMode = mNetworkSelectionMode; return NS_OK; } NS_IMETHODIMP MobileConnectionChild::GetNetworks(nsIMobileConnectionCallback* aCallback) { return SendRequest(GetNetworksRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::SelectNetwork(nsIMobileNetworkInfo* aNetwork, nsIMobileConnectionCallback* aCallback) { nsCOMPtr network = aNetwork; // We release the ref after serializing process is finished in // MobileConnectionIPCSerializer. return SendRequest(SelectNetworkRequest(network.forget().take()), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::SelectNetworkAutomatically(nsIMobileConnectionCallback* aCallback) { return SendRequest(SelectNetworkAutoRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::SetPreferredNetworkType(int32_t aType, nsIMobileConnectionCallback* aCallback) { return SendRequest(SetPreferredNetworkTypeRequest(aType), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::GetPreferredNetworkType(nsIMobileConnectionCallback* aCallback) { return SendRequest(GetPreferredNetworkTypeRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::SetRoamingPreference(int32_t aMode, nsIMobileConnectionCallback* aCallback) { return SendRequest(SetRoamingPreferenceRequest(aMode), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::GetRoamingPreference(nsIMobileConnectionCallback* aCallback) { return SendRequest(GetRoamingPreferenceRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::SetVoicePrivacyMode(bool aEnabled, nsIMobileConnectionCallback* aCallback) { return SendRequest(SetVoicePrivacyModeRequest(aEnabled), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::GetVoicePrivacyMode(nsIMobileConnectionCallback* aCallback) { return SendRequest(GetVoicePrivacyModeRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::SetCallForwarding(uint16_t aAction, uint16_t aReason, const nsAString& aNumber, uint16_t aTimeSeconds, uint16_t aServiceClass, nsIMobileConnectionCallback* aCallback) { return SendRequest(SetCallForwardingRequest(aAction, aReason, nsString(aNumber), aTimeSeconds, aServiceClass), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::GetCallForwarding(uint16_t aReason, nsIMobileConnectionCallback* aCallback) { return SendRequest(GetCallForwardingRequest(aReason), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::SetCallBarring(uint16_t aProgram, bool aEnabled, const nsAString& aPassword, uint16_t aServiceClass, nsIMobileConnectionCallback* aCallback) { return SendRequest(SetCallBarringRequest(aProgram, aEnabled, nsString(aPassword), aServiceClass), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::GetCallBarring(uint16_t aProgram, const nsAString& aPassword, uint16_t aServiceClass, nsIMobileConnectionCallback* aCallback) { return SendRequest(GetCallBarringRequest(aProgram, nsString(aPassword), aServiceClass), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::ChangeCallBarringPassword(const nsAString& aPin, const nsAString& aNewPin, nsIMobileConnectionCallback* aCallback) { return SendRequest(ChangeCallBarringPasswordRequest(nsString(aPin), nsString(aNewPin)), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::SetCallWaiting(bool aEnabled, uint16_t aServiceClass, nsIMobileConnectionCallback* aCallback) { return SendRequest(SetCallWaitingRequest(aEnabled, aServiceClass), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::GetCallWaiting(nsIMobileConnectionCallback* aCallback) { return SendRequest(GetCallWaitingRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::SetCallingLineIdRestriction(uint16_t aMode, nsIMobileConnectionCallback* aCallback) { return SendRequest(SetCallingLineIdRestrictionRequest(aMode), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::GetCallingLineIdRestriction(nsIMobileConnectionCallback* aCallback) { return SendRequest(GetCallingLineIdRestrictionRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::ExitEmergencyCbMode(nsIMobileConnectionCallback* aCallback) { return SendRequest(ExitEmergencyCbModeRequest(), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::SetRadioEnabled(bool aEnabled, nsIMobileConnectionCallback* aCallback) { return SendRequest(SetRadioEnabledRequest(aEnabled), aCallback) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP MobileConnectionChild::GetNeighboringCellIds(nsINeighboringCellIdsCallback* aCallback) { // This function is supported in chrome context only. return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP MobileConnectionChild::GetCellInfoList(nsICellInfoListCallback* aCallback) { // This function is supported in chrome context only. return NS_ERROR_NOT_IMPLEMENTED; } bool MobileConnectionChild::SendRequest(const MobileConnectionRequest& aRequest, nsIMobileConnectionCallback* aCallback) { NS_ENSURE_TRUE(mLive, false); // Deallocated in MobileConnectionChild::DeallocPMobileConnectionRequestChild(). MobileConnectionRequestChild* actor = new MobileConnectionRequestChild(aCallback); SendPMobileConnectionRequestConstructor(actor, aRequest); return true; } void MobileConnectionChild::ActorDestroy(ActorDestroyReason why) { mLive = false; } PMobileConnectionRequestChild* MobileConnectionChild::AllocPMobileConnectionRequestChild(const MobileConnectionRequest& request) { MOZ_CRASH("Caller is supposed to manually construct a request!"); } bool MobileConnectionChild::DeallocPMobileConnectionRequestChild(PMobileConnectionRequestChild* aActor) { delete aActor; return true; } bool MobileConnectionChild::RecvNotifyVoiceInfoChanged(nsIMobileConnectionInfo* const& aInfo) { // Use dont_AddRef here because this instances is already AddRef-ed in // MobileConnectionIPCSerializer.h nsCOMPtr voice = dont_AddRef(aInfo); mVoice->Update(voice); for (int32_t i = 0; i < mListeners.Count(); i++) { mListeners[i]->NotifyVoiceChanged(); } return true; } bool MobileConnectionChild::RecvNotifyDataInfoChanged(nsIMobileConnectionInfo* const& aInfo) { // Use dont_AddRef here because this instances is already AddRef-ed in // MobileConnectionIPCSerializer.h nsCOMPtr data = dont_AddRef(aInfo); mData->Update(data); for (int32_t i = 0; i < mListeners.Count(); i++) { mListeners[i]->NotifyDataChanged(); } return true; } bool MobileConnectionChild::RecvNotifyDataError(const nsString& aMessage) { for (int32_t i = 0; i < mListeners.Count(); i++) { mListeners[i]->NotifyDataError(aMessage); } return true; } bool MobileConnectionChild::RecvNotifyCFStateChanged(const uint16_t& aAction, const uint16_t& aReason, const nsString& aNumber, const uint16_t& aTimeSeconds, const uint16_t& aServiceClass) { for (int32_t i = 0; i < mListeners.Count(); i++) { mListeners[i]->NotifyCFStateChanged(aAction, aReason, aNumber, aTimeSeconds, aServiceClass); } return true; } bool MobileConnectionChild::RecvNotifyEmergencyCbModeChanged(const bool& aActive, const uint32_t& aTimeoutMs) { for (int32_t i = 0; i < mListeners.Count(); i++) { mListeners[i]->NotifyEmergencyCbModeChanged(aActive, aTimeoutMs); } return true; } bool MobileConnectionChild::RecvNotifyOtaStatusChanged(const nsString& aStatus) { for (int32_t i = 0; i < mListeners.Count(); i++) { mListeners[i]->NotifyOtaStatusChanged(aStatus); } return true; } bool MobileConnectionChild::RecvNotifyRadioStateChanged(const int32_t& aRadioState) { mRadioState = aRadioState; for (int32_t i = 0; i < mListeners.Count(); i++) { mListeners[i]->NotifyRadioStateChanged(); } return true; } bool MobileConnectionChild::RecvNotifyClirModeChanged(const uint32_t& aMode) { for (int32_t i = 0; i < mListeners.Count(); i++) { mListeners[i]->NotifyClirModeChanged(aMode); } return true; } bool MobileConnectionChild::RecvNotifyLastNetworkChanged(const nsString& aNetwork) { mLastNetwork.Assign(aNetwork); return true; } bool MobileConnectionChild::RecvNotifyLastHomeNetworkChanged(const nsString& aNetwork) { mLastHomeNetwork.Assign(aNetwork); return true; } bool MobileConnectionChild::RecvNotifyNetworkSelectionModeChanged(const int32_t& aMode) { mNetworkSelectionMode = aMode; return true; } /****************************************************************************** * MobileConnectionRequestChild ******************************************************************************/ void MobileConnectionRequestChild::ActorDestroy(ActorDestroyReason why) { mRequestCallback = nullptr; } bool MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccess& aReply) { return NS_SUCCEEDED(mRequestCallback->NotifySuccess()); } bool MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessBoolean& aReply) { return NS_SUCCEEDED(mRequestCallback->NotifySuccessWithBoolean(aReply.result())); } bool MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessNetworks& aReply) { uint32_t count = aReply.results().Length(); nsTArray> results; for (uint32_t i = 0; i < count; i++) { // Use dont_AddRef here because these instances are already AddRef-ed in // MobileConnectionIPCSerializer.h nsCOMPtr item = dont_AddRef(aReply.results()[i]); results.AppendElement(item); } return NS_SUCCEEDED(mRequestCallback->NotifyGetNetworksSuccess(count, const_cast(aReply.results().Elements()))); } bool MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessCallForwarding& aReply) { uint32_t count = aReply.results().Length(); nsTArray> results; for (uint32_t i = 0; i < count; i++) { // Use dont_AddRef here because these instances are already AddRef-ed in // MobileConnectionIPCSerializer.h nsCOMPtr item = dont_AddRef(aReply.results()[i]); results.AppendElement(item); } return NS_SUCCEEDED(mRequestCallback->NotifyGetCallForwardingSuccess( count, const_cast(aReply.results().Elements()))); } bool MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessCallBarring& aReply) { return NS_SUCCEEDED(mRequestCallback->NotifyGetCallBarringSuccess(aReply.program(), aReply.enabled(), aReply.serviceClass())); } bool MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessCallWaiting& aReply) { return NS_SUCCEEDED(mRequestCallback->NotifyGetCallWaitingSuccess(aReply.serviceClass())); } bool MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessClirStatus& aReply) { return NS_SUCCEEDED(mRequestCallback->NotifyGetClirStatusSuccess(aReply.n(), aReply.m())); } bool MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessPreferredNetworkType& aReply) { return NS_SUCCEEDED(mRequestCallback->NotifyGetPreferredNetworkTypeSuccess(aReply.type())); } bool MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessRoamingPreference& aReply) { return NS_SUCCEEDED(mRequestCallback->NotifyGetRoamingPreferenceSuccess(aReply.mode())); } bool MobileConnectionRequestChild::DoReply(const MobileConnectionReplyError& aReply) { return NS_SUCCEEDED(mRequestCallback->NotifyError(aReply.message())); } bool MobileConnectionRequestChild::Recv__delete__(const MobileConnectionReply& aReply) { MOZ_ASSERT(mRequestCallback); switch (aReply.type()) { case MobileConnectionReply::TMobileConnectionReplySuccess: return DoReply(aReply.get_MobileConnectionReplySuccess()); case MobileConnectionReply::TMobileConnectionReplySuccessBoolean: return DoReply(aReply.get_MobileConnectionReplySuccessBoolean()); case MobileConnectionReply::TMobileConnectionReplySuccessNetworks: return DoReply(aReply.get_MobileConnectionReplySuccessNetworks()); case MobileConnectionReply::TMobileConnectionReplySuccessCallForwarding: return DoReply(aReply.get_MobileConnectionReplySuccessCallForwarding()); case MobileConnectionReply::TMobileConnectionReplySuccessCallBarring: return DoReply(aReply.get_MobileConnectionReplySuccessCallBarring()); case MobileConnectionReply::TMobileConnectionReplySuccessCallWaiting: return DoReply(aReply.get_MobileConnectionReplySuccessCallWaiting()); case MobileConnectionReply::TMobileConnectionReplySuccessClirStatus: return DoReply(aReply.get_MobileConnectionReplySuccessClirStatus()); case MobileConnectionReply::TMobileConnectionReplySuccessPreferredNetworkType: return DoReply(aReply.get_MobileConnectionReplySuccessPreferredNetworkType()); case MobileConnectionReply::TMobileConnectionReplySuccessRoamingPreference: return DoReply(aReply.get_MobileConnectionReplySuccessRoamingPreference()); case MobileConnectionReply::TMobileConnectionReplyError: return DoReply(aReply.get_MobileConnectionReplyError()); default: MOZ_CRASH("Received invalid response type!"); } return false; }