|
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 "mozilla/dom/ContentChild.h" |
|
7 #include "SmsIPCService.h" |
|
8 #include "nsXULAppAPI.h" |
|
9 #include "mozilla/dom/mobilemessage/SmsChild.h" |
|
10 #include "SmsMessage.h" |
|
11 #include "SmsFilter.h" |
|
12 #include "SmsSegmentInfo.h" |
|
13 #include "nsJSUtils.h" |
|
14 #include "nsCxPusher.h" |
|
15 #include "mozilla/dom/MobileMessageManagerBinding.h" |
|
16 #include "mozilla/dom/MozMmsMessageBinding.h" |
|
17 #include "mozilla/dom/BindingUtils.h" |
|
18 #include "mozilla/Preferences.h" |
|
19 #include "nsString.h" |
|
20 |
|
21 using namespace mozilla::dom; |
|
22 using namespace mozilla::dom::mobilemessage; |
|
23 |
|
24 namespace { |
|
25 |
|
26 const char* kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces"; |
|
27 #define kPrefMmsDefaultServiceId "dom.mms.defaultServiceId" |
|
28 #define kPrefSmsDefaultServiceId "dom.sms.defaultServiceId" |
|
29 const char* kObservedPrefs[] = { |
|
30 kPrefMmsDefaultServiceId, |
|
31 kPrefSmsDefaultServiceId, |
|
32 nullptr |
|
33 }; |
|
34 |
|
35 // TODO: Bug 767082 - WebSMS: sSmsChild leaks at shutdown |
|
36 PSmsChild* gSmsChild; |
|
37 |
|
38 PSmsChild* |
|
39 GetSmsChild() |
|
40 { |
|
41 MOZ_ASSERT(NS_IsMainThread()); |
|
42 |
|
43 if (!gSmsChild) { |
|
44 gSmsChild = ContentChild::GetSingleton()->SendPSmsConstructor(); |
|
45 |
|
46 NS_WARN_IF_FALSE(gSmsChild, |
|
47 "Calling methods on SmsIPCService during shutdown!"); |
|
48 } |
|
49 |
|
50 return gSmsChild; |
|
51 } |
|
52 |
|
53 nsresult |
|
54 SendRequest(const IPCSmsRequest& aRequest, |
|
55 nsIMobileMessageCallback* aRequestReply) |
|
56 { |
|
57 PSmsChild* smsChild = GetSmsChild(); |
|
58 NS_ENSURE_TRUE(smsChild, NS_ERROR_FAILURE); |
|
59 |
|
60 SmsRequestChild* actor = new SmsRequestChild(aRequestReply); |
|
61 smsChild->SendPSmsRequestConstructor(actor, aRequest); |
|
62 |
|
63 return NS_OK; |
|
64 } |
|
65 |
|
66 nsresult |
|
67 SendCursorRequest(const IPCMobileMessageCursor& aRequest, |
|
68 nsIMobileMessageCursorCallback* aRequestReply, |
|
69 nsICursorContinueCallback** aResult) |
|
70 { |
|
71 PSmsChild* smsChild = GetSmsChild(); |
|
72 NS_ENSURE_TRUE(smsChild, NS_ERROR_FAILURE); |
|
73 |
|
74 nsRefPtr<MobileMessageCursorChild> actor = |
|
75 new MobileMessageCursorChild(aRequestReply); |
|
76 |
|
77 // Add an extra ref for IPDL. Will be released in |
|
78 // SmsChild::DeallocPMobileMessageCursor(). |
|
79 actor->AddRef(); |
|
80 |
|
81 smsChild->SendPMobileMessageCursorConstructor(actor, aRequest); |
|
82 |
|
83 actor.forget(aResult); |
|
84 return NS_OK; |
|
85 } |
|
86 |
|
87 uint32_t |
|
88 getDefaultServiceId(const char* aPrefKey) |
|
89 { |
|
90 int32_t id = mozilla::Preferences::GetInt(aPrefKey, 0); |
|
91 int32_t numRil = mozilla::Preferences::GetInt(kPrefRilNumRadioInterfaces, 1); |
|
92 |
|
93 if (id >= numRil || id < 0) { |
|
94 id = 0; |
|
95 } |
|
96 |
|
97 return id; |
|
98 } |
|
99 |
|
100 } // anonymous namespace |
|
101 |
|
102 NS_IMPL_ISUPPORTS(SmsIPCService, |
|
103 nsISmsService, |
|
104 nsIMmsService, |
|
105 nsIMobileMessageDatabaseService, |
|
106 nsIObserver) |
|
107 |
|
108 SmsIPCService::SmsIPCService() |
|
109 { |
|
110 Preferences::AddStrongObservers(this, kObservedPrefs); |
|
111 mMmsDefaultServiceId = getDefaultServiceId(kPrefMmsDefaultServiceId); |
|
112 mSmsDefaultServiceId = getDefaultServiceId(kPrefSmsDefaultServiceId); |
|
113 } |
|
114 |
|
115 /* |
|
116 * Implementation of nsIObserver. |
|
117 */ |
|
118 |
|
119 NS_IMETHODIMP |
|
120 SmsIPCService::Observe(nsISupports* aSubject, |
|
121 const char* aTopic, |
|
122 const char16_t* aData) |
|
123 { |
|
124 if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { |
|
125 nsDependentString data(aData); |
|
126 if (data.EqualsLiteral(kPrefMmsDefaultServiceId)) { |
|
127 mMmsDefaultServiceId = getDefaultServiceId(kPrefMmsDefaultServiceId); |
|
128 } else if (data.EqualsLiteral(kPrefSmsDefaultServiceId)) { |
|
129 mSmsDefaultServiceId = getDefaultServiceId(kPrefSmsDefaultServiceId); |
|
130 } |
|
131 return NS_OK; |
|
132 } |
|
133 |
|
134 MOZ_ASSERT(false, "SmsIPCService got unexpected topic!"); |
|
135 return NS_ERROR_UNEXPECTED; |
|
136 } |
|
137 |
|
138 /* |
|
139 * Implementation of nsISmsService. |
|
140 */ |
|
141 |
|
142 NS_IMETHODIMP |
|
143 SmsIPCService::GetSmsDefaultServiceId(uint32_t* aServiceId) |
|
144 { |
|
145 *aServiceId = mSmsDefaultServiceId; |
|
146 return NS_OK; |
|
147 } |
|
148 |
|
149 NS_IMETHODIMP |
|
150 SmsIPCService::GetSegmentInfoForText(const nsAString& aText, |
|
151 nsIMobileMessageCallback* aRequest) |
|
152 { |
|
153 return SendRequest(GetSegmentInfoForTextRequest(nsString(aText)), |
|
154 aRequest); |
|
155 } |
|
156 |
|
157 NS_IMETHODIMP |
|
158 SmsIPCService::GetSmscAddress(uint32_t aServiceId, |
|
159 nsIMobileMessageCallback* aRequest) |
|
160 { |
|
161 return SendRequest(GetSmscAddressRequest(aServiceId), aRequest); |
|
162 } |
|
163 |
|
164 NS_IMETHODIMP |
|
165 SmsIPCService::Send(uint32_t aServiceId, |
|
166 const nsAString& aNumber, |
|
167 const nsAString& aMessage, |
|
168 bool aSilent, |
|
169 nsIMobileMessageCallback* aRequest) |
|
170 { |
|
171 return SendRequest(SendMessageRequest(SendSmsMessageRequest(aServiceId, |
|
172 nsString(aNumber), |
|
173 nsString(aMessage), |
|
174 aSilent)), |
|
175 aRequest); |
|
176 } |
|
177 |
|
178 NS_IMETHODIMP |
|
179 SmsIPCService::IsSilentNumber(const nsAString& aNumber, |
|
180 bool* aIsSilent) |
|
181 { |
|
182 NS_ERROR("We should not be here!"); |
|
183 return NS_ERROR_FAILURE; |
|
184 } |
|
185 |
|
186 NS_IMETHODIMP |
|
187 SmsIPCService::AddSilentNumber(const nsAString& aNumber) |
|
188 { |
|
189 PSmsChild* smsChild = GetSmsChild(); |
|
190 NS_ENSURE_TRUE(smsChild, NS_ERROR_FAILURE); |
|
191 |
|
192 smsChild->SendAddSilentNumber(nsString(aNumber)); |
|
193 return NS_OK; |
|
194 } |
|
195 |
|
196 NS_IMETHODIMP |
|
197 SmsIPCService::RemoveSilentNumber(const nsAString& aNumber) |
|
198 { |
|
199 PSmsChild* smsChild = GetSmsChild(); |
|
200 NS_ENSURE_TRUE(smsChild, NS_ERROR_FAILURE); |
|
201 |
|
202 smsChild->SendRemoveSilentNumber(nsString(aNumber)); |
|
203 return NS_OK; |
|
204 } |
|
205 |
|
206 /* |
|
207 * Implementation of nsIMobileMessageDatabaseService. |
|
208 */ |
|
209 NS_IMETHODIMP |
|
210 SmsIPCService::GetMessageMoz(int32_t aMessageId, |
|
211 nsIMobileMessageCallback* aRequest) |
|
212 { |
|
213 return SendRequest(GetMessageRequest(aMessageId), aRequest); |
|
214 } |
|
215 |
|
216 NS_IMETHODIMP |
|
217 SmsIPCService::DeleteMessage(int32_t *aMessageIds, uint32_t aSize, |
|
218 nsIMobileMessageCallback* aRequest) |
|
219 { |
|
220 DeleteMessageRequest data; |
|
221 data.messageIds().AppendElements(aMessageIds, aSize); |
|
222 return SendRequest(data, aRequest); |
|
223 } |
|
224 |
|
225 NS_IMETHODIMP |
|
226 SmsIPCService::CreateMessageCursor(nsIDOMMozSmsFilter* aFilter, |
|
227 bool aReverse, |
|
228 nsIMobileMessageCursorCallback* aCursorCallback, |
|
229 nsICursorContinueCallback** aResult) |
|
230 { |
|
231 const SmsFilterData& data = |
|
232 SmsFilterData(static_cast<SmsFilter*>(aFilter)->GetData()); |
|
233 |
|
234 return SendCursorRequest(CreateMessageCursorRequest(data, aReverse), |
|
235 aCursorCallback, aResult); |
|
236 } |
|
237 |
|
238 NS_IMETHODIMP |
|
239 SmsIPCService::MarkMessageRead(int32_t aMessageId, |
|
240 bool aValue, |
|
241 bool aSendReadReport, |
|
242 nsIMobileMessageCallback* aRequest) |
|
243 { |
|
244 return SendRequest(MarkMessageReadRequest(aMessageId, aValue, aSendReadReport), aRequest); |
|
245 } |
|
246 |
|
247 NS_IMETHODIMP |
|
248 SmsIPCService::CreateThreadCursor(nsIMobileMessageCursorCallback* aCursorCallback, |
|
249 nsICursorContinueCallback** aResult) |
|
250 { |
|
251 return SendCursorRequest(CreateThreadCursorRequest(), aCursorCallback, |
|
252 aResult); |
|
253 } |
|
254 |
|
255 bool |
|
256 GetSendMmsMessageRequestFromParams(uint32_t aServiceId, |
|
257 const JS::Value& aParam, |
|
258 SendMmsMessageRequest& request) { |
|
259 if (aParam.isUndefined() || aParam.isNull() || !aParam.isObject()) { |
|
260 return false; |
|
261 } |
|
262 |
|
263 mozilla::AutoJSContext cx; |
|
264 JS::Rooted<JS::Value> param(cx, aParam); |
|
265 RootedDictionary<MmsParameters> params(cx); |
|
266 if (!params.Init(cx, param)) { |
|
267 return false; |
|
268 } |
|
269 |
|
270 // SendMobileMessageRequest.receivers |
|
271 if (!params.mReceivers.WasPassed()) { |
|
272 return false; |
|
273 } |
|
274 request.receivers().AppendElements(params.mReceivers.Value()); |
|
275 |
|
276 // SendMobileMessageRequest.attachments |
|
277 mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton(); |
|
278 |
|
279 if (!params.mAttachments.WasPassed()) { |
|
280 return false; |
|
281 } |
|
282 |
|
283 for (uint32_t i = 0; i < params.mAttachments.Value().Length(); i++) { |
|
284 mozilla::dom::MmsAttachment& attachment = params.mAttachments.Value()[i]; |
|
285 MmsAttachmentData mmsAttachment; |
|
286 mmsAttachment.id().Assign(attachment.mId); |
|
287 mmsAttachment.location().Assign(attachment.mLocation); |
|
288 mmsAttachment.contentChild() = cc->GetOrCreateActorForBlob(attachment.mContent); |
|
289 if (!mmsAttachment.contentChild()) { |
|
290 return false; |
|
291 } |
|
292 request.attachments().AppendElement(mmsAttachment); |
|
293 } |
|
294 |
|
295 request.smil() = params.mSmil; |
|
296 request.subject() = params.mSubject; |
|
297 |
|
298 // Set service ID. |
|
299 request.serviceId() = aServiceId; |
|
300 |
|
301 return true; |
|
302 } |
|
303 |
|
304 /* |
|
305 * Implementation of nsIMmsService. |
|
306 */ |
|
307 |
|
308 NS_IMETHODIMP |
|
309 SmsIPCService::GetMmsDefaultServiceId(uint32_t* aServiceId) |
|
310 { |
|
311 *aServiceId = mMmsDefaultServiceId; |
|
312 return NS_OK; |
|
313 } |
|
314 |
|
315 NS_IMETHODIMP |
|
316 SmsIPCService::Send(uint32_t aServiceId, |
|
317 JS::Handle<JS::Value> aParameters, |
|
318 nsIMobileMessageCallback *aRequest) |
|
319 { |
|
320 SendMmsMessageRequest req; |
|
321 if (!GetSendMmsMessageRequestFromParams(aServiceId, aParameters, req)) { |
|
322 return NS_ERROR_INVALID_ARG; |
|
323 } |
|
324 return SendRequest(SendMessageRequest(req), aRequest); |
|
325 } |
|
326 |
|
327 NS_IMETHODIMP |
|
328 SmsIPCService::Retrieve(int32_t aId, nsIMobileMessageCallback *aRequest) |
|
329 { |
|
330 return SendRequest(RetrieveMessageRequest(aId), aRequest); |
|
331 } |
|
332 |
|
333 NS_IMETHODIMP |
|
334 SmsIPCService::SendReadReport(const nsAString & messageID, |
|
335 const nsAString & toAddress, |
|
336 const nsAString & iccId) |
|
337 { |
|
338 NS_ERROR("We should not be here!"); |
|
339 return NS_OK; |
|
340 } |