michael@0: /* -*- Mode: C++ tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/dom/telephony/TelephonyParent.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: michael@0: USING_TELEPHONY_NAMESPACE michael@0: michael@0: /******************************************************************************* michael@0: * TelephonyParent michael@0: ******************************************************************************/ michael@0: michael@0: NS_IMPL_ISUPPORTS(TelephonyParent, nsITelephonyListener) michael@0: michael@0: TelephonyParent::TelephonyParent() michael@0: : mActorDestroyed(false) michael@0: , mRegistered(false) michael@0: { michael@0: } michael@0: michael@0: void michael@0: TelephonyParent::ActorDestroy(ActorDestroyReason why) michael@0: { michael@0: // The child process could die before this asynchronous notification, in which michael@0: // case ActorDestroy() was called and mActorDestroyed is set to true. Return michael@0: // an error here to avoid sending a message to the dead process. michael@0: mActorDestroyed = true; michael@0: michael@0: // Try to unregister listener if we're still registered. michael@0: RecvUnregisterListener(); michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvPTelephonyRequestConstructor(PTelephonyRequestParent* aActor, michael@0: const IPCTelephonyRequest& aRequest) michael@0: { michael@0: TelephonyRequestParent* actor = static_cast(aActor); michael@0: michael@0: switch (aRequest.type()) { michael@0: case IPCTelephonyRequest::TEnumerateCallsRequest: michael@0: return actor->DoRequest(aRequest.get_EnumerateCallsRequest()); michael@0: case IPCTelephonyRequest::TDialRequest: michael@0: return actor->DoRequest(aRequest.get_DialRequest()); michael@0: default: michael@0: MOZ_CRASH("Unknown type!"); michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: PTelephonyRequestParent* michael@0: TelephonyParent::AllocPTelephonyRequestParent(const IPCTelephonyRequest& aRequest) michael@0: { michael@0: TelephonyRequestParent* actor = new TelephonyRequestParent(); michael@0: // Add an extra ref for IPDL. Will be released in michael@0: // TelephonyParent::DeallocPTelephonyRequestParent(). michael@0: NS_ADDREF(actor); michael@0: michael@0: return actor; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::DeallocPTelephonyRequestParent(PTelephonyRequestParent* aActor) michael@0: { michael@0: // TelephonyRequestParent is refcounted, must not be freed manually. michael@0: static_cast(aActor)->Release(); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::Recv__delete__() michael@0: { michael@0: return true; // Unregister listener in TelephonyParent::ActorDestroy(). michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvRegisterListener() michael@0: { michael@0: NS_ENSURE_TRUE(!mRegistered, true); michael@0: michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: mRegistered = NS_SUCCEEDED(provider->RegisterListener(this)); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvUnregisterListener() michael@0: { michael@0: NS_ENSURE_TRUE(mRegistered, true); michael@0: michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: mRegistered = !NS_SUCCEEDED(provider->UnregisterListener(this)); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvHangUpCall(const uint32_t& aClientId, michael@0: const uint32_t& aCallIndex) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->HangUp(aClientId, aCallIndex); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvAnswerCall(const uint32_t& aClientId, michael@0: const uint32_t& aCallIndex) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->AnswerCall(aClientId, aCallIndex); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvRejectCall(const uint32_t& aClientId, michael@0: const uint32_t& aCallIndex) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->RejectCall(aClientId, aCallIndex); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvHoldCall(const uint32_t& aClientId, michael@0: const uint32_t& aCallIndex) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->HoldCall(aClientId, aCallIndex); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvResumeCall(const uint32_t& aClientId, michael@0: const uint32_t& aCallIndex) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->ResumeCall(aClientId, aCallIndex); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvConferenceCall(const uint32_t& aClientId) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->ConferenceCall(aClientId); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvSeparateCall(const uint32_t& aClientId, michael@0: const uint32_t& aCallIndex) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->SeparateCall(aClientId, aCallIndex); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvHoldConference(const uint32_t& aClientId) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->HoldConference(aClientId); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvResumeConference(const uint32_t& aClientId) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->ResumeConference(aClientId); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvStartTone(const uint32_t& aClientId, const nsString& aTone) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->StartTone(aClientId, aTone); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvStopTone(const uint32_t& aClientId) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->StopTone(aClientId); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvGetMicrophoneMuted(bool* aMuted) michael@0: { michael@0: *aMuted = false; michael@0: michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->GetMicrophoneMuted(aMuted); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvSetMicrophoneMuted(const bool& aMuted) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->SetMicrophoneMuted(aMuted); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvGetSpeakerEnabled(bool* aEnabled) michael@0: { michael@0: *aEnabled = false; michael@0: michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->GetSpeakerEnabled(aEnabled); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyParent::RecvSetSpeakerEnabled(const bool& aEnabled) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: NS_ENSURE_TRUE(provider, true); michael@0: michael@0: provider->SetSpeakerEnabled(aEnabled); michael@0: return true; michael@0: } michael@0: michael@0: // nsITelephonyListener michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyParent::CallStateChanged(uint32_t aClientId, michael@0: uint32_t aCallIndex, michael@0: uint16_t aCallState, michael@0: const nsAString& aNumber, michael@0: bool aIsActive, michael@0: bool aIsOutgoing, michael@0: bool aIsEmergency, michael@0: bool aIsConference, michael@0: bool aIsSwitchable, michael@0: bool aIsMergeable) michael@0: { michael@0: NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); michael@0: michael@0: IPCCallStateData data(aCallIndex, aCallState, nsString(aNumber), michael@0: aIsActive, aIsOutgoing, aIsEmergency, aIsConference, michael@0: aIsSwitchable, aIsMergeable); michael@0: return SendNotifyCallStateChanged(aClientId, data) ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyParent::ConferenceCallStateChanged(uint16_t aCallState) michael@0: { michael@0: NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); michael@0: michael@0: return SendNotifyConferenceCallStateChanged(aCallState) ? NS_OK michael@0: : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyParent::EnumerateCallStateComplete() michael@0: { michael@0: MOZ_CRASH("Not a EnumerateCalls request!"); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyParent::EnumerateCallState(uint32_t aClientId, michael@0: uint32_t aCallIndex, michael@0: uint16_t aCallState, michael@0: const nsAString& aNumber, michael@0: bool aIsActive, michael@0: bool aIsOutgoing, michael@0: bool aIsEmergency, michael@0: bool aIsConference, michael@0: bool aIsSwitchable, michael@0: bool aIsMergeable) michael@0: { michael@0: MOZ_CRASH("Not a EnumerateCalls request!"); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyParent::NotifyCdmaCallWaiting(uint32_t aClientId, michael@0: const nsAString& aNumber) michael@0: { michael@0: NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); michael@0: michael@0: return SendNotifyCdmaCallWaiting(aClientId, nsString(aNumber)) michael@0: ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyParent::NotifyConferenceError(const nsAString& aName, michael@0: const nsAString& aMessage) michael@0: { michael@0: NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); michael@0: michael@0: return SendNotifyConferenceError(nsString(aName), nsString(aMessage)) ? NS_OK michael@0: : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyParent::NotifyError(uint32_t aClientId, michael@0: int32_t aCallIndex, michael@0: const nsAString& aError) michael@0: { michael@0: NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); michael@0: michael@0: return SendNotifyCallError(aClientId, aCallIndex, nsString(aError)) michael@0: ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyParent::SupplementaryServiceNotification(uint32_t aClientId, michael@0: int32_t aCallIndex, michael@0: uint16_t aNotification) michael@0: { michael@0: NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); michael@0: michael@0: return SendNotifySupplementaryService(aClientId, aCallIndex, aNotification) michael@0: ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: /******************************************************************************* michael@0: * TelephonyRequestParent michael@0: ******************************************************************************/ michael@0: michael@0: NS_IMPL_ISUPPORTS(TelephonyRequestParent, michael@0: nsITelephonyListener, michael@0: nsITelephonyCallback) michael@0: michael@0: TelephonyRequestParent::TelephonyRequestParent() michael@0: : mActorDestroyed(false) michael@0: { michael@0: } michael@0: michael@0: void michael@0: TelephonyRequestParent::ActorDestroy(ActorDestroyReason why) michael@0: { michael@0: // The child process could die before this asynchronous notification, in which michael@0: // case ActorDestroy() was called and mActorDestroyed is set to true. Return michael@0: // an error here to avoid sending a message to the dead process. michael@0: mActorDestroyed = true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyRequestParent::DoRequest(const EnumerateCallsRequest& aRequest) michael@0: { michael@0: nsresult rv = NS_ERROR_FAILURE; michael@0: michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: if (provider) { michael@0: rv = provider->EnumerateCalls(this); michael@0: } michael@0: michael@0: if (NS_FAILED(rv)) { michael@0: return NS_SUCCEEDED(EnumerateCallStateComplete()); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: TelephonyRequestParent::DoRequest(const DialRequest& aRequest) michael@0: { michael@0: nsCOMPtr provider = michael@0: do_GetService(TELEPHONY_PROVIDER_CONTRACTID); michael@0: if (provider) { michael@0: provider->Dial(aRequest.clientId(), aRequest.number(), michael@0: aRequest.isEmergency(), this); michael@0: } else { michael@0: return NS_SUCCEEDED(NotifyDialError(NS_LITERAL_STRING("InvalidStateError"))); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: // nsITelephonyListener michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyRequestParent::CallStateChanged(uint32_t aClientId, michael@0: uint32_t aCallIndex, michael@0: uint16_t aCallState, michael@0: const nsAString& aNumber, michael@0: bool aIsActive, michael@0: bool aIsOutgoing, michael@0: bool aIsEmergency, michael@0: bool aIsConference, michael@0: bool aIsSwitchable, michael@0: bool aIsMergeable) michael@0: { michael@0: MOZ_CRASH("Not a TelephonyParent!"); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyRequestParent::ConferenceCallStateChanged(uint16_t aCallState) michael@0: { michael@0: MOZ_CRASH("Not a TelephonyParent!"); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyRequestParent::EnumerateCallStateComplete() michael@0: { michael@0: NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); michael@0: michael@0: return Send__delete__(this, EnumerateCallsResponse()) ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyRequestParent::EnumerateCallState(uint32_t aClientId, michael@0: uint32_t aCallIndex, michael@0: uint16_t aCallState, michael@0: const nsAString& aNumber, michael@0: bool aIsActive, michael@0: bool aIsOutgoing, michael@0: bool aIsEmergency, michael@0: bool aIsConference, michael@0: bool aIsSwitchable, michael@0: bool aIsMergeable) michael@0: { michael@0: NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); michael@0: michael@0: IPCCallStateData data(aCallIndex, aCallState, nsString(aNumber), michael@0: aIsActive, aIsOutgoing, aIsEmergency, aIsConference, michael@0: aIsSwitchable, aIsMergeable); michael@0: return SendNotifyEnumerateCallState(aClientId, data) ? NS_OK michael@0: : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyRequestParent::NotifyCdmaCallWaiting(uint32_t aClientId, michael@0: const nsAString& aNumber) michael@0: { michael@0: MOZ_CRASH("Not a TelephonyParent!"); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyRequestParent::NotifyConferenceError(const nsAString& aName, michael@0: const nsAString& aMessage) michael@0: { michael@0: MOZ_CRASH("Not a TelephonyParent!"); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyRequestParent::NotifyError(uint32_t aClientId, michael@0: int32_t aCallIndex, michael@0: const nsAString& aError) michael@0: { michael@0: MOZ_CRASH("Not a TelephonyParent!"); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyRequestParent::SupplementaryServiceNotification(uint32_t aClientId, michael@0: int32_t aCallIndex, michael@0: uint16_t aNotification) michael@0: { michael@0: MOZ_CRASH("Not a TelephonyParent!"); michael@0: } michael@0: michael@0: // nsITelephonyCallback michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyRequestParent::NotifyDialError(const nsAString& aError) michael@0: { michael@0: NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); michael@0: michael@0: return (SendNotifyDialError(nsString(aError)) && michael@0: Send__delete__(this, DialResponse())) ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: TelephonyRequestParent::NotifyDialSuccess() michael@0: { michael@0: NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); michael@0: michael@0: return (SendNotifyDialSuccess() && michael@0: Send__delete__(this, DialResponse())) ? NS_OK : NS_ERROR_FAILURE; michael@0: }