1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is Mozilla Foundation
18 : * Portions created by the Initial Developer are Copyright (C) 2011
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Mounir Lamouri <mounir.lamouri@mozilla.com> (Original Author)
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "SmsFilter.h"
39 : #include "SmsManager.h"
40 : #include "nsIDOMClassInfo.h"
41 : #include "nsISmsService.h"
42 : #include "nsIObserverService.h"
43 : #include "mozilla/Services.h"
44 : #include "Constants.h"
45 : #include "SmsEvent.h"
46 : #include "nsIDOMSmsMessage.h"
47 : #include "nsIDOMSmsRequest.h"
48 : #include "SmsRequestManager.h"
49 : #include "nsJSUtils.h"
50 : #include "nsContentUtils.h"
51 : #include "nsISmsDatabaseService.h"
52 : #include "nsIXPConnect.h"
53 :
54 : /**
55 : * We have to use macros here because our leak analysis tool things we are
56 : * leaking strings when we have |static const nsString|. Sad :(
57 : */
58 : #define RECEIVED_EVENT_NAME NS_LITERAL_STRING("received")
59 : #define SENT_EVENT_NAME NS_LITERAL_STRING("sent")
60 : #define DELIVERED_EVENT_NAME NS_LITERAL_STRING("delivered")
61 :
62 : DOMCI_DATA(MozSmsManager, mozilla::dom::sms::SmsManager)
63 :
64 : namespace mozilla {
65 : namespace dom {
66 : namespace sms {
67 :
68 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(SmsManager)
69 :
70 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SmsManager,
71 : nsDOMEventTargetHelper)
72 0 : NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(received)
73 0 : NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(sent)
74 0 : NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(delivered)
75 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
76 :
77 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SmsManager,
78 : nsDOMEventTargetHelper)
79 0 : NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(received)
80 0 : NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(sent)
81 0 : NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(delivered)
82 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
83 :
84 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SmsManager)
85 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMMozSmsManager)
86 0 : NS_INTERFACE_MAP_ENTRY(nsIObserver)
87 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozSmsManager)
88 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozSmsManager)
89 0 : NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
90 :
91 0 : NS_IMPL_ADDREF_INHERITED(SmsManager, nsDOMEventTargetHelper)
92 0 : NS_IMPL_RELEASE_INHERITED(SmsManager, nsDOMEventTargetHelper)
93 :
94 : void
95 0 : SmsManager::Init(nsPIDOMWindow *aWindow)
96 : {
97 0 : BindToOwner(aWindow);
98 :
99 0 : nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
100 : // GetObserverService() can return null is some situations like shutdown.
101 0 : if (!obs) {
102 : return;
103 : }
104 :
105 0 : obs->AddObserver(this, kSmsReceivedObserverTopic, false);
106 0 : obs->AddObserver(this, kSmsSentObserverTopic, false);
107 0 : obs->AddObserver(this, kSmsDeliveredObserverTopic, false);
108 : }
109 :
110 : void
111 0 : SmsManager::Shutdown()
112 : {
113 0 : nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
114 : // GetObserverService() can return null is some situations like shutdown.
115 0 : if (!obs) {
116 : return;
117 : }
118 :
119 0 : obs->RemoveObserver(this, kSmsReceivedObserverTopic);
120 0 : obs->RemoveObserver(this, kSmsSentObserverTopic);
121 0 : obs->RemoveObserver(this, kSmsDeliveredObserverTopic);
122 : }
123 :
124 : NS_IMETHODIMP
125 0 : SmsManager::GetNumberOfMessagesForText(const nsAString& aText, PRUint16* aResult)
126 : {
127 0 : nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
128 0 : NS_ENSURE_TRUE(smsService, NS_OK);
129 :
130 0 : smsService->GetNumberOfMessagesForText(aText, aResult);
131 :
132 0 : return NS_OK;
133 : }
134 :
135 : nsresult
136 0 : SmsManager::Send(JSContext* aCx, JSObject* aGlobal, JSString* aNumber,
137 : const nsAString& aMessage, jsval* aRequest)
138 : {
139 0 : nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
140 0 : if (!smsService) {
141 0 : NS_ERROR("No SMS Service!");
142 0 : return NS_ERROR_FAILURE;
143 : }
144 :
145 0 : nsCOMPtr<nsIDOMMozSmsRequest> request;
146 :
147 0 : nsCOMPtr<nsISmsRequestManager> requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);
148 :
149 : PRInt32 requestId;
150 0 : nsresult rv = requestManager->CreateRequest(this, getter_AddRefs(request),
151 0 : &requestId);
152 0 : if (NS_FAILED(rv)) {
153 0 : NS_ERROR("Failed to create the request!");
154 0 : return rv;
155 : }
156 :
157 0 : nsDependentJSString number;
158 0 : number.init(aCx, aNumber);
159 :
160 0 : smsService->Send(number, aMessage, requestId, 0);
161 :
162 0 : rv = nsContentUtils::WrapNative(aCx, aGlobal, request, aRequest);
163 0 : if (NS_FAILED(rv)) {
164 0 : NS_ERROR("Failed to create the js value!");
165 0 : return rv;
166 : }
167 :
168 0 : return NS_OK;
169 : }
170 :
171 : NS_IMETHODIMP
172 0 : SmsManager::Send(const jsval& aNumber, const nsAString& aMessage, jsval* aReturn)
173 : {
174 : nsresult rv;
175 0 : nsIScriptContext* sc = GetContextForEventHandlers(&rv);
176 0 : NS_ENSURE_STATE(sc);
177 0 : JSContext* cx = sc->GetNativeContext();
178 0 : NS_ASSERTION(cx, "Failed to get a context!");
179 :
180 0 : if (!aNumber.isString() &&
181 0 : !(aNumber.isObject() && JS_IsArrayObject(cx, &aNumber.toObject()))) {
182 0 : return NS_ERROR_INVALID_ARG;
183 : }
184 :
185 0 : JSObject* global = sc->GetNativeGlobal();
186 0 : NS_ASSERTION(global, "Failed to get global object!");
187 :
188 0 : JSAutoRequest ar(cx);
189 0 : JSAutoEnterCompartment ac;
190 0 : if (!ac.enter(cx, global)) {
191 0 : NS_ERROR("Failed to enter the js compartment!");
192 0 : return NS_ERROR_FAILURE;
193 : }
194 :
195 0 : if (aNumber.isString()) {
196 0 : return Send(cx, global, aNumber.toString(), aMessage, aReturn);
197 : }
198 :
199 : // Must be an array then.
200 0 : JSObject& numbers = aNumber.toObject();
201 :
202 : uint32_t size;
203 0 : JS_ALWAYS_TRUE(JS_GetArrayLength(cx, &numbers, &size));
204 :
205 0 : jsval* requests = new jsval[size];
206 :
207 0 : for (uint32_t i=0; i<size; ++i) {
208 : jsval number;
209 0 : if (!JS_GetElement(cx, &numbers, i, &number)) {
210 0 : return NS_ERROR_INVALID_ARG;
211 : }
212 :
213 0 : nsresult rv = Send(cx, global, number.toString(), aMessage, &requests[i]);
214 0 : NS_ENSURE_SUCCESS(rv, rv);
215 : }
216 :
217 0 : aReturn->setObjectOrNull(JS_NewArrayObject(cx, size, requests));
218 0 : NS_ENSURE_TRUE(aReturn->isObject(), NS_ERROR_FAILURE);
219 :
220 0 : return NS_OK;
221 : }
222 :
223 : NS_IMETHODIMP
224 0 : SmsManager::GetMessageMoz(PRInt32 aId, nsIDOMMozSmsRequest** aRequest)
225 : {
226 0 : nsCOMPtr<nsISmsRequestManager> requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);
227 :
228 : PRInt32 requestId;
229 0 : nsresult rv = requestManager->CreateRequest(this, aRequest, &requestId);
230 0 : if (NS_FAILED(rv)) {
231 0 : NS_ERROR("Failed to create the request!");
232 0 : return rv;
233 : }
234 :
235 : nsCOMPtr<nsISmsDatabaseService> smsDBService =
236 0 : do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
237 0 : NS_ENSURE_TRUE(smsDBService, NS_ERROR_FAILURE);
238 :
239 0 : smsDBService->GetMessageMoz(aId, requestId, 0);
240 :
241 0 : return NS_OK;
242 : }
243 :
244 : nsresult
245 0 : SmsManager::Delete(PRInt32 aId, nsIDOMMozSmsRequest** aRequest)
246 : {
247 0 : nsCOMPtr<nsISmsRequestManager> requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);
248 :
249 : PRInt32 requestId;
250 0 : nsresult rv = requestManager->CreateRequest(this, aRequest, &requestId);
251 0 : if (NS_FAILED(rv)) {
252 0 : NS_ERROR("Failed to create the request!");
253 0 : return rv;
254 : }
255 :
256 : nsCOMPtr<nsISmsDatabaseService> smsDBService =
257 0 : do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
258 0 : NS_ENSURE_TRUE(smsDBService, NS_ERROR_FAILURE);
259 :
260 0 : smsDBService->DeleteMessage(aId, requestId, 0);
261 :
262 0 : return NS_OK;
263 : }
264 :
265 : NS_IMETHODIMP
266 0 : SmsManager::Delete(const jsval& aParam, nsIDOMMozSmsRequest** aRequest)
267 : {
268 0 : if (aParam.isInt32()) {
269 0 : return Delete(aParam.toInt32(), aRequest);
270 : }
271 :
272 0 : if (!aParam.isObject()) {
273 0 : return NS_ERROR_INVALID_ARG;
274 : }
275 :
276 : nsresult rv;
277 0 : nsIScriptContext* sc = GetContextForEventHandlers(&rv);
278 0 : NS_ENSURE_STATE(sc);
279 : nsCOMPtr<nsIDOMMozSmsMessage> message =
280 0 : do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(
281 0 : sc->GetNativeContext(), &aParam.toObject()));
282 0 : NS_ENSURE_TRUE(message, NS_ERROR_INVALID_ARG);
283 :
284 : PRInt32 id;
285 0 : message->GetId(&id);
286 :
287 0 : return Delete(id, aRequest);
288 : }
289 :
290 : NS_IMETHODIMP
291 0 : SmsManager::GetMessages(nsIDOMMozSmsFilter* aFilter, bool aReverse,
292 : nsIDOMMozSmsRequest** aRequest)
293 : {
294 0 : nsCOMPtr<nsIDOMMozSmsFilter> filter = aFilter;
295 :
296 0 : if (!filter) {
297 0 : filter = new SmsFilter();
298 : }
299 :
300 0 : nsCOMPtr<nsISmsRequestManager> requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);
301 :
302 : PRInt32 requestId;
303 0 : nsresult rv = requestManager->CreateRequest(this, aRequest,
304 0 : &requestId);
305 0 : if (NS_FAILED(rv)) {
306 0 : NS_ERROR("Failed to create the request!");
307 0 : return rv;
308 : }
309 :
310 : nsCOMPtr<nsISmsDatabaseService> smsDBService =
311 0 : do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
312 0 : NS_ENSURE_TRUE(smsDBService, NS_ERROR_FAILURE);
313 :
314 0 : smsDBService->CreateMessageList(filter, aReverse, requestId, 0);
315 :
316 0 : return NS_OK;
317 : }
318 :
319 0 : NS_IMPL_EVENT_HANDLER(SmsManager, received)
320 0 : NS_IMPL_EVENT_HANDLER(SmsManager, sent)
321 0 : NS_IMPL_EVENT_HANDLER(SmsManager, delivered)
322 :
323 : nsresult
324 0 : SmsManager::DispatchTrustedSmsEventToSelf(const nsAString& aEventName, nsIDOMMozSmsMessage* aMessage)
325 : {
326 0 : nsRefPtr<nsDOMEvent> event = new SmsEvent(nsnull, nsnull);
327 0 : nsresult rv = static_cast<SmsEvent*>(event.get())->Init(aEventName, false,
328 0 : false, aMessage);
329 0 : NS_ENSURE_SUCCESS(rv, rv);
330 :
331 0 : rv = event->SetTrusted(true);
332 0 : NS_ENSURE_SUCCESS(rv, rv);
333 :
334 : bool dummy;
335 0 : rv = DispatchEvent(event, &dummy);
336 0 : NS_ENSURE_SUCCESS(rv, rv);
337 :
338 0 : return NS_OK;
339 : }
340 :
341 : NS_IMETHODIMP
342 0 : SmsManager::Observe(nsISupports* aSubject, const char* aTopic,
343 : const PRUnichar* aData)
344 : {
345 0 : if (!strcmp(aTopic, kSmsReceivedObserverTopic)) {
346 0 : nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
347 0 : if (!message) {
348 0 : NS_ERROR("Got a 'sms-received' topic without a valid message!");
349 0 : return NS_OK;
350 : }
351 :
352 0 : DispatchTrustedSmsEventToSelf(RECEIVED_EVENT_NAME, message);
353 0 : return NS_OK;
354 : }
355 :
356 0 : if (!strcmp(aTopic, kSmsSentObserverTopic)) {
357 0 : nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
358 0 : if (!message) {
359 0 : NS_ERROR("Got a 'sms-sent' topic without a valid message!");
360 0 : return NS_OK;
361 : }
362 :
363 0 : DispatchTrustedSmsEventToSelf(SENT_EVENT_NAME, message);
364 0 : return NS_OK;
365 : }
366 :
367 0 : if (!strcmp(aTopic, kSmsDeliveredObserverTopic)) {
368 0 : nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
369 0 : if (!message) {
370 0 : NS_ERROR("Got a 'sms-delivered' topic without a valid message!");
371 0 : return NS_OK;
372 : }
373 :
374 0 : DispatchTrustedSmsEventToSelf(DELIVERED_EVENT_NAME, message);
375 0 : return NS_OK;
376 : }
377 :
378 0 : return NS_OK;
379 : }
380 :
381 : } // namespace sms
382 : } // namespace dom
383 4392 : } // namespace mozilla
|