mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-14 15:37:55 +00:00
921 lines
28 KiB
C++
921 lines
28 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* 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 "SmsParent.h"
|
|
#include "nsISmsService.h"
|
|
#include "nsIMmsService.h"
|
|
#include "nsIObserverService.h"
|
|
#include "mozilla/Services.h"
|
|
#include "nsIDOMMozSmsMessage.h"
|
|
#include "nsIDOMMozMmsMessage.h"
|
|
#include "mozilla/unused.h"
|
|
#include "SmsMessage.h"
|
|
#include "MmsMessage.h"
|
|
#include "nsIMobileMessageDatabaseService.h"
|
|
#include "MobileMessageThread.h"
|
|
#include "mozilla/dom/ipc/BlobParent.h"
|
|
#include "mozilla/dom/ContentParent.h"
|
|
#include "mozilla/dom/File.h"
|
|
#include "mozilla/dom/mobilemessage/Constants.h" // For MessageType
|
|
#include "nsContentUtils.h"
|
|
#include "nsTArrayHelpers.h"
|
|
#include "xpcpublic.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "DeletedMessageInfo.h"
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
namespace mobilemessage {
|
|
|
|
static JSObject*
|
|
MmsAttachmentDataToJSObject(JSContext* aContext,
|
|
const MmsAttachmentData& aAttachment)
|
|
{
|
|
JS::Rooted<JSObject*> obj(aContext, JS_NewObject(aContext, nullptr, JS::NullPtr(),
|
|
JS::NullPtr()));
|
|
NS_ENSURE_TRUE(obj, nullptr);
|
|
|
|
JS::Rooted<JSString*> idStr(aContext, JS_NewUCStringCopyN(aContext,
|
|
aAttachment.id().get(),
|
|
aAttachment.id().Length()));
|
|
NS_ENSURE_TRUE(idStr, nullptr);
|
|
if (!JS_DefineProperty(aContext, obj, "id", idStr, 0)) {
|
|
return nullptr;
|
|
}
|
|
|
|
JS::Rooted<JSString*> locStr(aContext, JS_NewUCStringCopyN(aContext,
|
|
aAttachment.location().get(),
|
|
aAttachment.location().Length()));
|
|
NS_ENSURE_TRUE(locStr, nullptr);
|
|
if (!JS_DefineProperty(aContext, obj, "location", locStr, 0)) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsRefPtr<FileImpl> blobImpl = static_cast<BlobParent*>(aAttachment.contentParent())->GetBlobImpl();
|
|
|
|
// nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
|
|
// called because the static analysis thinks dereferencing XPCOM objects
|
|
// can GC (because in some cases it can!), and a return statement with a
|
|
// JSObject* type means that JSObject* is on the stack as a raw pointer
|
|
// while destructors are running.
|
|
JS::Rooted<JS::Value> content(aContext);
|
|
{
|
|
nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aContext));
|
|
MOZ_ASSERT(global);
|
|
|
|
nsRefPtr<File> blob = new File(global, blobImpl);
|
|
if (!GetOrCreateDOMReflector(aContext, blob, &content)) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
if (!JS_DefineProperty(aContext, obj, "content", content, 0)) {
|
|
return nullptr;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
static bool
|
|
GetParamsFromSendMmsMessageRequest(JSContext* aCx,
|
|
const SendMmsMessageRequest& aRequest,
|
|
JS::Value* aParam)
|
|
{
|
|
JS::Rooted<JSObject*> paramsObj(aCx, JS_NewObject(aCx, nullptr, JS::NullPtr(), JS::NullPtr()));
|
|
NS_ENSURE_TRUE(paramsObj, false);
|
|
|
|
// smil
|
|
JS::Rooted<JSString*> smilStr(aCx, JS_NewUCStringCopyN(aCx,
|
|
aRequest.smil().get(),
|
|
aRequest.smil().Length()));
|
|
NS_ENSURE_TRUE(smilStr, false);
|
|
if(!JS_DefineProperty(aCx, paramsObj, "smil", smilStr, 0)) {
|
|
return false;
|
|
}
|
|
|
|
// subject
|
|
JS::Rooted<JSString*> subjectStr(aCx, JS_NewUCStringCopyN(aCx,
|
|
aRequest.subject().get(),
|
|
aRequest.subject().Length()));
|
|
NS_ENSURE_TRUE(subjectStr, false);
|
|
if(!JS_DefineProperty(aCx, paramsObj, "subject", subjectStr, 0)) {
|
|
return false;
|
|
}
|
|
|
|
// receivers
|
|
JS::Rooted<JSObject*> receiverArray(aCx);
|
|
if (NS_FAILED(nsTArrayToJSArray(aCx, aRequest.receivers(), &receiverArray)))
|
|
{
|
|
return false;
|
|
}
|
|
if (!JS_DefineProperty(aCx, paramsObj, "receivers", receiverArray, 0)) {
|
|
return false;
|
|
}
|
|
|
|
// attachments
|
|
JS::Rooted<JSObject*> attachmentArray(aCx, JS_NewArrayObject(aCx,
|
|
aRequest.attachments().Length()));
|
|
for (uint32_t i = 0; i < aRequest.attachments().Length(); i++) {
|
|
JS::Rooted<JSObject*> obj(aCx,
|
|
MmsAttachmentDataToJSObject(aCx, aRequest.attachments().ElementAt(i)));
|
|
NS_ENSURE_TRUE(obj, false);
|
|
if (!JS_SetElement(aCx, attachmentArray, i, obj)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!JS_DefineProperty(aCx, paramsObj, "attachments", attachmentArray, 0)) {
|
|
return false;
|
|
}
|
|
|
|
aParam->setObject(*paramsObj);
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
GetMobileMessageDataFromMessage(ContentParent* aParent,
|
|
nsISupports *aMsg,
|
|
MobileMessageData &aData)
|
|
{
|
|
if (!aMsg) {
|
|
NS_WARNING("Invalid message to convert!");
|
|
return false;
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMMozMmsMessage> mmsMsg = do_QueryInterface(aMsg);
|
|
if (mmsMsg) {
|
|
if (!aParent) {
|
|
NS_ERROR("Invalid ContentParent to convert MMS Message!");
|
|
return false;
|
|
}
|
|
MmsMessageData data;
|
|
if (!static_cast<MmsMessage*>(mmsMsg.get())->GetData(aParent, data)) {
|
|
return false;
|
|
}
|
|
aData = data;
|
|
return true;
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMMozSmsMessage> smsMsg = do_QueryInterface(aMsg);
|
|
if (smsMsg) {
|
|
aData = static_cast<SmsMessage*>(smsMsg.get())->GetData();
|
|
return true;
|
|
}
|
|
|
|
NS_WARNING("Cannot get MobileMessageData");
|
|
return false;
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(SmsParent, nsIObserver)
|
|
|
|
SmsParent::SmsParent()
|
|
{
|
|
MOZ_COUNT_CTOR(SmsParent);
|
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
if (!obs) {
|
|
return;
|
|
}
|
|
|
|
obs->AddObserver(this, kSmsReceivedObserverTopic, false);
|
|
obs->AddObserver(this, kSmsRetrievingObserverTopic, false);
|
|
obs->AddObserver(this, kSmsSendingObserverTopic, false);
|
|
obs->AddObserver(this, kSmsSentObserverTopic, false);
|
|
obs->AddObserver(this, kSmsFailedObserverTopic, false);
|
|
obs->AddObserver(this, kSmsDeliverySuccessObserverTopic, false);
|
|
obs->AddObserver(this, kSmsDeliveryErrorObserverTopic, false);
|
|
obs->AddObserver(this, kSilentSmsReceivedObserverTopic, false);
|
|
obs->AddObserver(this, kSmsReadSuccessObserverTopic, false);
|
|
obs->AddObserver(this, kSmsReadErrorObserverTopic, false);
|
|
obs->AddObserver(this, kSmsDeletedObserverTopic, false);
|
|
}
|
|
|
|
void
|
|
SmsParent::ActorDestroy(ActorDestroyReason why)
|
|
{
|
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
if (!obs) {
|
|
return;
|
|
}
|
|
|
|
obs->RemoveObserver(this, kSmsReceivedObserverTopic);
|
|
obs->RemoveObserver(this, kSmsRetrievingObserverTopic);
|
|
obs->RemoveObserver(this, kSmsSendingObserverTopic);
|
|
obs->RemoveObserver(this, kSmsSentObserverTopic);
|
|
obs->RemoveObserver(this, kSmsFailedObserverTopic);
|
|
obs->RemoveObserver(this, kSmsDeliverySuccessObserverTopic);
|
|
obs->RemoveObserver(this, kSmsDeliveryErrorObserverTopic);
|
|
obs->RemoveObserver(this, kSilentSmsReceivedObserverTopic);
|
|
obs->RemoveObserver(this, kSmsReadSuccessObserverTopic);
|
|
obs->RemoveObserver(this, kSmsReadErrorObserverTopic);
|
|
obs->RemoveObserver(this, kSmsDeletedObserverTopic);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsParent::Observe(nsISupports* aSubject, const char* aTopic,
|
|
const char16_t* aData)
|
|
{
|
|
ContentParent *parent = static_cast<ContentParent*>(Manager());
|
|
|
|
if (!strcmp(aTopic, kSmsReceivedObserverTopic)) {
|
|
MobileMessageData msgData;
|
|
if (!GetMobileMessageDataFromMessage(parent, aSubject, msgData)) {
|
|
NS_ERROR("Got a 'sms-received' topic without a valid message!");
|
|
return NS_OK;
|
|
}
|
|
|
|
unused << SendNotifyReceivedMessage(msgData);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!strcmp(aTopic, kSmsRetrievingObserverTopic)) {
|
|
MobileMessageData msgData;
|
|
if (!GetMobileMessageDataFromMessage(parent, aSubject, msgData)) {
|
|
NS_ERROR("Got a 'sms-retrieving' topic without a valid message!");
|
|
return NS_OK;
|
|
}
|
|
|
|
unused << SendNotifyRetrievingMessage(msgData);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!strcmp(aTopic, kSmsSendingObserverTopic)) {
|
|
MobileMessageData msgData;
|
|
if (!GetMobileMessageDataFromMessage(parent, aSubject, msgData)) {
|
|
NS_ERROR("Got a 'sms-sending' topic without a valid message!");
|
|
return NS_OK;
|
|
}
|
|
|
|
unused << SendNotifySendingMessage(msgData);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!strcmp(aTopic, kSmsSentObserverTopic)) {
|
|
MobileMessageData msgData;
|
|
if (!GetMobileMessageDataFromMessage(parent, aSubject, msgData)) {
|
|
NS_ERROR("Got a 'sms-sent' topic without a valid message!");
|
|
return NS_OK;
|
|
}
|
|
|
|
unused << SendNotifySentMessage(msgData);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!strcmp(aTopic, kSmsFailedObserverTopic)) {
|
|
MobileMessageData msgData;
|
|
if (!GetMobileMessageDataFromMessage(parent, aSubject, msgData)) {
|
|
NS_ERROR("Got a 'sms-failed' topic without a valid message!");
|
|
return NS_OK;
|
|
}
|
|
|
|
unused << SendNotifyFailedMessage(msgData);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!strcmp(aTopic, kSmsDeliverySuccessObserverTopic)) {
|
|
MobileMessageData msgData;
|
|
if (!GetMobileMessageDataFromMessage(parent, aSubject, msgData)) {
|
|
NS_ERROR("Got a 'sms-sending' topic without a valid message!");
|
|
return NS_OK;
|
|
}
|
|
|
|
unused << SendNotifyDeliverySuccessMessage(msgData);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!strcmp(aTopic, kSmsDeliveryErrorObserverTopic)) {
|
|
MobileMessageData msgData;
|
|
if (!GetMobileMessageDataFromMessage(parent, aSubject, msgData)) {
|
|
NS_ERROR("Got a 'sms-delivery-error' topic without a valid message!");
|
|
return NS_OK;
|
|
}
|
|
|
|
unused << SendNotifyDeliveryErrorMessage(msgData);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!strcmp(aTopic, kSilentSmsReceivedObserverTopic)) {
|
|
nsCOMPtr<nsIDOMMozSmsMessage> smsMsg = do_QueryInterface(aSubject);
|
|
if (!smsMsg) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsString sender;
|
|
if (NS_FAILED(smsMsg->GetSender(sender)) ||
|
|
!mSilentNumbers.Contains(sender)) {
|
|
return NS_OK;
|
|
}
|
|
|
|
MobileMessageData msgData =
|
|
static_cast<SmsMessage*>(smsMsg.get())->GetData();
|
|
unused << SendNotifyReceivedSilentMessage(msgData);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!strcmp(aTopic, kSmsReadSuccessObserverTopic)) {
|
|
MobileMessageData msgData;
|
|
if (!GetMobileMessageDataFromMessage(parent, aSubject, msgData)) {
|
|
NS_ERROR("Got a 'sms-read-success' topic without a valid message!");
|
|
return NS_OK;
|
|
}
|
|
|
|
unused << SendNotifyReadSuccessMessage(msgData);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!strcmp(aTopic, kSmsReadErrorObserverTopic)) {
|
|
MobileMessageData msgData;
|
|
if (!GetMobileMessageDataFromMessage(parent, aSubject, msgData)) {
|
|
NS_ERROR("Got a 'sms-read-error' topic without a valid message!");
|
|
return NS_OK;
|
|
}
|
|
|
|
unused << SendNotifyReadErrorMessage(msgData);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!strcmp(aTopic, kSmsDeletedObserverTopic)) {
|
|
nsCOMPtr<nsIDeletedMessageInfo> deletedInfo = do_QueryInterface(aSubject);
|
|
if (!deletedInfo) {
|
|
NS_ERROR("Got a 'sms-deleted' topic without a valid message!");
|
|
return NS_OK;
|
|
}
|
|
|
|
unused << SendNotifyDeletedMessageInfo(
|
|
static_cast<DeletedMessageInfo*>(deletedInfo.get())->GetData());
|
|
return NS_OK;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
SmsParent::RecvAddSilentNumber(const nsString& aNumber)
|
|
{
|
|
if (mSilentNumbers.Contains(aNumber)) {
|
|
return true;
|
|
}
|
|
|
|
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
|
NS_ENSURE_TRUE(smsService, true);
|
|
|
|
nsresult rv = smsService->AddSilentNumber(aNumber);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mSilentNumbers.AppendElement(aNumber);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SmsParent::RecvRemoveSilentNumber(const nsString& aNumber)
|
|
{
|
|
if (!mSilentNumbers.Contains(aNumber)) {
|
|
return true;
|
|
}
|
|
|
|
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
|
NS_ENSURE_TRUE(smsService, true);
|
|
|
|
nsresult rv = smsService->RemoveSilentNumber(aNumber);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mSilentNumbers.RemoveElement(aNumber);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SmsParent::RecvPSmsRequestConstructor(PSmsRequestParent* aActor,
|
|
const IPCSmsRequest& aRequest)
|
|
{
|
|
SmsRequestParent* actor = static_cast<SmsRequestParent*>(aActor);
|
|
|
|
switch (aRequest.type()) {
|
|
case IPCSmsRequest::TSendMessageRequest:
|
|
return actor->DoRequest(aRequest.get_SendMessageRequest());
|
|
case IPCSmsRequest::TRetrieveMessageRequest:
|
|
return actor->DoRequest(aRequest.get_RetrieveMessageRequest());
|
|
case IPCSmsRequest::TGetMessageRequest:
|
|
return actor->DoRequest(aRequest.get_GetMessageRequest());
|
|
case IPCSmsRequest::TDeleteMessageRequest:
|
|
return actor->DoRequest(aRequest.get_DeleteMessageRequest());
|
|
case IPCSmsRequest::TMarkMessageReadRequest:
|
|
return actor->DoRequest(aRequest.get_MarkMessageReadRequest());
|
|
case IPCSmsRequest::TGetSegmentInfoForTextRequest:
|
|
return actor->DoRequest(aRequest.get_GetSegmentInfoForTextRequest());
|
|
case IPCSmsRequest::TGetSmscAddressRequest:
|
|
return actor->DoRequest(aRequest.get_GetSmscAddressRequest());
|
|
default:
|
|
MOZ_CRASH("Unknown type!");
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
PSmsRequestParent*
|
|
SmsParent::AllocPSmsRequestParent(const IPCSmsRequest& aRequest)
|
|
{
|
|
SmsRequestParent* actor = new SmsRequestParent();
|
|
// Add an extra ref for IPDL. Will be released in
|
|
// SmsParent::DeallocPSmsRequestParent().
|
|
actor->AddRef();
|
|
|
|
return actor;
|
|
}
|
|
|
|
bool
|
|
SmsParent::DeallocPSmsRequestParent(PSmsRequestParent* aActor)
|
|
{
|
|
// SmsRequestParent is refcounted, must not be freed manually.
|
|
static_cast<SmsRequestParent*>(aActor)->Release();
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SmsParent::RecvPMobileMessageCursorConstructor(PMobileMessageCursorParent* aActor,
|
|
const IPCMobileMessageCursor& aRequest)
|
|
{
|
|
MobileMessageCursorParent* actor =
|
|
static_cast<MobileMessageCursorParent*>(aActor);
|
|
|
|
switch (aRequest.type()) {
|
|
case IPCMobileMessageCursor::TCreateMessageCursorRequest:
|
|
return actor->DoRequest(aRequest.get_CreateMessageCursorRequest());
|
|
case IPCMobileMessageCursor::TCreateThreadCursorRequest:
|
|
return actor->DoRequest(aRequest.get_CreateThreadCursorRequest());
|
|
default:
|
|
MOZ_CRASH("Unknown type!");
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
PMobileMessageCursorParent*
|
|
SmsParent::AllocPMobileMessageCursorParent(const IPCMobileMessageCursor& aRequest)
|
|
{
|
|
MobileMessageCursorParent* actor = new MobileMessageCursorParent();
|
|
// Add an extra ref for IPDL. Will be released in
|
|
// SmsParent::DeallocPMobileMessageCursorParent().
|
|
actor->AddRef();
|
|
|
|
return actor;
|
|
}
|
|
|
|
bool
|
|
SmsParent::DeallocPMobileMessageCursorParent(PMobileMessageCursorParent* aActor)
|
|
{
|
|
// MobileMessageCursorParent is refcounted, must not be freed manually.
|
|
static_cast<MobileMessageCursorParent*>(aActor)->Release();
|
|
return true;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SmsRequestParent
|
|
******************************************************************************/
|
|
|
|
NS_IMPL_ISUPPORTS(SmsRequestParent, nsIMobileMessageCallback)
|
|
|
|
void
|
|
SmsRequestParent::ActorDestroy(ActorDestroyReason aWhy)
|
|
{
|
|
mActorDestroyed = true;
|
|
}
|
|
|
|
bool
|
|
SmsRequestParent::DoRequest(const SendMessageRequest& aRequest)
|
|
{
|
|
switch(aRequest.type()) {
|
|
case SendMessageRequest::TSendSmsMessageRequest: {
|
|
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
|
NS_ENSURE_TRUE(smsService, true);
|
|
|
|
const SendSmsMessageRequest &req = aRequest.get_SendSmsMessageRequest();
|
|
smsService->Send(req.serviceId(), req.number(), req.message(),
|
|
req.silent(), this);
|
|
}
|
|
break;
|
|
case SendMessageRequest::TSendMmsMessageRequest: {
|
|
nsCOMPtr<nsIMmsService> mmsService = do_GetService(MMS_SERVICE_CONTRACTID);
|
|
NS_ENSURE_TRUE(mmsService, true);
|
|
|
|
// There are cases (see bug 981202) where this is called with no JS on the
|
|
// stack. And since mmsService might be JS-Implemented, we need to pass a
|
|
// jsval to ::Send. Only system code should be looking at the result here,
|
|
// so we just create it in the System-Principaled Junk Scope.
|
|
AutoJSContext cx;
|
|
JSAutoCompartment ac(cx, xpc::PrivilegedJunkScope());
|
|
JS::Rooted<JS::Value> params(cx);
|
|
const SendMmsMessageRequest &req = aRequest.get_SendMmsMessageRequest();
|
|
if (!GetParamsFromSendMmsMessageRequest(cx,
|
|
req,
|
|
params.address())) {
|
|
NS_WARNING("SmsRequestParent: Fail to build MMS params.");
|
|
return true;
|
|
}
|
|
mmsService->Send(req.serviceId(), params, this);
|
|
}
|
|
break;
|
|
default:
|
|
MOZ_CRASH("Unknown type of SendMessageRequest!");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SmsRequestParent::DoRequest(const RetrieveMessageRequest& aRequest)
|
|
{
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIMmsService> mmsService = do_GetService(MMS_SERVICE_CONTRACTID);
|
|
if (mmsService) {
|
|
rv = mmsService->Retrieve(aRequest.messageId(), this);
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
return NS_SUCCEEDED(NotifyGetMessageFailed(nsIMobileMessageCallback::INTERNAL_ERROR));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SmsRequestParent::DoRequest(const GetMessageRequest& aRequest)
|
|
{
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
|
|
do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
|
|
if (dbService) {
|
|
rv = dbService->GetMessageMoz(aRequest.messageId(), this);
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
return NS_SUCCEEDED(NotifyGetMessageFailed(nsIMobileMessageCallback::INTERNAL_ERROR));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SmsRequestParent::DoRequest(const GetSmscAddressRequest& aRequest)
|
|
{
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
|
if (smsService) {
|
|
rv = smsService->GetSmscAddress(aRequest.serviceId(), this);
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
return NS_SUCCEEDED(NotifyGetSmscAddressFailed(nsIMobileMessageCallback::INTERNAL_ERROR));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SmsRequestParent::DoRequest(const DeleteMessageRequest& aRequest)
|
|
{
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
|
|
do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
|
|
if (dbService) {
|
|
const InfallibleTArray<int32_t>& messageIds = aRequest.messageIds();
|
|
rv = dbService->DeleteMessage(const_cast<int32_t *>(messageIds.Elements()),
|
|
messageIds.Length(), this);
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
return NS_SUCCEEDED(NotifyDeleteMessageFailed(nsIMobileMessageCallback::INTERNAL_ERROR));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SmsRequestParent::DoRequest(const MarkMessageReadRequest& aRequest)
|
|
{
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
|
|
do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
|
|
if (dbService) {
|
|
rv = dbService->MarkMessageRead(aRequest.messageId(), aRequest.value(),
|
|
aRequest.sendReadReport(), this);
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
return NS_SUCCEEDED(NotifyMarkMessageReadFailed(nsIMobileMessageCallback::INTERNAL_ERROR));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SmsRequestParent::DoRequest(const GetSegmentInfoForTextRequest& aRequest)
|
|
{
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
|
if (smsService) {
|
|
rv = smsService->GetSegmentInfoForText(aRequest.text(), this);
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
return NS_SUCCEEDED(NotifyGetSegmentInfoForTextFailed(
|
|
nsIMobileMessageCallback::INTERNAL_ERROR));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
nsresult
|
|
SmsRequestParent::SendReply(const MessageReply& aReply)
|
|
{
|
|
// The child process could die before this asynchronous notification, in which
|
|
// case ActorDestroy() was called and mActorDestroyed is set to true. Return
|
|
// an error here to avoid sending a message to the dead process.
|
|
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
|
|
|
|
return Send__delete__(this, aReply) ? NS_OK : NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// nsIMobileMessageCallback
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifyMessageSent(nsISupports *aMessage)
|
|
{
|
|
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
|
|
|
|
ContentParent *parent = static_cast<ContentParent*>(Manager()->Manager());
|
|
MobileMessageData data;
|
|
if (GetMobileMessageDataFromMessage(parent, aMessage, data)) {
|
|
return SendReply(ReplyMessageSend(data));
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifySendMessageFailed(int32_t aError, nsISupports *aMessage)
|
|
{
|
|
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
|
|
|
|
ContentParent *parent = static_cast<ContentParent*>(Manager()->Manager());
|
|
MobileMessageData data;
|
|
if (!GetMobileMessageDataFromMessage(parent, aMessage, data)) {
|
|
return SendReply(ReplyMessageSendFail(aError, OptionalMobileMessageData(void_t())));
|
|
}
|
|
|
|
return SendReply(ReplyMessageSendFail(aError, OptionalMobileMessageData(data)));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifyMessageGot(nsISupports *aMessage)
|
|
{
|
|
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
|
|
|
|
ContentParent *parent = static_cast<ContentParent*>(Manager()->Manager());
|
|
MobileMessageData data;
|
|
if (GetMobileMessageDataFromMessage(parent, aMessage, data)) {
|
|
return SendReply(ReplyGetMessage(data));
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifyGetMessageFailed(int32_t aError)
|
|
{
|
|
return SendReply(ReplyGetMessageFail(aError));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifyMessageDeleted(bool *aDeleted, uint32_t aSize)
|
|
{
|
|
ReplyMessageDelete data;
|
|
data.deleted().AppendElements(aDeleted, aSize);
|
|
return SendReply(data);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifyDeleteMessageFailed(int32_t aError)
|
|
{
|
|
return SendReply(ReplyMessageDeleteFail(aError));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifyMessageMarkedRead(bool aRead)
|
|
{
|
|
return SendReply(ReplyMarkeMessageRead(aRead));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifyMarkMessageReadFailed(int32_t aError)
|
|
{
|
|
return SendReply(ReplyMarkeMessageReadFail(aError));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifySegmentInfoForTextGot(int32_t aSegments,
|
|
int32_t aCharsPerSegment,
|
|
int32_t aCharsAvailableInLastSegment)
|
|
{
|
|
return SendReply(ReplyGetSegmentInfoForText(aSegments,
|
|
aCharsPerSegment,
|
|
aCharsAvailableInLastSegment));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifyGetSegmentInfoForTextFailed(int32_t aError)
|
|
{
|
|
return SendReply(ReplyGetSegmentInfoForTextFail(aError));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifyGetSmscAddress(const nsAString& aSmscAddress)
|
|
{
|
|
return SendReply(ReplyGetSmscAddress(nsString(aSmscAddress)));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
SmsRequestParent::NotifyGetSmscAddressFailed(int32_t aError)
|
|
{
|
|
return SendReply(ReplyGetSmscAddressFail(aError));
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* MobileMessageCursorParent
|
|
******************************************************************************/
|
|
|
|
NS_IMPL_ISUPPORTS(MobileMessageCursorParent, nsIMobileMessageCursorCallback)
|
|
|
|
void
|
|
MobileMessageCursorParent::ActorDestroy(ActorDestroyReason aWhy)
|
|
{
|
|
// Two possible scenarios here:
|
|
// 1) When parent fails to SendNotifyResult() in NotifyCursorResult(), it's
|
|
// destroyed without nulling out mContinueCallback.
|
|
// 2) When parent dies normally, mContinueCallback should have been cleared in
|
|
// NotifyCursorError(), but just ensure this again.
|
|
mContinueCallback = nullptr;
|
|
}
|
|
|
|
bool
|
|
MobileMessageCursorParent::RecvContinue()
|
|
{
|
|
MOZ_ASSERT(mContinueCallback);
|
|
|
|
if (NS_FAILED(mContinueCallback->HandleContinue())) {
|
|
return NS_SUCCEEDED(NotifyCursorError(nsIMobileMessageCallback::INTERNAL_ERROR));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
MobileMessageCursorParent::DoRequest(const CreateMessageCursorRequest& aRequest)
|
|
{
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
|
|
do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
|
|
if (dbService) {
|
|
const SmsFilterData& filter = aRequest.filter();
|
|
|
|
const nsTArray<nsString>& numbers = filter.numbers();
|
|
nsAutoArrayPtr<const char16_t*> ptrNumbers;
|
|
uint32_t numbersCount = numbers.Length();
|
|
if (numbersCount) {
|
|
uint32_t index;
|
|
|
|
ptrNumbers = new const char16_t* [numbersCount];
|
|
for (index = 0; index < numbersCount; index++) {
|
|
ptrNumbers[index] = numbers[index].get();
|
|
}
|
|
}
|
|
|
|
rv = dbService->CreateMessageCursor(filter.hasStartDate(),
|
|
filter.startDate(),
|
|
filter.hasEndDate(),
|
|
filter.endDate(),
|
|
ptrNumbers, numbersCount,
|
|
filter.delivery(),
|
|
filter.hasRead(),
|
|
filter.read(),
|
|
filter.threadId(),
|
|
aRequest.reverse(),
|
|
this,
|
|
getter_AddRefs(mContinueCallback));
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
return NS_SUCCEEDED(NotifyCursorError(nsIMobileMessageCallback::INTERNAL_ERROR));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
MobileMessageCursorParent::DoRequest(const CreateThreadCursorRequest& aRequest)
|
|
{
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
|
|
do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
|
|
if (dbService) {
|
|
rv = dbService->CreateThreadCursor(this,
|
|
getter_AddRefs(mContinueCallback));
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
return NS_SUCCEEDED(NotifyCursorError(nsIMobileMessageCallback::INTERNAL_ERROR));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// nsIMobileMessageCursorCallback
|
|
|
|
NS_IMETHODIMP
|
|
MobileMessageCursorParent::NotifyCursorError(int32_t aError)
|
|
{
|
|
// The child process could die before this asynchronous notification, in which
|
|
// case ActorDestroy() was called and mContinueCallback is now null. Return an
|
|
// error here to avoid sending a message to the dead process.
|
|
NS_ENSURE_TRUE(mContinueCallback, NS_ERROR_FAILURE);
|
|
|
|
mContinueCallback = nullptr;
|
|
|
|
return Send__delete__(this, aError) ? NS_OK : NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MobileMessageCursorParent::NotifyCursorResult(nsISupports** aResults,
|
|
uint32_t aSize)
|
|
{
|
|
MOZ_ASSERT(aResults && *aResults && aSize);
|
|
|
|
// The child process could die before this asynchronous notification, in which
|
|
// case ActorDestroy() was called and mContinueCallback is now null. Return an
|
|
// error here to avoid sending a message to the dead process.
|
|
NS_ENSURE_TRUE(mContinueCallback, NS_ERROR_FAILURE);
|
|
|
|
nsCOMPtr<nsIDOMMozMobileMessageThread> iThread =
|
|
do_QueryInterface(aResults[0]);
|
|
if (iThread) {
|
|
nsTArray<ThreadData> threads;
|
|
|
|
for (uint32_t i = 0; i < aSize; i++) {
|
|
nsCOMPtr<nsIDOMMozMobileMessageThread> iThread =
|
|
do_QueryInterface(aResults[i]);
|
|
NS_ENSURE_TRUE(iThread, NS_ERROR_FAILURE);
|
|
|
|
MobileMessageThread* thread =
|
|
static_cast<MobileMessageThread*>(iThread.get());
|
|
threads.AppendElement(thread->GetData());
|
|
}
|
|
|
|
return SendNotifyResult(MobileMessageCursorData(ThreadArrayData(threads)))
|
|
? NS_OK : NS_ERROR_FAILURE;
|
|
}
|
|
|
|
ContentParent* parent = static_cast<ContentParent*>(Manager()->Manager());
|
|
nsTArray<MobileMessageData> messages;
|
|
for (uint32_t i = 0; i < aSize; i++) {
|
|
nsCOMPtr<nsIDOMMozSmsMessage> iSms = do_QueryInterface(aResults[i]);
|
|
if (iSms) {
|
|
SmsMessage* sms = static_cast<SmsMessage*>(iSms.get());
|
|
messages.AppendElement(sms->GetData());
|
|
continue;
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMMozMmsMessage> iMms = do_QueryInterface(aResults[i]);
|
|
if (iMms) {
|
|
MmsMessage* mms = static_cast<MmsMessage*>(iMms.get());
|
|
MmsMessageData mmsData;
|
|
NS_ENSURE_TRUE(mms->GetData(parent, mmsData), NS_ERROR_FAILURE);
|
|
messages.AppendElement(mmsData);
|
|
continue;
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return SendNotifyResult(MobileMessageCursorData(MobileMessageArrayData(messages)))
|
|
? NS_OK : NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MobileMessageCursorParent::NotifyCursorDone()
|
|
{
|
|
return NotifyCursorError(nsIMobileMessageCallback::SUCCESS_NO_ERROR);
|
|
}
|
|
|
|
} // namespace mobilemessage
|
|
} // namespace dom
|
|
} // namespace mozilla
|