1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "MobileMessageManager.h"
8 #include "DeletedMessageInfo.h"
10 #include "DOMRequest.h"
11 #include "MobileMessageCallback.h"
12 #include "MobileMessageCursorCallback.h"
13 #include "mozilla/dom/mobilemessage/Constants.h" // For kSms*ObserverTopic
14 #include "mozilla/dom/MozMessageDeletedEvent.h"
15 #include "mozilla/dom/MozMmsEvent.h"
16 #include "mozilla/dom/MozMobileMessageManagerBinding.h"
17 #include "mozilla/dom/MozSmsEvent.h"
18 #include "mozilla/dom/ToJSValue.h"
19 #include "mozilla/Preferences.h"
20 #include "mozilla/Services.h"
21 #include "nsIDOMMozMmsMessage.h"
22 #include "nsIDOMMozSmsMessage.h"
23 #include "nsIMmsService.h"
24 #include "nsIMobileMessageCallback.h"
25 #include "nsIMobileMessageDatabaseService.h"
26 #include "nsIObserverService.h"
27 #include "nsISmsService.h"
28 #include "nsServiceManagerUtils.h" // For do_GetService()
30 #define RECEIVED_EVENT_NAME NS_LITERAL_STRING("received")
31 #define RETRIEVING_EVENT_NAME NS_LITERAL_STRING("retrieving")
32 #define SENDING_EVENT_NAME NS_LITERAL_STRING("sending")
33 #define SENT_EVENT_NAME NS_LITERAL_STRING("sent")
34 #define FAILED_EVENT_NAME NS_LITERAL_STRING("failed")
35 #define DELIVERY_SUCCESS_EVENT_NAME NS_LITERAL_STRING("deliverysuccess")
36 #define DELIVERY_ERROR_EVENT_NAME NS_LITERAL_STRING("deliveryerror")
37 #define READ_SUCCESS_EVENT_NAME NS_LITERAL_STRING("readsuccess")
38 #define READ_ERROR_EVENT_NAME NS_LITERAL_STRING("readerror")
39 #define DELETED_EVENT_NAME NS_LITERAL_STRING("deleted")
41 using namespace mozilla::dom::mobilemessage
;
46 NS_INTERFACE_MAP_BEGIN(MobileMessageManager
)
47 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
48 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
50 NS_IMPL_ADDREF_INHERITED(MobileMessageManager
, DOMEventTargetHelper
)
51 NS_IMPL_RELEASE_INHERITED(MobileMessageManager
, DOMEventTargetHelper
)
53 MobileMessageManager::MobileMessageManager(nsPIDOMWindow
*aWindow
)
54 : DOMEventTargetHelper(aWindow
)
59 MobileMessageManager::Init()
61 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
62 // GetObserverService() can return null is some situations like shutdown.
67 obs
->AddObserver(this, kSmsReceivedObserverTopic
, false);
68 obs
->AddObserver(this, kSmsRetrievingObserverTopic
, false);
69 obs
->AddObserver(this, kSmsSendingObserverTopic
, false);
70 obs
->AddObserver(this, kSmsSentObserverTopic
, false);
71 obs
->AddObserver(this, kSmsFailedObserverTopic
, false);
72 obs
->AddObserver(this, kSmsDeliverySuccessObserverTopic
, false);
73 obs
->AddObserver(this, kSmsDeliveryErrorObserverTopic
, false);
74 obs
->AddObserver(this, kSmsReadSuccessObserverTopic
, false);
75 obs
->AddObserver(this, kSmsReadErrorObserverTopic
, false);
76 obs
->AddObserver(this, kSmsDeletedObserverTopic
, false);
80 MobileMessageManager::Shutdown()
82 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
83 // GetObserverService() can return null is some situations like shutdown.
88 obs
->RemoveObserver(this, kSmsReceivedObserverTopic
);
89 obs
->RemoveObserver(this, kSmsRetrievingObserverTopic
);
90 obs
->RemoveObserver(this, kSmsSendingObserverTopic
);
91 obs
->RemoveObserver(this, kSmsSentObserverTopic
);
92 obs
->RemoveObserver(this, kSmsFailedObserverTopic
);
93 obs
->RemoveObserver(this, kSmsDeliverySuccessObserverTopic
);
94 obs
->RemoveObserver(this, kSmsDeliveryErrorObserverTopic
);
95 obs
->RemoveObserver(this, kSmsReadSuccessObserverTopic
);
96 obs
->RemoveObserver(this, kSmsReadErrorObserverTopic
);
97 obs
->RemoveObserver(this, kSmsDeletedObserverTopic
);
101 MobileMessageManager::WrapObject(JSContext
* aCx
)
103 return MozMobileMessageManagerBinding::Wrap(aCx
, this);
106 already_AddRefed
<DOMRequest
>
107 MobileMessageManager::GetSegmentInfoForText(const nsAString
& aText
,
110 nsCOMPtr
<nsISmsService
> smsService
= do_GetService(SMS_SERVICE_CONTRACTID
);
112 aRv
.Throw(NS_ERROR_FAILURE
);
116 nsRefPtr
<DOMRequest
> request
= new DOMRequest(GetOwner());
117 nsCOMPtr
<nsIMobileMessageCallback
> msgCallback
=
118 new MobileMessageCallback(request
);
119 nsresult rv
= smsService
->GetSegmentInfoForText(aText
, msgCallback
);
125 return request
.forget();
128 already_AddRefed
<DOMRequest
>
129 MobileMessageManager::Send(nsISmsService
* aSmsService
,
131 const nsAString
& aNumber
,
132 const nsAString
& aText
,
135 nsRefPtr
<DOMRequest
> request
= new DOMRequest(GetOwner());
136 nsCOMPtr
<nsIMobileMessageCallback
> msgCallback
=
137 new MobileMessageCallback(request
);
139 // By default, we don't send silent messages via MobileMessageManager.
140 nsresult rv
= aSmsService
->Send(aServiceId
, aNumber
, aText
,
147 return request
.forget();
150 already_AddRefed
<DOMRequest
>
151 MobileMessageManager::Send(const nsAString
& aNumber
,
152 const nsAString
& aText
,
153 const SmsSendParameters
& aSendParams
,
156 nsCOMPtr
<nsISmsService
> smsService
= do_GetService(SMS_SERVICE_CONTRACTID
);
158 aRv
.Throw(NS_ERROR_FAILURE
);
162 // Use the default one unless |aSendParams.serviceId| is available.
164 if (aSendParams
.mServiceId
.WasPassed()) {
165 serviceId
= aSendParams
.mServiceId
.Value();
167 nsresult rv
= smsService
->GetSmsDefaultServiceId(&serviceId
);
174 return Send(smsService
, serviceId
, aNumber
, aText
, aRv
);
178 MobileMessageManager::Send(const Sequence
<nsString
>& aNumbers
,
179 const nsAString
& aText
,
180 const SmsSendParameters
& aSendParams
,
181 nsTArray
<nsRefPtr
<DOMRequest
>>& aReturn
,
184 nsCOMPtr
<nsISmsService
> smsService
= do_GetService(SMS_SERVICE_CONTRACTID
);
186 aRv
.Throw(NS_ERROR_FAILURE
);
190 // Use the default one unless |aSendParams.serviceId| is available.
192 if (aSendParams
.mServiceId
.WasPassed()) {
193 serviceId
= aSendParams
.mServiceId
.Value();
195 nsresult rv
= smsService
->GetSmsDefaultServiceId(&serviceId
);
202 const uint32_t size
= aNumbers
.Length();
203 for (uint32_t i
= 0; i
< size
; ++i
) {
204 nsRefPtr
<DOMRequest
> request
= Send(smsService
, serviceId
, aNumbers
[i
], aText
, aRv
);
208 aReturn
.AppendElement(request
);
212 already_AddRefed
<DOMRequest
>
213 MobileMessageManager::SendMMS(const MmsParameters
& aParams
,
214 const MmsSendParameters
& aSendParams
,
217 nsCOMPtr
<nsIMmsService
> mmsService
= do_GetService(MMS_SERVICE_CONTRACTID
);
219 aRv
.Throw(NS_ERROR_FAILURE
);
223 // Use the default one unless |aSendParams.serviceId| is available.
226 if (aSendParams
.mServiceId
.WasPassed()) {
227 serviceId
= aSendParams
.mServiceId
.Value();
229 rv
= mmsService
->GetMmsDefaultServiceId(&serviceId
);
237 if (!NS_WARN_IF(jsapi
.Init(GetOwner()))) {
238 aRv
.Throw(NS_ERROR_FAILURE
);
242 JSContext
*cx
= jsapi
.cx();
243 JS::Rooted
<JS::Value
> val(cx
);
244 if (!ToJSValue(cx
, aParams
, &val
)) {
245 aRv
.Throw(NS_ERROR_TYPE_ERR
);
249 nsRefPtr
<DOMRequest
> request
= new DOMRequest(GetOwner());
250 nsCOMPtr
<nsIMobileMessageCallback
> msgCallback
= new MobileMessageCallback(request
);
251 rv
= mmsService
->Send(serviceId
, val
, msgCallback
);
257 return request
.forget();
260 already_AddRefed
<DOMRequest
>
261 MobileMessageManager::GetMessage(int32_t aId
,
264 nsCOMPtr
<nsIMobileMessageDatabaseService
> dbService
=
265 do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID
);
267 aRv
.Throw(NS_ERROR_FAILURE
);
271 nsRefPtr
<DOMRequest
> request
= new DOMRequest(GetOwner());
272 nsCOMPtr
<nsIMobileMessageCallback
> msgCallback
= new MobileMessageCallback(request
);
273 nsresult rv
= dbService
->GetMessageMoz(aId
, msgCallback
);
279 return request
.forget();
282 already_AddRefed
<DOMRequest
>
283 MobileMessageManager::Delete(int32_t* aIdArray
,
287 nsCOMPtr
<nsIMobileMessageDatabaseService
> dbService
=
288 do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID
);
290 aRv
.Throw(NS_ERROR_FAILURE
);
294 nsRefPtr
<DOMRequest
> request
= new DOMRequest(GetOwner());
295 nsCOMPtr
<nsIMobileMessageCallback
> msgCallback
=
296 new MobileMessageCallback(request
);
298 nsresult rv
= dbService
->DeleteMessage(aIdArray
, aSize
, msgCallback
);
304 return request
.forget();
307 already_AddRefed
<DOMRequest
>
308 MobileMessageManager::Delete(int32_t aId
,
311 return Delete(&aId
, 1, aRv
);
314 already_AddRefed
<DOMRequest
>
315 MobileMessageManager::Delete(nsIDOMMozSmsMessage
* aMessage
,
320 DebugOnly
<nsresult
> rv
= aMessage
->GetId(&id
);
321 MOZ_ASSERT(NS_SUCCEEDED(rv
));
323 return Delete(id
, aRv
);
326 already_AddRefed
<DOMRequest
>
327 MobileMessageManager::Delete(nsIDOMMozMmsMessage
* aMessage
,
332 DebugOnly
<nsresult
> rv
= aMessage
->GetId(&id
);
333 MOZ_ASSERT(NS_SUCCEEDED(rv
));
335 return Delete(id
, aRv
);
338 already_AddRefed
<DOMRequest
>
339 MobileMessageManager::Delete(const Sequence
<OwningLongOrMozSmsMessageOrMozMmsMessage
>& aParams
,
342 const uint32_t size
= aParams
.Length();
343 FallibleTArray
<int32_t> idArray
;
344 if (!idArray
.SetLength(size
)) {
345 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
349 DebugOnly
<nsresult
> rv
;
350 for (uint32_t i
= 0; i
< size
; i
++) {
351 const OwningLongOrMozSmsMessageOrMozMmsMessage
& element
= aParams
[i
];
352 int32_t &id
= idArray
[i
];
354 if (element
.IsLong()) {
355 id
= element
.GetAsLong();
356 } else if (element
.IsMozMmsMessage()) {
357 rv
= element
.GetAsMozMmsMessage()->GetId(&id
);
358 MOZ_ASSERT(NS_SUCCEEDED(rv
));
359 } else /*if (element.IsMozSmsMessage())*/ {
360 rv
= element
.GetAsMozSmsMessage()->GetId(&id
);
361 MOZ_ASSERT(NS_SUCCEEDED(rv
));
365 return Delete(idArray
.Elements(), size
, aRv
);
368 already_AddRefed
<DOMCursor
>
369 MobileMessageManager::GetMessages(const MobileMessageFilter
& aFilter
,
373 nsCOMPtr
<nsIMobileMessageDatabaseService
> dbService
=
374 do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID
);
376 aRv
.Throw(NS_ERROR_FAILURE
);
380 bool hasStartDate
= !aFilter
.mStartDate
.IsNull();
381 uint64_t startDate
= 0;
383 startDate
= aFilter
.mStartDate
.Value();
386 bool hasEndDate
= !aFilter
.mEndDate
.IsNull();
387 uint64_t endDate
= 0;
389 endDate
= aFilter
.mEndDate
.Value();
392 nsAutoArrayPtr
<const char16_t
*> ptrNumbers
;
393 uint32_t numbersCount
= 0;
394 if (!aFilter
.mNumbers
.IsNull() &&
395 aFilter
.mNumbers
.Value().Length()) {
396 const FallibleTArray
<nsString
>& numbers
= aFilter
.mNumbers
.Value();
399 numbersCount
= numbers
.Length();
400 ptrNumbers
= new const char16_t
* [numbersCount
];
401 for (index
= 0; index
< numbersCount
; index
++) {
402 ptrNumbers
[index
] = numbers
[index
].get();
407 delivery
.SetIsVoid(true);
408 if (!aFilter
.mDelivery
.IsNull()) {
409 const uint32_t index
= static_cast<uint32_t>(aFilter
.mDelivery
.Value());
410 const EnumEntry
& entry
=
411 MobileMessageFilterDeliveryValues::strings
[index
];
412 delivery
.AssignASCII(entry
.value
, entry
.length
);
415 bool hasRead
= !aFilter
.mRead
.IsNull();
418 read
= aFilter
.mRead
.Value();
421 uint64_t threadId
= 0;
422 if (!aFilter
.mThreadId
.IsNull()) {
423 threadId
= aFilter
.mThreadId
.Value();
426 nsRefPtr
<MobileMessageCursorCallback
> cursorCallback
=
427 new MobileMessageCursorCallback();
428 nsCOMPtr
<nsICursorContinueCallback
> continueCallback
;
429 nsresult rv
= dbService
->CreateMessageCursor(hasStartDate
, startDate
,
431 ptrNumbers
, numbersCount
,
435 aReverse
, cursorCallback
,
436 getter_AddRefs(continueCallback
));
442 cursorCallback
->mDOMCursor
=
443 new MobileMessageCursor(GetOwner(), continueCallback
);
445 nsRefPtr
<DOMCursor
> cursor(cursorCallback
->mDOMCursor
);
446 return cursor
.forget();
449 already_AddRefed
<DOMRequest
>
450 MobileMessageManager::MarkMessageRead(int32_t aId
,
452 bool aSendReadReport
,
455 nsCOMPtr
<nsIMobileMessageDatabaseService
> dbService
=
456 do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID
);
458 aRv
.Throw(NS_ERROR_FAILURE
);
462 nsRefPtr
<DOMRequest
> request
= new DOMRequest(GetOwner());
463 nsCOMPtr
<nsIMobileMessageCallback
> msgCallback
= new MobileMessageCallback(request
);
464 nsresult rv
= dbService
->MarkMessageRead(aId
, aValue
, aSendReadReport
,
471 return request
.forget();
474 already_AddRefed
<DOMCursor
>
475 MobileMessageManager::GetThreads(ErrorResult
& aRv
)
477 nsCOMPtr
<nsIMobileMessageDatabaseService
> dbService
=
478 do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID
);
480 aRv
.Throw(NS_ERROR_FAILURE
);
484 nsRefPtr
<MobileMessageCursorCallback
> cursorCallback
=
485 new MobileMessageCursorCallback();
487 nsCOMPtr
<nsICursorContinueCallback
> continueCallback
;
488 nsresult rv
= dbService
->CreateThreadCursor(cursorCallback
,
489 getter_AddRefs(continueCallback
));
495 cursorCallback
->mDOMCursor
=
496 new MobileMessageCursor(GetOwner(), continueCallback
);
498 nsRefPtr
<DOMCursor
> cursor(cursorCallback
->mDOMCursor
);
499 return cursor
.forget();
502 already_AddRefed
<DOMRequest
>
503 MobileMessageManager::RetrieveMMS(int32_t aId
,
506 nsCOMPtr
<nsIMmsService
> mmsService
= do_GetService(MMS_SERVICE_CONTRACTID
);
508 aRv
.Throw(NS_ERROR_FAILURE
);
512 nsRefPtr
<DOMRequest
> request
= new DOMRequest(GetOwner());
513 nsCOMPtr
<nsIMobileMessageCallback
> msgCallback
= new MobileMessageCallback(request
);
515 nsresult rv
= mmsService
->Retrieve(aId
, msgCallback
);
521 return request
.forget();
524 already_AddRefed
<DOMRequest
>
525 MobileMessageManager::RetrieveMMS(nsIDOMMozMmsMessage
* aMessage
,
530 DebugOnly
<nsresult
> rv
= aMessage
->GetId(&id
);
531 MOZ_ASSERT(NS_SUCCEEDED(rv
));
533 return RetrieveMMS(id
, aRv
);
537 MobileMessageManager::DispatchTrustedSmsEventToSelf(const char* aTopic
,
538 const nsAString
& aEventName
,
541 nsCOMPtr
<nsIDOMMozSmsMessage
> sms
= do_QueryInterface(aMsg
);
543 MozSmsEventInit init
;
544 init
.mBubbles
= false;
545 init
.mCancelable
= false;
548 nsRefPtr
<MozSmsEvent
> event
=
549 MozSmsEvent::Constructor(this, aEventName
, init
);
550 return DispatchTrustedEvent(event
);
553 nsCOMPtr
<nsIDOMMozMmsMessage
> mms
= do_QueryInterface(aMsg
);
555 MozMmsEventInit init
;
556 init
.mBubbles
= false;
557 init
.mCancelable
= false;
560 nsRefPtr
<MozMmsEvent
> event
=
561 MozMmsEvent::Constructor(this, aEventName
, init
);
562 return DispatchTrustedEvent(event
);
565 nsAutoCString errorMsg
;
566 errorMsg
.AssignLiteral("Got a '");
567 errorMsg
.Append(aTopic
);
568 errorMsg
.AppendLiteral("' topic without a valid message!");
569 NS_ERROR(errorMsg
.get());
574 MobileMessageManager::DispatchTrustedDeletedEventToSelf(nsISupports
* aDeletedInfo
)
576 nsCOMPtr
<nsIDeletedMessageInfo
> deletedInfo
= do_QueryInterface(aDeletedInfo
);
578 MozMessageDeletedEventInit init
;
579 init
.mBubbles
= false;
580 init
.mCancelable
= false;
581 DeletedMessageInfo
* info
=
582 static_cast<DeletedMessageInfo
*>(deletedInfo
.get());
584 uint32_t msgIdLength
= info
->GetData().deletedMessageIds().Length();
586 Sequence
<int32_t>& deletedMsgIds
= init
.mDeletedMessageIds
.SetValue();
587 deletedMsgIds
.AppendElements(info
->GetData().deletedMessageIds());
590 uint32_t threadIdLength
= info
->GetData().deletedThreadIds().Length();
591 if (threadIdLength
) {
592 Sequence
<uint64_t>& deletedThreadIds
= init
.mDeletedThreadIds
.SetValue();
593 deletedThreadIds
.AppendElements(info
->GetData().deletedThreadIds());
596 nsRefPtr
<MozMessageDeletedEvent
> event
=
597 MozMessageDeletedEvent::Constructor(this, DELETED_EVENT_NAME
, init
);
598 return DispatchTrustedEvent(event
);
601 NS_ERROR("Got a 'deleted' topic without a valid message!");
607 MobileMessageManager::Observe(nsISupports
* aSubject
, const char* aTopic
,
608 const char16_t
* aData
)
610 if (!strcmp(aTopic
, kSmsReceivedObserverTopic
)) {
611 return DispatchTrustedSmsEventToSelf(aTopic
, RECEIVED_EVENT_NAME
, aSubject
);
614 if (!strcmp(aTopic
, kSmsRetrievingObserverTopic
)) {
615 return DispatchTrustedSmsEventToSelf(aTopic
, RETRIEVING_EVENT_NAME
, aSubject
);
618 if (!strcmp(aTopic
, kSmsSendingObserverTopic
)) {
619 return DispatchTrustedSmsEventToSelf(aTopic
, SENDING_EVENT_NAME
, aSubject
);
622 if (!strcmp(aTopic
, kSmsSentObserverTopic
)) {
623 return DispatchTrustedSmsEventToSelf(aTopic
, SENT_EVENT_NAME
, aSubject
);
626 if (!strcmp(aTopic
, kSmsFailedObserverTopic
)) {
627 return DispatchTrustedSmsEventToSelf(aTopic
, FAILED_EVENT_NAME
, aSubject
);
630 if (!strcmp(aTopic
, kSmsDeliverySuccessObserverTopic
)) {
631 return DispatchTrustedSmsEventToSelf(aTopic
, DELIVERY_SUCCESS_EVENT_NAME
, aSubject
);
634 if (!strcmp(aTopic
, kSmsDeliveryErrorObserverTopic
)) {
635 return DispatchTrustedSmsEventToSelf(aTopic
, DELIVERY_ERROR_EVENT_NAME
, aSubject
);
638 if (!strcmp(aTopic
, kSmsReadSuccessObserverTopic
)) {
639 return DispatchTrustedSmsEventToSelf(aTopic
, READ_SUCCESS_EVENT_NAME
, aSubject
);
642 if (!strcmp(aTopic
, kSmsReadErrorObserverTopic
)) {
643 return DispatchTrustedSmsEventToSelf(aTopic
, READ_ERROR_EVENT_NAME
, aSubject
);
646 if (!strcmp(aTopic
, kSmsDeletedObserverTopic
)) {
647 return DispatchTrustedDeletedEventToSelf(aSubject
);
653 already_AddRefed
<DOMRequest
>
654 MobileMessageManager::GetSmscAddress(const Optional
<uint32_t>& aServiceId
,
657 nsCOMPtr
<nsISmsService
> smsService
= do_GetService(SMS_SERVICE_CONTRACTID
);
659 aRv
.Throw(NS_ERROR_FAILURE
);
663 // Use the default one unless |aSendParams.serviceId| is available.
666 if (aServiceId
.WasPassed()) {
667 serviceId
= aServiceId
.Value();
669 rv
= smsService
->GetSmsDefaultServiceId(&serviceId
);
676 nsRefPtr
<DOMRequest
> request
= new DOMRequest(GetOwner());
677 nsCOMPtr
<nsIMobileMessageCallback
> msgCallback
= new MobileMessageCallback(request
);
678 rv
= smsService
->GetSmscAddress(serviceId
, msgCallback
);
684 return request
.forget();
688 } // namespace mozilla