|
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/. */ |
|
5 |
|
6 #include "SmsParent.h" |
|
7 #include "nsISmsService.h" |
|
8 #include "nsIMmsService.h" |
|
9 #include "nsIObserverService.h" |
|
10 #include "mozilla/Services.h" |
|
11 #include "nsIDOMMozSmsMessage.h" |
|
12 #include "nsIDOMMozMmsMessage.h" |
|
13 #include "mozilla/unused.h" |
|
14 #include "SmsMessage.h" |
|
15 #include "MmsMessage.h" |
|
16 #include "nsIMobileMessageDatabaseService.h" |
|
17 #include "SmsFilter.h" |
|
18 #include "SmsSegmentInfo.h" |
|
19 #include "MobileMessageThread.h" |
|
20 #include "nsIDOMFile.h" |
|
21 #include "mozilla/dom/ipc/Blob.h" |
|
22 #include "mozilla/dom/ContentParent.h" |
|
23 #include "mozilla/dom/mobilemessage/Constants.h" // For MessageType |
|
24 #include "nsContentUtils.h" |
|
25 #include "nsTArrayHelpers.h" |
|
26 #include "nsCxPusher.h" |
|
27 #include "xpcpublic.h" |
|
28 #include "nsServiceManagerUtils.h" |
|
29 |
|
30 namespace mozilla { |
|
31 namespace dom { |
|
32 namespace mobilemessage { |
|
33 |
|
34 static JSObject* |
|
35 MmsAttachmentDataToJSObject(JSContext* aContext, |
|
36 const MmsAttachmentData& aAttachment) |
|
37 { |
|
38 JS::Rooted<JSObject*> obj(aContext, JS_NewObject(aContext, nullptr, JS::NullPtr(), |
|
39 JS::NullPtr())); |
|
40 NS_ENSURE_TRUE(obj, nullptr); |
|
41 |
|
42 JS::Rooted<JSString*> idStr(aContext, JS_NewUCStringCopyN(aContext, |
|
43 aAttachment.id().get(), |
|
44 aAttachment.id().Length())); |
|
45 NS_ENSURE_TRUE(idStr, nullptr); |
|
46 if (!JS_DefineProperty(aContext, obj, "id", idStr, 0)) { |
|
47 return nullptr; |
|
48 } |
|
49 |
|
50 JS::Rooted<JSString*> locStr(aContext, JS_NewUCStringCopyN(aContext, |
|
51 aAttachment.location().get(), |
|
52 aAttachment.location().Length())); |
|
53 NS_ENSURE_TRUE(locStr, nullptr); |
|
54 if (!JS_DefineProperty(aContext, obj, "location", locStr, 0)) { |
|
55 return nullptr; |
|
56 } |
|
57 |
|
58 nsCOMPtr<nsIDOMBlob> blob = static_cast<BlobParent*>(aAttachment.contentParent())->GetBlob(); |
|
59 JS::Rooted<JS::Value> content(aContext); |
|
60 nsresult rv = nsContentUtils::WrapNative(aContext, |
|
61 blob, |
|
62 &NS_GET_IID(nsIDOMBlob), |
|
63 &content); |
|
64 NS_ENSURE_SUCCESS(rv, nullptr); |
|
65 if (!JS_DefineProperty(aContext, obj, "content", content, 0)) { |
|
66 return nullptr; |
|
67 } |
|
68 |
|
69 return obj; |
|
70 } |
|
71 |
|
72 static bool |
|
73 GetParamsFromSendMmsMessageRequest(JSContext* aCx, |
|
74 const SendMmsMessageRequest& aRequest, |
|
75 JS::Value* aParam) |
|
76 { |
|
77 JS::Rooted<JSObject*> paramsObj(aCx, JS_NewObject(aCx, nullptr, JS::NullPtr(), JS::NullPtr())); |
|
78 NS_ENSURE_TRUE(paramsObj, false); |
|
79 |
|
80 // smil |
|
81 JS::Rooted<JSString*> smilStr(aCx, JS_NewUCStringCopyN(aCx, |
|
82 aRequest.smil().get(), |
|
83 aRequest.smil().Length())); |
|
84 NS_ENSURE_TRUE(smilStr, false); |
|
85 if(!JS_DefineProperty(aCx, paramsObj, "smil", smilStr, 0)) { |
|
86 return false; |
|
87 } |
|
88 |
|
89 // subject |
|
90 JS::Rooted<JSString*> subjectStr(aCx, JS_NewUCStringCopyN(aCx, |
|
91 aRequest.subject().get(), |
|
92 aRequest.subject().Length())); |
|
93 NS_ENSURE_TRUE(subjectStr, false); |
|
94 if(!JS_DefineProperty(aCx, paramsObj, "subject", subjectStr, 0)) { |
|
95 return false; |
|
96 } |
|
97 |
|
98 // receivers |
|
99 JS::Rooted<JSObject*> receiverArray(aCx); |
|
100 if (NS_FAILED(nsTArrayToJSArray(aCx, |
|
101 aRequest.receivers(), |
|
102 receiverArray.address()))) { |
|
103 return false; |
|
104 } |
|
105 if (!JS_DefineProperty(aCx, paramsObj, "receivers", receiverArray, 0)) { |
|
106 return false; |
|
107 } |
|
108 |
|
109 // attachments |
|
110 JS::Rooted<JSObject*> attachmentArray(aCx, JS_NewArrayObject(aCx, |
|
111 aRequest.attachments().Length())); |
|
112 for (uint32_t i = 0; i < aRequest.attachments().Length(); i++) { |
|
113 JS::Rooted<JSObject*> obj(aCx, |
|
114 MmsAttachmentDataToJSObject(aCx, aRequest.attachments().ElementAt(i))); |
|
115 NS_ENSURE_TRUE(obj, false); |
|
116 if (!JS_SetElement(aCx, attachmentArray, i, obj)) { |
|
117 return false; |
|
118 } |
|
119 } |
|
120 |
|
121 if (!JS_DefineProperty(aCx, paramsObj, "attachments", attachmentArray, 0)) { |
|
122 return false; |
|
123 } |
|
124 |
|
125 aParam->setObject(*paramsObj); |
|
126 return true; |
|
127 } |
|
128 |
|
129 NS_IMPL_ISUPPORTS(SmsParent, nsIObserver) |
|
130 |
|
131 SmsParent::SmsParent() |
|
132 { |
|
133 MOZ_COUNT_CTOR(SmsParent); |
|
134 nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
|
135 if (!obs) { |
|
136 return; |
|
137 } |
|
138 |
|
139 obs->AddObserver(this, kSmsReceivedObserverTopic, false); |
|
140 obs->AddObserver(this, kSmsRetrievingObserverTopic, false); |
|
141 obs->AddObserver(this, kSmsSendingObserverTopic, false); |
|
142 obs->AddObserver(this, kSmsSentObserverTopic, false); |
|
143 obs->AddObserver(this, kSmsFailedObserverTopic, false); |
|
144 obs->AddObserver(this, kSmsDeliverySuccessObserverTopic, false); |
|
145 obs->AddObserver(this, kSmsDeliveryErrorObserverTopic, false); |
|
146 obs->AddObserver(this, kSilentSmsReceivedObserverTopic, false); |
|
147 obs->AddObserver(this, kSmsReadSuccessObserverTopic, false); |
|
148 obs->AddObserver(this, kSmsReadErrorObserverTopic, false); |
|
149 } |
|
150 |
|
151 void |
|
152 SmsParent::ActorDestroy(ActorDestroyReason why) |
|
153 { |
|
154 nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); |
|
155 if (!obs) { |
|
156 return; |
|
157 } |
|
158 |
|
159 obs->RemoveObserver(this, kSmsReceivedObserverTopic); |
|
160 obs->RemoveObserver(this, kSmsRetrievingObserverTopic); |
|
161 obs->RemoveObserver(this, kSmsSendingObserverTopic); |
|
162 obs->RemoveObserver(this, kSmsSentObserverTopic); |
|
163 obs->RemoveObserver(this, kSmsFailedObserverTopic); |
|
164 obs->RemoveObserver(this, kSmsDeliverySuccessObserverTopic); |
|
165 obs->RemoveObserver(this, kSmsDeliveryErrorObserverTopic); |
|
166 obs->RemoveObserver(this, kSilentSmsReceivedObserverTopic); |
|
167 obs->RemoveObserver(this, kSmsReadSuccessObserverTopic); |
|
168 obs->RemoveObserver(this, kSmsReadErrorObserverTopic); |
|
169 } |
|
170 |
|
171 NS_IMETHODIMP |
|
172 SmsParent::Observe(nsISupports* aSubject, const char* aTopic, |
|
173 const char16_t* aData) |
|
174 { |
|
175 if (!strcmp(aTopic, kSmsReceivedObserverTopic)) { |
|
176 MobileMessageData msgData; |
|
177 if (!GetMobileMessageDataFromMessage(aSubject, msgData)) { |
|
178 NS_ERROR("Got a 'sms-received' topic without a valid message!"); |
|
179 return NS_OK; |
|
180 } |
|
181 |
|
182 unused << SendNotifyReceivedMessage(msgData); |
|
183 return NS_OK; |
|
184 } |
|
185 |
|
186 if (!strcmp(aTopic, kSmsRetrievingObserverTopic)) { |
|
187 MobileMessageData msgData; |
|
188 if (!GetMobileMessageDataFromMessage(aSubject, msgData)) { |
|
189 NS_ERROR("Got a 'sms-retrieving' topic without a valid message!"); |
|
190 return NS_OK; |
|
191 } |
|
192 |
|
193 unused << SendNotifyRetrievingMessage(msgData); |
|
194 return NS_OK; |
|
195 } |
|
196 |
|
197 if (!strcmp(aTopic, kSmsSendingObserverTopic)) { |
|
198 MobileMessageData msgData; |
|
199 if (!GetMobileMessageDataFromMessage(aSubject, msgData)) { |
|
200 NS_ERROR("Got a 'sms-sending' topic without a valid message!"); |
|
201 return NS_OK; |
|
202 } |
|
203 |
|
204 unused << SendNotifySendingMessage(msgData); |
|
205 return NS_OK; |
|
206 } |
|
207 |
|
208 if (!strcmp(aTopic, kSmsSentObserverTopic)) { |
|
209 MobileMessageData msgData; |
|
210 if (!GetMobileMessageDataFromMessage(aSubject, msgData)) { |
|
211 NS_ERROR("Got a 'sms-sent' topic without a valid message!"); |
|
212 return NS_OK; |
|
213 } |
|
214 |
|
215 unused << SendNotifySentMessage(msgData); |
|
216 return NS_OK; |
|
217 } |
|
218 |
|
219 if (!strcmp(aTopic, kSmsFailedObserverTopic)) { |
|
220 MobileMessageData msgData; |
|
221 if (!GetMobileMessageDataFromMessage(aSubject, msgData)) { |
|
222 NS_ERROR("Got a 'sms-failed' topic without a valid message!"); |
|
223 return NS_OK; |
|
224 } |
|
225 |
|
226 unused << SendNotifyFailedMessage(msgData); |
|
227 return NS_OK; |
|
228 } |
|
229 |
|
230 if (!strcmp(aTopic, kSmsDeliverySuccessObserverTopic)) { |
|
231 MobileMessageData msgData; |
|
232 if (!GetMobileMessageDataFromMessage(aSubject, msgData)) { |
|
233 NS_ERROR("Got a 'sms-sending' topic without a valid message!"); |
|
234 return NS_OK; |
|
235 } |
|
236 |
|
237 unused << SendNotifyDeliverySuccessMessage(msgData); |
|
238 return NS_OK; |
|
239 } |
|
240 |
|
241 if (!strcmp(aTopic, kSmsDeliveryErrorObserverTopic)) { |
|
242 MobileMessageData msgData; |
|
243 if (!GetMobileMessageDataFromMessage(aSubject, msgData)) { |
|
244 NS_ERROR("Got a 'sms-delivery-error' topic without a valid message!"); |
|
245 return NS_OK; |
|
246 } |
|
247 |
|
248 unused << SendNotifyDeliveryErrorMessage(msgData); |
|
249 return NS_OK; |
|
250 } |
|
251 |
|
252 if (!strcmp(aTopic, kSilentSmsReceivedObserverTopic)) { |
|
253 nsCOMPtr<nsIDOMMozSmsMessage> smsMsg = do_QueryInterface(aSubject); |
|
254 if (!smsMsg) { |
|
255 return NS_OK; |
|
256 } |
|
257 |
|
258 nsString sender; |
|
259 if (NS_FAILED(smsMsg->GetSender(sender)) || |
|
260 !mSilentNumbers.Contains(sender)) { |
|
261 return NS_OK; |
|
262 } |
|
263 |
|
264 MobileMessageData msgData = |
|
265 static_cast<SmsMessage*>(smsMsg.get())->GetData(); |
|
266 unused << SendNotifyReceivedSilentMessage(msgData); |
|
267 return NS_OK; |
|
268 } |
|
269 |
|
270 |
|
271 if (!strcmp(aTopic, kSmsReadSuccessObserverTopic)) { |
|
272 MobileMessageData msgData; |
|
273 if (!GetMobileMessageDataFromMessage(aSubject, msgData)) { |
|
274 NS_ERROR("Got a 'sms-read-success' topic without a valid message!"); |
|
275 return NS_OK; |
|
276 } |
|
277 |
|
278 unused << SendNotifyReadSuccessMessage(msgData); |
|
279 return NS_OK; |
|
280 } |
|
281 |
|
282 if (!strcmp(aTopic, kSmsReadErrorObserverTopic)) { |
|
283 MobileMessageData msgData; |
|
284 if (!GetMobileMessageDataFromMessage(aSubject, msgData)) { |
|
285 NS_ERROR("Got a 'sms-read-error' topic without a valid message!"); |
|
286 return NS_OK; |
|
287 } |
|
288 |
|
289 unused << SendNotifyReadErrorMessage(msgData); |
|
290 return NS_OK; |
|
291 } |
|
292 |
|
293 |
|
294 return NS_OK; |
|
295 } |
|
296 |
|
297 bool |
|
298 SmsParent::GetMobileMessageDataFromMessage(nsISupports *aMsg, |
|
299 MobileMessageData &aData) |
|
300 { |
|
301 nsCOMPtr<nsIDOMMozMmsMessage> mmsMsg = do_QueryInterface(aMsg); |
|
302 if (mmsMsg) { |
|
303 MmsMessageData data; |
|
304 ContentParent *parent = static_cast<ContentParent*>(Manager()); |
|
305 if (!static_cast<MmsMessage*>(mmsMsg.get())->GetData(parent, data)) { |
|
306 return false; |
|
307 } |
|
308 aData = data; |
|
309 return true; |
|
310 } |
|
311 |
|
312 nsCOMPtr<nsIDOMMozSmsMessage> smsMsg = do_QueryInterface(aMsg); |
|
313 if (smsMsg) { |
|
314 aData = static_cast<SmsMessage*>(smsMsg.get())->GetData(); |
|
315 return true; |
|
316 } |
|
317 |
|
318 NS_WARNING("Cannot get MobileMessageData"); |
|
319 return false; |
|
320 } |
|
321 |
|
322 bool |
|
323 SmsParent::RecvAddSilentNumber(const nsString& aNumber) |
|
324 { |
|
325 if (mSilentNumbers.Contains(aNumber)) { |
|
326 return true; |
|
327 } |
|
328 |
|
329 nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID); |
|
330 NS_ENSURE_TRUE(smsService, true); |
|
331 |
|
332 nsresult rv = smsService->AddSilentNumber(aNumber); |
|
333 if (NS_SUCCEEDED(rv)) { |
|
334 mSilentNumbers.AppendElement(aNumber); |
|
335 } |
|
336 |
|
337 return true; |
|
338 } |
|
339 |
|
340 bool |
|
341 SmsParent::RecvRemoveSilentNumber(const nsString& aNumber) |
|
342 { |
|
343 if (!mSilentNumbers.Contains(aNumber)) { |
|
344 return true; |
|
345 } |
|
346 |
|
347 nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID); |
|
348 NS_ENSURE_TRUE(smsService, true); |
|
349 |
|
350 nsresult rv = smsService->RemoveSilentNumber(aNumber); |
|
351 if (NS_SUCCEEDED(rv)) { |
|
352 mSilentNumbers.RemoveElement(aNumber); |
|
353 } |
|
354 |
|
355 return true; |
|
356 } |
|
357 |
|
358 bool |
|
359 SmsParent::RecvPSmsRequestConstructor(PSmsRequestParent* aActor, |
|
360 const IPCSmsRequest& aRequest) |
|
361 { |
|
362 SmsRequestParent* actor = static_cast<SmsRequestParent*>(aActor); |
|
363 |
|
364 switch (aRequest.type()) { |
|
365 case IPCSmsRequest::TSendMessageRequest: |
|
366 return actor->DoRequest(aRequest.get_SendMessageRequest()); |
|
367 case IPCSmsRequest::TRetrieveMessageRequest: |
|
368 return actor->DoRequest(aRequest.get_RetrieveMessageRequest()); |
|
369 case IPCSmsRequest::TGetMessageRequest: |
|
370 return actor->DoRequest(aRequest.get_GetMessageRequest()); |
|
371 case IPCSmsRequest::TDeleteMessageRequest: |
|
372 return actor->DoRequest(aRequest.get_DeleteMessageRequest()); |
|
373 case IPCSmsRequest::TMarkMessageReadRequest: |
|
374 return actor->DoRequest(aRequest.get_MarkMessageReadRequest()); |
|
375 case IPCSmsRequest::TGetSegmentInfoForTextRequest: |
|
376 return actor->DoRequest(aRequest.get_GetSegmentInfoForTextRequest()); |
|
377 case IPCSmsRequest::TGetSmscAddressRequest: |
|
378 return actor->DoRequest(aRequest.get_GetSmscAddressRequest()); |
|
379 default: |
|
380 MOZ_CRASH("Unknown type!"); |
|
381 } |
|
382 |
|
383 return false; |
|
384 } |
|
385 |
|
386 PSmsRequestParent* |
|
387 SmsParent::AllocPSmsRequestParent(const IPCSmsRequest& aRequest) |
|
388 { |
|
389 SmsRequestParent* actor = new SmsRequestParent(); |
|
390 // Add an extra ref for IPDL. Will be released in |
|
391 // SmsParent::DeallocPSmsRequestParent(). |
|
392 actor->AddRef(); |
|
393 |
|
394 return actor; |
|
395 } |
|
396 |
|
397 bool |
|
398 SmsParent::DeallocPSmsRequestParent(PSmsRequestParent* aActor) |
|
399 { |
|
400 // SmsRequestParent is refcounted, must not be freed manually. |
|
401 static_cast<SmsRequestParent*>(aActor)->Release(); |
|
402 return true; |
|
403 } |
|
404 |
|
405 bool |
|
406 SmsParent::RecvPMobileMessageCursorConstructor(PMobileMessageCursorParent* aActor, |
|
407 const IPCMobileMessageCursor& aRequest) |
|
408 { |
|
409 MobileMessageCursorParent* actor = |
|
410 static_cast<MobileMessageCursorParent*>(aActor); |
|
411 |
|
412 switch (aRequest.type()) { |
|
413 case IPCMobileMessageCursor::TCreateMessageCursorRequest: |
|
414 return actor->DoRequest(aRequest.get_CreateMessageCursorRequest()); |
|
415 case IPCMobileMessageCursor::TCreateThreadCursorRequest: |
|
416 return actor->DoRequest(aRequest.get_CreateThreadCursorRequest()); |
|
417 default: |
|
418 MOZ_CRASH("Unknown type!"); |
|
419 } |
|
420 |
|
421 return false; |
|
422 } |
|
423 |
|
424 PMobileMessageCursorParent* |
|
425 SmsParent::AllocPMobileMessageCursorParent(const IPCMobileMessageCursor& aRequest) |
|
426 { |
|
427 MobileMessageCursorParent* actor = new MobileMessageCursorParent(); |
|
428 // Add an extra ref for IPDL. Will be released in |
|
429 // SmsParent::DeallocPMobileMessageCursorParent(). |
|
430 actor->AddRef(); |
|
431 |
|
432 return actor; |
|
433 } |
|
434 |
|
435 bool |
|
436 SmsParent::DeallocPMobileMessageCursorParent(PMobileMessageCursorParent* aActor) |
|
437 { |
|
438 // MobileMessageCursorParent is refcounted, must not be freed manually. |
|
439 static_cast<MobileMessageCursorParent*>(aActor)->Release(); |
|
440 return true; |
|
441 } |
|
442 |
|
443 /******************************************************************************* |
|
444 * SmsRequestParent |
|
445 ******************************************************************************/ |
|
446 |
|
447 NS_IMPL_ISUPPORTS(SmsRequestParent, nsIMobileMessageCallback) |
|
448 |
|
449 void |
|
450 SmsRequestParent::ActorDestroy(ActorDestroyReason aWhy) |
|
451 { |
|
452 mActorDestroyed = true; |
|
453 } |
|
454 |
|
455 bool |
|
456 SmsRequestParent::DoRequest(const SendMessageRequest& aRequest) |
|
457 { |
|
458 switch(aRequest.type()) { |
|
459 case SendMessageRequest::TSendSmsMessageRequest: { |
|
460 nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID); |
|
461 NS_ENSURE_TRUE(smsService, true); |
|
462 |
|
463 const SendSmsMessageRequest &req = aRequest.get_SendSmsMessageRequest(); |
|
464 smsService->Send(req.serviceId(), req.number(), req.message(), |
|
465 req.silent(), this); |
|
466 } |
|
467 break; |
|
468 case SendMessageRequest::TSendMmsMessageRequest: { |
|
469 nsCOMPtr<nsIMmsService> mmsService = do_GetService(MMS_SERVICE_CONTRACTID); |
|
470 NS_ENSURE_TRUE(mmsService, true); |
|
471 |
|
472 // There are cases (see bug 981202) where this is called with no JS on the |
|
473 // stack. And since mmsService might be JS-Implemented, we need to pass a |
|
474 // jsval to ::Send. Only system code should be looking at the result here, |
|
475 // so we just create it in the System-Principaled Junk Scope. |
|
476 AutoJSContext cx; |
|
477 JSAutoCompartment ac(cx, xpc::GetJunkScope()); |
|
478 JS::Rooted<JS::Value> params(cx); |
|
479 const SendMmsMessageRequest &req = aRequest.get_SendMmsMessageRequest(); |
|
480 if (!GetParamsFromSendMmsMessageRequest(cx, |
|
481 req, |
|
482 params.address())) { |
|
483 NS_WARNING("SmsRequestParent: Fail to build MMS params."); |
|
484 return true; |
|
485 } |
|
486 mmsService->Send(req.serviceId(), params, this); |
|
487 } |
|
488 break; |
|
489 default: |
|
490 MOZ_CRASH("Unknown type of SendMessageRequest!"); |
|
491 } |
|
492 return true; |
|
493 } |
|
494 |
|
495 bool |
|
496 SmsRequestParent::DoRequest(const RetrieveMessageRequest& aRequest) |
|
497 { |
|
498 nsresult rv = NS_ERROR_FAILURE; |
|
499 |
|
500 nsCOMPtr<nsIMmsService> mmsService = do_GetService(MMS_SERVICE_CONTRACTID); |
|
501 if (mmsService) { |
|
502 rv = mmsService->Retrieve(aRequest.messageId(), this); |
|
503 } |
|
504 |
|
505 if (NS_FAILED(rv)) { |
|
506 return NS_SUCCEEDED(NotifyGetMessageFailed(nsIMobileMessageCallback::INTERNAL_ERROR)); |
|
507 } |
|
508 |
|
509 return true; |
|
510 } |
|
511 |
|
512 bool |
|
513 SmsRequestParent::DoRequest(const GetMessageRequest& aRequest) |
|
514 { |
|
515 nsresult rv = NS_ERROR_FAILURE; |
|
516 |
|
517 nsCOMPtr<nsIMobileMessageDatabaseService> dbService = |
|
518 do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); |
|
519 if (dbService) { |
|
520 rv = dbService->GetMessageMoz(aRequest.messageId(), this); |
|
521 } |
|
522 |
|
523 if (NS_FAILED(rv)) { |
|
524 return NS_SUCCEEDED(NotifyGetMessageFailed(nsIMobileMessageCallback::INTERNAL_ERROR)); |
|
525 } |
|
526 |
|
527 return true; |
|
528 } |
|
529 |
|
530 bool |
|
531 SmsRequestParent::DoRequest(const GetSmscAddressRequest& aRequest) |
|
532 { |
|
533 nsresult rv = NS_ERROR_FAILURE; |
|
534 |
|
535 nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID); |
|
536 if (smsService) { |
|
537 rv = smsService->GetSmscAddress(aRequest.serviceId(), this); |
|
538 } |
|
539 |
|
540 if (NS_FAILED(rv)) { |
|
541 return NS_SUCCEEDED(NotifyGetSmscAddressFailed(nsIMobileMessageCallback::INTERNAL_ERROR)); |
|
542 } |
|
543 |
|
544 return true; |
|
545 } |
|
546 |
|
547 bool |
|
548 SmsRequestParent::DoRequest(const DeleteMessageRequest& aRequest) |
|
549 { |
|
550 nsresult rv = NS_ERROR_FAILURE; |
|
551 |
|
552 nsCOMPtr<nsIMobileMessageDatabaseService> dbService = |
|
553 do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); |
|
554 if (dbService) { |
|
555 const InfallibleTArray<int32_t>& messageIds = aRequest.messageIds(); |
|
556 rv = dbService->DeleteMessage(const_cast<int32_t *>(messageIds.Elements()), |
|
557 messageIds.Length(), this); |
|
558 } |
|
559 |
|
560 if (NS_FAILED(rv)) { |
|
561 return NS_SUCCEEDED(NotifyDeleteMessageFailed(nsIMobileMessageCallback::INTERNAL_ERROR)); |
|
562 } |
|
563 |
|
564 return true; |
|
565 } |
|
566 |
|
567 bool |
|
568 SmsRequestParent::DoRequest(const MarkMessageReadRequest& aRequest) |
|
569 { |
|
570 nsresult rv = NS_ERROR_FAILURE; |
|
571 |
|
572 nsCOMPtr<nsIMobileMessageDatabaseService> dbService = |
|
573 do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); |
|
574 if (dbService) { |
|
575 rv = dbService->MarkMessageRead(aRequest.messageId(), aRequest.value(), |
|
576 aRequest.sendReadReport(), this); |
|
577 } |
|
578 |
|
579 if (NS_FAILED(rv)) { |
|
580 return NS_SUCCEEDED(NotifyMarkMessageReadFailed(nsIMobileMessageCallback::INTERNAL_ERROR)); |
|
581 } |
|
582 |
|
583 return true; |
|
584 } |
|
585 |
|
586 bool |
|
587 SmsRequestParent::DoRequest(const GetSegmentInfoForTextRequest& aRequest) |
|
588 { |
|
589 nsresult rv = NS_ERROR_FAILURE; |
|
590 |
|
591 nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID); |
|
592 if (smsService) { |
|
593 rv = smsService->GetSegmentInfoForText(aRequest.text(), this); |
|
594 } |
|
595 |
|
596 if (NS_FAILED(rv)) { |
|
597 return NS_SUCCEEDED(NotifyGetSegmentInfoForTextFailed( |
|
598 nsIMobileMessageCallback::INTERNAL_ERROR)); |
|
599 } |
|
600 |
|
601 return true; |
|
602 } |
|
603 |
|
604 nsresult |
|
605 SmsRequestParent::SendReply(const MessageReply& aReply) |
|
606 { |
|
607 // The child process could die before this asynchronous notification, in which |
|
608 // case ActorDestroy() was called and mActorDestroyed is set to true. Return |
|
609 // an error here to avoid sending a message to the dead process. |
|
610 NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); |
|
611 |
|
612 return Send__delete__(this, aReply) ? NS_OK : NS_ERROR_FAILURE; |
|
613 } |
|
614 |
|
615 // nsIMobileMessageCallback |
|
616 |
|
617 NS_IMETHODIMP |
|
618 SmsRequestParent::NotifyMessageSent(nsISupports *aMessage) |
|
619 { |
|
620 NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); |
|
621 |
|
622 nsCOMPtr<nsIDOMMozMmsMessage> mms = do_QueryInterface(aMessage); |
|
623 if (mms) { |
|
624 MmsMessage *msg = static_cast<MmsMessage*>(mms.get()); |
|
625 ContentParent *parent = static_cast<ContentParent*>(Manager()->Manager()); |
|
626 MmsMessageData data; |
|
627 if (!msg->GetData(parent, data)) { |
|
628 return NS_ERROR_FAILURE; |
|
629 } |
|
630 return SendReply(ReplyMessageSend(MobileMessageData(data))); |
|
631 } |
|
632 |
|
633 nsCOMPtr<nsIDOMMozSmsMessage> sms = do_QueryInterface(aMessage); |
|
634 if (sms) { |
|
635 SmsMessage* msg = static_cast<SmsMessage*>(sms.get()); |
|
636 return SendReply(ReplyMessageSend(MobileMessageData(msg->GetData()))); |
|
637 } |
|
638 |
|
639 return NS_ERROR_FAILURE; |
|
640 } |
|
641 |
|
642 NS_IMETHODIMP |
|
643 SmsRequestParent::NotifySendMessageFailed(int32_t aError) |
|
644 { |
|
645 return SendReply(ReplyMessageSendFail(aError)); |
|
646 } |
|
647 |
|
648 NS_IMETHODIMP |
|
649 SmsRequestParent::NotifyMessageGot(nsISupports *aMessage) |
|
650 { |
|
651 NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); |
|
652 |
|
653 nsCOMPtr<nsIDOMMozMmsMessage> mms = do_QueryInterface(aMessage); |
|
654 if (mms) { |
|
655 MmsMessage *msg = static_cast<MmsMessage*>(mms.get()); |
|
656 ContentParent *parent = static_cast<ContentParent*>(Manager()->Manager()); |
|
657 MmsMessageData data; |
|
658 if (!msg->GetData(parent, data)) { |
|
659 return NS_ERROR_FAILURE; |
|
660 } |
|
661 return SendReply(ReplyGetMessage(MobileMessageData(data))); |
|
662 } |
|
663 |
|
664 nsCOMPtr<nsIDOMMozSmsMessage> sms = do_QueryInterface(aMessage); |
|
665 if (sms) { |
|
666 SmsMessage* msg = static_cast<SmsMessage*>(sms.get()); |
|
667 return SendReply(ReplyGetMessage(MobileMessageData(msg->GetData()))); |
|
668 } |
|
669 |
|
670 return NS_ERROR_FAILURE; |
|
671 } |
|
672 |
|
673 NS_IMETHODIMP |
|
674 SmsRequestParent::NotifyGetMessageFailed(int32_t aError) |
|
675 { |
|
676 return SendReply(ReplyGetMessageFail(aError)); |
|
677 } |
|
678 |
|
679 NS_IMETHODIMP |
|
680 SmsRequestParent::NotifyMessageDeleted(bool *aDeleted, uint32_t aSize) |
|
681 { |
|
682 ReplyMessageDelete data; |
|
683 data.deleted().AppendElements(aDeleted, aSize); |
|
684 return SendReply(data); |
|
685 } |
|
686 |
|
687 NS_IMETHODIMP |
|
688 SmsRequestParent::NotifyDeleteMessageFailed(int32_t aError) |
|
689 { |
|
690 return SendReply(ReplyMessageDeleteFail(aError)); |
|
691 } |
|
692 |
|
693 NS_IMETHODIMP |
|
694 SmsRequestParent::NotifyMessageMarkedRead(bool aRead) |
|
695 { |
|
696 return SendReply(ReplyMarkeMessageRead(aRead)); |
|
697 } |
|
698 |
|
699 NS_IMETHODIMP |
|
700 SmsRequestParent::NotifyMarkMessageReadFailed(int32_t aError) |
|
701 { |
|
702 return SendReply(ReplyMarkeMessageReadFail(aError)); |
|
703 } |
|
704 |
|
705 NS_IMETHODIMP |
|
706 SmsRequestParent::NotifySegmentInfoForTextGot(nsIDOMMozSmsSegmentInfo *aInfo) |
|
707 { |
|
708 SmsSegmentInfo* info = static_cast<SmsSegmentInfo*>(aInfo); |
|
709 return SendReply(ReplyGetSegmentInfoForText(info->GetData())); |
|
710 } |
|
711 |
|
712 NS_IMETHODIMP |
|
713 SmsRequestParent::NotifyGetSegmentInfoForTextFailed(int32_t aError) |
|
714 { |
|
715 return SendReply(ReplyGetSegmentInfoForTextFail(aError)); |
|
716 } |
|
717 |
|
718 NS_IMETHODIMP |
|
719 SmsRequestParent::NotifyGetSmscAddress(const nsAString& aSmscAddress) |
|
720 { |
|
721 return SendReply(ReplyGetSmscAddress(nsString(aSmscAddress))); |
|
722 } |
|
723 |
|
724 NS_IMETHODIMP |
|
725 SmsRequestParent::NotifyGetSmscAddressFailed(int32_t aError) |
|
726 { |
|
727 return SendReply(ReplyGetSmscAddressFail(aError)); |
|
728 } |
|
729 |
|
730 /******************************************************************************* |
|
731 * MobileMessageCursorParent |
|
732 ******************************************************************************/ |
|
733 |
|
734 NS_IMPL_ISUPPORTS(MobileMessageCursorParent, nsIMobileMessageCursorCallback) |
|
735 |
|
736 void |
|
737 MobileMessageCursorParent::ActorDestroy(ActorDestroyReason aWhy) |
|
738 { |
|
739 // Two possible scenarios here: |
|
740 // 1) When parent fails to SendNotifyResult() in NotifyCursorResult(), it's |
|
741 // destroyed without nulling out mContinueCallback. |
|
742 // 2) When parent dies normally, mContinueCallback should have been cleared in |
|
743 // NotifyCursorError(), but just ensure this again. |
|
744 mContinueCallback = nullptr; |
|
745 } |
|
746 |
|
747 bool |
|
748 MobileMessageCursorParent::RecvContinue() |
|
749 { |
|
750 MOZ_ASSERT(mContinueCallback); |
|
751 |
|
752 if (NS_FAILED(mContinueCallback->HandleContinue())) { |
|
753 return NS_SUCCEEDED(NotifyCursorError(nsIMobileMessageCallback::INTERNAL_ERROR)); |
|
754 } |
|
755 |
|
756 return true; |
|
757 } |
|
758 |
|
759 bool |
|
760 MobileMessageCursorParent::DoRequest(const CreateMessageCursorRequest& aRequest) |
|
761 { |
|
762 nsresult rv = NS_ERROR_FAILURE; |
|
763 |
|
764 nsCOMPtr<nsIMobileMessageDatabaseService> dbService = |
|
765 do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); |
|
766 if (dbService) { |
|
767 nsCOMPtr<nsIDOMMozSmsFilter> filter = new SmsFilter(aRequest.filter()); |
|
768 bool reverse = aRequest.reverse(); |
|
769 |
|
770 rv = dbService->CreateMessageCursor(filter, reverse, this, |
|
771 getter_AddRefs(mContinueCallback)); |
|
772 } |
|
773 |
|
774 if (NS_FAILED(rv)) { |
|
775 return NS_SUCCEEDED(NotifyCursorError(nsIMobileMessageCallback::INTERNAL_ERROR)); |
|
776 } |
|
777 |
|
778 return true; |
|
779 } |
|
780 |
|
781 bool |
|
782 MobileMessageCursorParent::DoRequest(const CreateThreadCursorRequest& aRequest) |
|
783 { |
|
784 nsresult rv = NS_ERROR_FAILURE; |
|
785 |
|
786 nsCOMPtr<nsIMobileMessageDatabaseService> dbService = |
|
787 do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); |
|
788 if (dbService) { |
|
789 rv = dbService->CreateThreadCursor(this, |
|
790 getter_AddRefs(mContinueCallback)); |
|
791 } |
|
792 |
|
793 if (NS_FAILED(rv)) { |
|
794 return NS_SUCCEEDED(NotifyCursorError(nsIMobileMessageCallback::INTERNAL_ERROR)); |
|
795 } |
|
796 |
|
797 return true; |
|
798 } |
|
799 |
|
800 // nsIMobileMessageCursorCallback |
|
801 |
|
802 NS_IMETHODIMP |
|
803 MobileMessageCursorParent::NotifyCursorError(int32_t aError) |
|
804 { |
|
805 // The child process could die before this asynchronous notification, in which |
|
806 // case ActorDestroy() was called and mContinueCallback is now null. Return an |
|
807 // error here to avoid sending a message to the dead process. |
|
808 NS_ENSURE_TRUE(mContinueCallback, NS_ERROR_FAILURE); |
|
809 |
|
810 mContinueCallback = nullptr; |
|
811 |
|
812 return Send__delete__(this, aError) ? NS_OK : NS_ERROR_FAILURE; |
|
813 } |
|
814 |
|
815 NS_IMETHODIMP |
|
816 MobileMessageCursorParent::NotifyCursorResult(nsISupports* aResult) |
|
817 { |
|
818 // The child process could die before this asynchronous notification, in which |
|
819 // case ActorDestroy() was called and mContinueCallback is now null. Return an |
|
820 // error here to avoid sending a message to the dead process. |
|
821 NS_ENSURE_TRUE(mContinueCallback, NS_ERROR_FAILURE); |
|
822 |
|
823 nsCOMPtr<nsIDOMMozSmsMessage> iSms = do_QueryInterface(aResult); |
|
824 if (iSms) { |
|
825 SmsMessage* message = static_cast<SmsMessage*>(aResult); |
|
826 return SendNotifyResult(MobileMessageCursorData(message->GetData())) |
|
827 ? NS_OK : NS_ERROR_FAILURE; |
|
828 } |
|
829 |
|
830 nsCOMPtr<nsIDOMMozMmsMessage> iMms = do_QueryInterface(aResult); |
|
831 if (iMms) { |
|
832 MmsMessage* message = static_cast<MmsMessage*>(aResult); |
|
833 ContentParent* parent = static_cast<ContentParent*>(Manager()->Manager()); |
|
834 MmsMessageData data; |
|
835 if (!message->GetData(parent, data)) { |
|
836 return NS_ERROR_FAILURE; |
|
837 } |
|
838 return SendNotifyResult(MobileMessageCursorData(data)) |
|
839 ? NS_OK : NS_ERROR_FAILURE; |
|
840 } |
|
841 |
|
842 nsCOMPtr<nsIDOMMozMobileMessageThread> iThread = do_QueryInterface(aResult); |
|
843 if (iThread) { |
|
844 MobileMessageThread* thread = static_cast<MobileMessageThread*>(aResult); |
|
845 return SendNotifyResult(MobileMessageCursorData(thread->GetData())) |
|
846 ? NS_OK : NS_ERROR_FAILURE; |
|
847 } |
|
848 |
|
849 MOZ_CRASH("Received invalid response parameters!"); |
|
850 } |
|
851 |
|
852 NS_IMETHODIMP |
|
853 MobileMessageCursorParent::NotifyCursorDone() |
|
854 { |
|
855 return NotifyCursorError(nsIMobileMessageCallback::SUCCESS_NO_ERROR); |
|
856 } |
|
857 |
|
858 } // namespace mobilemessage |
|
859 } // namespace dom |
|
860 } // namespace mozilla |