Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 "MmsMessage.h"
7 #include "nsIDOMClassInfo.h"
8 #include "jsapi.h" // For OBJECT_TO_JSVAL and JS_NewDateObjectMsec
9 #include "jsfriendapi.h" // For js_DateGetMsecSinceEpoch
10 #include "nsJSUtils.h"
11 #include "nsContentUtils.h"
12 #include "nsIDOMFile.h"
13 #include "nsTArrayHelpers.h"
14 #include "mozilla/dom/ContentParent.h"
15 #include "mozilla/dom/mobilemessage/Constants.h" // For MessageType
16 #include "mozilla/dom/mobilemessage/SmsTypes.h"
17 #include "mozilla/dom/ToJSValue.h"
18 #include "nsDOMFile.h"
19 #include "nsCxPusher.h"
21 using namespace mozilla::dom::mobilemessage;
23 DOMCI_DATA(MozMmsMessage, mozilla::dom::MmsMessage)
25 namespace mozilla {
26 namespace dom {
28 NS_INTERFACE_MAP_BEGIN(MmsMessage)
29 NS_INTERFACE_MAP_ENTRY(nsIDOMMozMmsMessage)
30 NS_INTERFACE_MAP_ENTRY(nsISupports)
31 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozMmsMessage)
32 NS_INTERFACE_MAP_END
34 NS_IMPL_ADDREF(MmsMessage)
35 NS_IMPL_RELEASE(MmsMessage)
37 MmsMessage::MmsMessage(int32_t aId,
38 uint64_t aThreadId,
39 const nsAString& aIccId,
40 DeliveryState aDelivery,
41 const nsTArray<MmsDeliveryInfo>& aDeliveryInfo,
42 const nsAString& aSender,
43 const nsTArray<nsString>& aReceivers,
44 uint64_t aTimestamp,
45 uint64_t aSentTimestamp,
46 bool aRead,
47 const nsAString& aSubject,
48 const nsAString& aSmil,
49 const nsTArray<Attachment>& aAttachments,
50 uint64_t aExpiryDate,
51 bool aReadReportRequested)
52 : mId(aId),
53 mThreadId(aThreadId),
54 mIccId(aIccId),
55 mDelivery(aDelivery),
56 mDeliveryInfo(aDeliveryInfo),
57 mSender(aSender),
58 mReceivers(aReceivers),
59 mTimestamp(aTimestamp),
60 mSentTimestamp(aSentTimestamp),
61 mRead(aRead),
62 mSubject(aSubject),
63 mSmil(aSmil),
64 mAttachments(aAttachments),
65 mExpiryDate(aExpiryDate),
66 mReadReportRequested(aReadReportRequested)
67 {
68 }
70 MmsMessage::MmsMessage(const mobilemessage::MmsMessageData& aData)
71 : mId(aData.id())
72 , mThreadId(aData.threadId())
73 , mIccId(aData.iccId())
74 , mDelivery(aData.delivery())
75 , mSender(aData.sender())
76 , mReceivers(aData.receivers())
77 , mTimestamp(aData.timestamp())
78 , mSentTimestamp(aData.sentTimestamp())
79 , mRead(aData.read())
80 , mSubject(aData.subject())
81 , mSmil(aData.smil())
82 , mExpiryDate(aData.expiryDate())
83 , mReadReportRequested(aData.readReportRequested())
84 {
85 uint32_t len = aData.attachments().Length();
86 mAttachments.SetCapacity(len);
87 for (uint32_t i = 0; i < len; i++) {
88 MmsAttachment att;
89 const MmsAttachmentData &element = aData.attachments()[i];
90 att.mId = element.id();
91 att.mLocation = element.location();
92 if (element.contentParent()) {
93 att.mContent = static_cast<BlobParent*>(element.contentParent())->GetBlob();
94 } else if (element.contentChild()) {
95 att.mContent = static_cast<BlobChild*>(element.contentChild())->GetBlob();
96 } else {
97 NS_WARNING("MmsMessage: Unable to get attachment content.");
98 }
99 mAttachments.AppendElement(att);
100 }
102 len = aData.deliveryInfo().Length();
103 mDeliveryInfo.SetCapacity(len);
104 for (uint32_t i = 0; i < len; i++) {
105 MmsDeliveryInfo info;
106 const MmsDeliveryInfoData &infoData = aData.deliveryInfo()[i];
108 // Prepare |info.mReceiver|.
109 info.mReceiver = infoData.receiver();
111 // Prepare |info.mDeliveryStatus|.
112 nsString statusStr;
113 switch (infoData.deliveryStatus()) {
114 case eDeliveryStatus_NotApplicable:
115 statusStr = DELIVERY_STATUS_NOT_APPLICABLE;
116 break;
117 case eDeliveryStatus_Success:
118 statusStr = DELIVERY_STATUS_SUCCESS;
119 break;
120 case eDeliveryStatus_Pending:
121 statusStr = DELIVERY_STATUS_PENDING;
122 break;
123 case eDeliveryStatus_Error:
124 statusStr = DELIVERY_STATUS_ERROR;
125 break;
126 case eDeliveryStatus_Reject:
127 statusStr = DELIVERY_STATUS_REJECTED;
128 break;
129 case eDeliveryStatus_Manual:
130 statusStr = DELIVERY_STATUS_MANUAL;
131 break;
132 case eDeliveryStatus_EndGuard:
133 default:
134 MOZ_CRASH("We shouldn't get any other delivery status!");
135 }
136 info.mDeliveryStatus = statusStr;
138 // Prepare |info.mDeliveryTimestamp|.
139 info.mDeliveryTimestamp = infoData.deliveryTimestamp();
141 // Prepare |info.mReadStatus|.
142 nsString statusReadString;
143 switch(infoData.readStatus()) {
144 case eReadStatus_NotApplicable:
145 statusReadString = READ_STATUS_NOT_APPLICABLE;
146 break;
147 case eReadStatus_Success:
148 statusReadString = READ_STATUS_SUCCESS;
149 break;
150 case eReadStatus_Pending:
151 statusReadString = READ_STATUS_PENDING;
152 break;
153 case eReadStatus_Error:
154 statusReadString = READ_STATUS_ERROR;
155 break;
156 case eReadStatus_EndGuard:
157 default:
158 MOZ_CRASH("We shouldn't get any other read status!");
159 }
160 info.mReadStatus = statusReadString;
162 // Prepare |info.mReadTimestamp|.
163 info.mReadTimestamp = infoData.readTimestamp();
165 mDeliveryInfo.AppendElement(info);
166 }
167 }
169 /* static */ nsresult
170 MmsMessage::Create(int32_t aId,
171 uint64_t aThreadId,
172 const nsAString& aIccId,
173 const nsAString& aDelivery,
174 const JS::Value& aDeliveryInfo,
175 const nsAString& aSender,
176 const JS::Value& aReceivers,
177 uint64_t aTimestamp,
178 uint64_t aSentTimestamp,
179 bool aRead,
180 const nsAString& aSubject,
181 const nsAString& aSmil,
182 const JS::Value& aAttachments,
183 uint64_t aExpiryDate,
184 bool aIsReadReportRequested,
185 JSContext* aCx,
186 nsIDOMMozMmsMessage** aMessage)
187 {
188 *aMessage = nullptr;
190 // Set |delivery|.
191 DeliveryState delivery;
192 if (aDelivery.Equals(DELIVERY_SENT)) {
193 delivery = eDeliveryState_Sent;
194 } else if (aDelivery.Equals(DELIVERY_RECEIVED)) {
195 delivery = eDeliveryState_Received;
196 } else if (aDelivery.Equals(DELIVERY_SENDING)) {
197 delivery = eDeliveryState_Sending;
198 } else if (aDelivery.Equals(DELIVERY_NOT_DOWNLOADED)) {
199 delivery = eDeliveryState_NotDownloaded;
200 } else if (aDelivery.Equals(DELIVERY_ERROR)) {
201 delivery = eDeliveryState_Error;
202 } else {
203 return NS_ERROR_INVALID_ARG;
204 }
206 // Set |deliveryInfo|.
207 if (!aDeliveryInfo.isObject()) {
208 return NS_ERROR_INVALID_ARG;
209 }
210 JS::Rooted<JSObject*> deliveryInfoObj(aCx, &aDeliveryInfo.toObject());
211 if (!JS_IsArrayObject(aCx, deliveryInfoObj)) {
212 return NS_ERROR_INVALID_ARG;
213 }
215 uint32_t length;
216 MOZ_ALWAYS_TRUE(JS_GetArrayLength(aCx, deliveryInfoObj, &length));
218 nsTArray<MmsDeliveryInfo> deliveryInfo;
219 JS::Rooted<JS::Value> infoJsVal(aCx);
220 for (uint32_t i = 0; i < length; ++i) {
221 if (!JS_GetElement(aCx, deliveryInfoObj, i, &infoJsVal) ||
222 !infoJsVal.isObject()) {
223 return NS_ERROR_INVALID_ARG;
224 }
226 MmsDeliveryInfo info;
227 if (!info.Init(aCx, infoJsVal)) {
228 return NS_ERROR_TYPE_ERR;
229 }
231 deliveryInfo.AppendElement(info);
232 }
234 // Set |receivers|.
235 if (!aReceivers.isObject()) {
236 return NS_ERROR_INVALID_ARG;
237 }
238 JS::Rooted<JSObject*> receiversObj(aCx, &aReceivers.toObject());
239 if (!JS_IsArrayObject(aCx, receiversObj)) {
240 return NS_ERROR_INVALID_ARG;
241 }
243 MOZ_ALWAYS_TRUE(JS_GetArrayLength(aCx, receiversObj, &length));
245 nsTArray<nsString> receivers;
246 JS::Rooted<JS::Value> receiverJsVal(aCx);
247 for (uint32_t i = 0; i < length; ++i) {
248 if (!JS_GetElement(aCx, receiversObj, i, &receiverJsVal) ||
249 !receiverJsVal.isString()) {
250 return NS_ERROR_INVALID_ARG;
251 }
253 nsDependentJSString receiverStr;
254 receiverStr.init(aCx, receiverJsVal.toString());
255 receivers.AppendElement(receiverStr);
256 }
258 // Set |attachments|.
259 if (!aAttachments.isObject()) {
260 return NS_ERROR_INVALID_ARG;
261 }
262 JS::Rooted<JSObject*> attachmentsObj(aCx, &aAttachments.toObject());
263 if (!JS_IsArrayObject(aCx, attachmentsObj)) {
264 return NS_ERROR_INVALID_ARG;
265 }
267 nsTArray<Attachment> attachments;
268 MOZ_ALWAYS_TRUE(JS_GetArrayLength(aCx, attachmentsObj, &length));
270 JS::Rooted<JS::Value> attachmentJsVal(aCx);
271 for (uint32_t i = 0; i < length; ++i) {
272 if (!JS_GetElement(aCx, attachmentsObj, i, &attachmentJsVal)) {
273 return NS_ERROR_INVALID_ARG;
274 }
276 MmsAttachment attachment;
277 if (!attachment.Init(aCx, attachmentJsVal)) {
278 return NS_ERROR_TYPE_ERR;
279 }
281 attachments.AppendElement(attachment);
282 }
284 nsCOMPtr<nsIDOMMozMmsMessage> message = new MmsMessage(aId,
285 aThreadId,
286 aIccId,
287 delivery,
288 deliveryInfo,
289 aSender,
290 receivers,
291 aTimestamp,
292 aSentTimestamp,
293 aRead,
294 aSubject,
295 aSmil,
296 attachments,
297 aExpiryDate,
298 aIsReadReportRequested);
299 message.forget(aMessage);
300 return NS_OK;
301 }
303 bool
304 MmsMessage::GetData(ContentParent* aParent,
305 mobilemessage::MmsMessageData& aData)
306 {
307 NS_ASSERTION(aParent, "aParent is null");
309 aData.id() = mId;
310 aData.threadId() = mThreadId;
311 aData.iccId() = mIccId;
312 aData.delivery() = mDelivery;
313 aData.sender().Assign(mSender);
314 aData.receivers() = mReceivers;
315 aData.timestamp() = mTimestamp;
316 aData.sentTimestamp() = mSentTimestamp;
317 aData.read() = mRead;
318 aData.subject() = mSubject;
319 aData.smil() = mSmil;
320 aData.expiryDate() = mExpiryDate;
321 aData.readReportRequested() = mReadReportRequested;
323 aData.deliveryInfo().SetCapacity(mDeliveryInfo.Length());
324 for (uint32_t i = 0; i < mDeliveryInfo.Length(); i++) {
325 MmsDeliveryInfoData infoData;
326 const MmsDeliveryInfo &info = mDeliveryInfo[i];
328 // Prepare |infoData.mReceiver|.
329 infoData.receiver().Assign(info.mReceiver);
331 // Prepare |infoData.mDeliveryStatus|.
332 DeliveryStatus status;
333 if (info.mDeliveryStatus.Equals(DELIVERY_STATUS_NOT_APPLICABLE)) {
334 status = eDeliveryStatus_NotApplicable;
335 } else if (info.mDeliveryStatus.Equals(DELIVERY_STATUS_SUCCESS)) {
336 status = eDeliveryStatus_Success;
337 } else if (info.mDeliveryStatus.Equals(DELIVERY_STATUS_PENDING)) {
338 status = eDeliveryStatus_Pending;
339 } else if (info.mDeliveryStatus.Equals(DELIVERY_STATUS_ERROR)) {
340 status = eDeliveryStatus_Error;
341 } else if (info.mDeliveryStatus.Equals(DELIVERY_STATUS_REJECTED)) {
342 status = eDeliveryStatus_Reject;
343 } else if (info.mDeliveryStatus.Equals(DELIVERY_STATUS_MANUAL)) {
344 status = eDeliveryStatus_Manual;
345 } else {
346 return false;
347 }
348 infoData.deliveryStatus() = status;
350 // Prepare |infoData.mDeliveryTimestamp|.
351 infoData.deliveryTimestamp() = info.mDeliveryTimestamp;
353 // Prepare |infoData.mReadStatus|.
354 ReadStatus readStatus;
355 if (info.mReadStatus.Equals(READ_STATUS_NOT_APPLICABLE)) {
356 readStatus = eReadStatus_NotApplicable;
357 } else if (info.mReadStatus.Equals(READ_STATUS_SUCCESS)) {
358 readStatus = eReadStatus_Success;
359 } else if (info.mReadStatus.Equals(READ_STATUS_PENDING)) {
360 readStatus = eReadStatus_Pending;
361 } else if (info.mReadStatus.Equals(READ_STATUS_ERROR)) {
362 readStatus = eReadStatus_Error;
363 } else {
364 return false;
365 }
366 infoData.readStatus() = readStatus;
368 // Prepare |infoData.mReadTimestamp|.
369 infoData.readTimestamp() = info.mReadTimestamp;
371 aData.deliveryInfo().AppendElement(infoData);
372 }
374 aData.attachments().SetCapacity(mAttachments.Length());
375 for (uint32_t i = 0; i < mAttachments.Length(); i++) {
376 MmsAttachmentData mma;
377 const Attachment &element = mAttachments[i];
378 mma.id().Assign(element.id);
379 mma.location().Assign(element.location);
381 // This is a workaround. Sometimes the blob we get from the database
382 // doesn't have a valid last modified date, making the ContentParent
383 // send a "Mystery Blob" to the ContentChild. Attempting to get the
384 // last modified date of blob can force that value to be initialized.
385 nsDOMFileBase* file = static_cast<nsDOMFileBase*>(element.content.get());
386 if (file->IsDateUnknown()) {
387 uint64_t date;
388 if (NS_FAILED(file->GetMozLastModifiedDate(&date))) {
389 NS_WARNING("Failed to get last modified date!");
390 }
391 }
393 mma.contentParent() = aParent->GetOrCreateActorForBlob(element.content);
394 if (!mma.contentParent()) {
395 return false;
396 }
397 aData.attachments().AppendElement(mma);
398 }
400 return true;
401 }
403 NS_IMETHODIMP
404 MmsMessage::GetType(nsAString& aType)
405 {
406 aType = NS_LITERAL_STRING("mms");
407 return NS_OK;
408 }
410 NS_IMETHODIMP
411 MmsMessage::GetId(int32_t* aId)
412 {
413 *aId = mId;
414 return NS_OK;
415 }
417 NS_IMETHODIMP
418 MmsMessage::GetThreadId(uint64_t* aThreadId)
419 {
420 *aThreadId = mThreadId;
421 return NS_OK;
422 }
424 NS_IMETHODIMP
425 MmsMessage::GetIccId(nsAString& aIccId)
426 {
427 aIccId = mIccId;
428 return NS_OK;
429 }
431 NS_IMETHODIMP
432 MmsMessage::GetDelivery(nsAString& aDelivery)
433 {
434 switch (mDelivery) {
435 case eDeliveryState_Received:
436 aDelivery = DELIVERY_RECEIVED;
437 break;
438 case eDeliveryState_Sending:
439 aDelivery = DELIVERY_SENDING;
440 break;
441 case eDeliveryState_Sent:
442 aDelivery = DELIVERY_SENT;
443 break;
444 case eDeliveryState_Error:
445 aDelivery = DELIVERY_ERROR;
446 break;
447 case eDeliveryState_NotDownloaded:
448 aDelivery = DELIVERY_NOT_DOWNLOADED;
449 break;
450 case eDeliveryState_Unknown:
451 case eDeliveryState_EndGuard:
452 default:
453 MOZ_CRASH("We shouldn't get any other delivery state!");
454 }
456 return NS_OK;
457 }
459 NS_IMETHODIMP
460 MmsMessage::GetDeliveryInfo(JSContext* aCx, JS::MutableHandle<JS::Value> aDeliveryInfo)
461 {
462 // TODO Bug 850525 It'd be better to depend on the delivery of MmsMessage
463 // to return a more correct value. Ex, if .delivery = 'received', we should
464 // also make .deliveryInfo = null, since the .deliveryInfo is useless.
465 uint32_t length = mDeliveryInfo.Length();
466 if (length == 0) {
467 aDeliveryInfo.setNull();
468 return NS_OK;
469 }
471 if (!ToJSValue(aCx, mDeliveryInfo, aDeliveryInfo)) {
472 return NS_ERROR_OUT_OF_MEMORY;
473 }
475 return NS_OK;
476 }
478 NS_IMETHODIMP
479 MmsMessage::GetSender(nsAString& aSender)
480 {
481 aSender = mSender;
482 return NS_OK;
483 }
485 NS_IMETHODIMP
486 MmsMessage::GetReceivers(JSContext* aCx, JS::MutableHandle<JS::Value> aReceivers)
487 {
488 JS::Rooted<JSObject*> reveiversObj(aCx);
489 nsresult rv = nsTArrayToJSArray(aCx, mReceivers, reveiversObj.address());
490 NS_ENSURE_SUCCESS(rv, rv);
492 aReceivers.setObject(*reveiversObj);
493 return NS_OK;
494 }
496 NS_IMETHODIMP
497 MmsMessage::GetTimestamp(DOMTimeStamp* aTimestamp)
498 {
499 *aTimestamp = mTimestamp;
500 return NS_OK;
501 }
503 NS_IMETHODIMP
504 MmsMessage::GetSentTimestamp(DOMTimeStamp* aSentTimestamp)
505 {
506 *aSentTimestamp = mSentTimestamp;
507 return NS_OK;
508 }
510 NS_IMETHODIMP
511 MmsMessage::GetRead(bool* aRead)
512 {
513 *aRead = mRead;
514 return NS_OK;
515 }
517 NS_IMETHODIMP
518 MmsMessage::GetSubject(nsAString& aSubject)
519 {
520 aSubject = mSubject;
521 return NS_OK;
522 }
524 NS_IMETHODIMP
525 MmsMessage::GetSmil(nsAString& aSmil)
526 {
527 aSmil = mSmil;
528 return NS_OK;
529 }
531 NS_IMETHODIMP
532 MmsMessage::GetAttachments(JSContext* aCx, JS::MutableHandle<JS::Value> aAttachments)
533 {
534 uint32_t length = mAttachments.Length();
536 JS::Rooted<JSObject*> attachments(
537 aCx, JS_NewArrayObject(aCx, length));
538 NS_ENSURE_TRUE(attachments, NS_ERROR_OUT_OF_MEMORY);
540 for (uint32_t i = 0; i < length; ++i) {
541 const Attachment &attachment = mAttachments[i];
543 JS::Rooted<JSObject*> attachmentObj(
544 aCx, JS_NewObject(aCx, nullptr, JS::NullPtr(), JS::NullPtr()));
545 NS_ENSURE_TRUE(attachmentObj, NS_ERROR_OUT_OF_MEMORY);
547 JS::Rooted<JSString*> tmpJsStr(aCx);
549 // Get |attachment.mId|.
550 tmpJsStr = JS_NewUCStringCopyN(aCx,
551 attachment.id.get(),
552 attachment.id.Length());
553 NS_ENSURE_TRUE(tmpJsStr, NS_ERROR_OUT_OF_MEMORY);
555 if (!JS_DefineProperty(aCx, attachmentObj, "id", tmpJsStr, JSPROP_ENUMERATE)) {
556 return NS_ERROR_FAILURE;
557 }
559 // Get |attachment.mLocation|.
560 tmpJsStr = JS_NewUCStringCopyN(aCx,
561 attachment.location.get(),
562 attachment.location.Length());
563 NS_ENSURE_TRUE(tmpJsStr, NS_ERROR_OUT_OF_MEMORY);
565 if (!JS_DefineProperty(aCx, attachmentObj, "location", tmpJsStr, JSPROP_ENUMERATE)) {
566 return NS_ERROR_FAILURE;
567 }
569 // Get |attachment.mContent|.
570 JS::Rooted<JS::Value> tmpJsVal(aCx);
571 nsresult rv = nsContentUtils::WrapNative(aCx,
572 attachment.content,
573 &NS_GET_IID(nsIDOMBlob),
574 &tmpJsVal);
575 NS_ENSURE_SUCCESS(rv, rv);
577 if (!JS_DefineProperty(aCx, attachmentObj, "content", tmpJsVal, JSPROP_ENUMERATE)) {
578 return NS_ERROR_FAILURE;
579 }
581 if (!JS_SetElement(aCx, attachments, i, attachmentObj)) {
582 return NS_ERROR_FAILURE;
583 }
584 }
586 aAttachments.setObject(*attachments);
587 return NS_OK;
588 }
590 NS_IMETHODIMP
591 MmsMessage::GetExpiryDate(DOMTimeStamp* aExpiryDate)
592 {
593 *aExpiryDate = mExpiryDate;
594 return NS_OK;
595 }
597 NS_IMETHODIMP
598 MmsMessage::GetReadReportRequested(bool* aReadReportRequested)
599 {
600 *aReadReportRequested = mReadReportRequested;
601 return NS_OK;
602 }
605 } // namespace dom
606 } // namespace mozilla