1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "DOMRequest.h"
10 #include "nsThreadUtils.h"
11 #include "DOMCursor.h"
12 #include "nsIDOMEvent.h"
14 using mozilla::dom::DOMError
;
15 using mozilla::dom::DOMRequest
;
16 using mozilla::dom::DOMRequestService
;
17 using mozilla::dom::DOMCursor
;
18 using mozilla::AutoSafeJSContext
;
20 DOMRequest::DOMRequest(nsPIDOMWindow
* aWindow
)
21 : DOMEventTargetHelper(aWindow
->IsInnerWindow() ?
22 aWindow
: aWindow
->GetCurrentInnerWindow())
28 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMRequest
)
30 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMRequest
,
32 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError
)
33 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
35 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMRequest
,
37 NS_IMPL_CYCLE_COLLECTION_UNLINK(mError
)
38 tmp
->mResult
= JSVAL_VOID
;
39 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
41 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DOMRequest
,
43 // Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
44 // DOMEventTargetHelper does it for us.
45 NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mResult
)
46 NS_IMPL_CYCLE_COLLECTION_TRACE_END
48 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMRequest
)
49 NS_INTERFACE_MAP_ENTRY(nsIDOMDOMRequest
)
50 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
52 NS_IMPL_ADDREF_INHERITED(DOMRequest
, DOMEventTargetHelper
)
53 NS_IMPL_RELEASE_INHERITED(DOMRequest
, DOMEventTargetHelper
)
55 /* virtual */ JSObject
*
56 DOMRequest::WrapObject(JSContext
* aCx
)
58 return DOMRequestBinding::Wrap(aCx
, this);
61 NS_IMPL_EVENT_HANDLER(DOMRequest
, success
)
62 NS_IMPL_EVENT_HANDLER(DOMRequest
, error
)
65 DOMRequest::GetReadyState(nsAString
& aReadyState
)
67 DOMRequestReadyState readyState
= ReadyState();
69 case DOMRequestReadyState::Pending
:
70 aReadyState
.AssignLiteral("pending");
72 case DOMRequestReadyState::Done
:
73 aReadyState
.AssignLiteral("done");
76 MOZ_CRASH("Unrecognized readyState.");
83 DOMRequest::GetResult(JS::MutableHandle
<JS::Value
> aResult
)
85 GetResult(nullptr, aResult
);
90 DOMRequest::GetError(nsISupports
** aError
)
92 NS_IF_ADDREF(*aError
= GetError());
97 DOMRequest::FireSuccess(JS::Handle
<JS::Value
> aResult
)
99 NS_ASSERTION(!mDone
, "mDone shouldn't have been set to true already!");
100 NS_ASSERTION(!mError
, "mError shouldn't have been set!");
101 NS_ASSERTION(mResult
== JSVAL_VOID
, "mResult shouldn't have been set!");
104 if (aResult
.isGCThing()) {
109 FireEvent(NS_LITERAL_STRING("success"), false, false);
113 DOMRequest::FireError(const nsAString
& aError
)
115 NS_ASSERTION(!mDone
, "mDone shouldn't have been set to true already!");
116 NS_ASSERTION(!mError
, "mError shouldn't have been set!");
117 NS_ASSERTION(mResult
== JSVAL_VOID
, "mResult shouldn't have been set!");
120 mError
= new DOMError(GetOwner(), aError
);
122 FireEvent(NS_LITERAL_STRING("error"), true, true);
126 DOMRequest::FireError(nsresult aError
)
128 NS_ASSERTION(!mDone
, "mDone shouldn't have been set to true already!");
129 NS_ASSERTION(!mError
, "mError shouldn't have been set!");
130 NS_ASSERTION(mResult
== JSVAL_VOID
, "mResult shouldn't have been set!");
133 mError
= new DOMError(GetOwner(), aError
);
135 FireEvent(NS_LITERAL_STRING("error"), true, true);
139 DOMRequest::FireDetailedError(DOMError
* aError
)
141 NS_ASSERTION(!mDone
, "mDone shouldn't have been set to true already!");
142 NS_ASSERTION(!mError
, "mError shouldn't have been set!");
143 NS_ASSERTION(mResult
== JSVAL_VOID
, "mResult shouldn't have been set!");
144 NS_ASSERTION(aError
, "No detailed error provided");
149 FireEvent(NS_LITERAL_STRING("error"), true, true);
153 DOMRequest::FireEvent(const nsAString
& aType
, bool aBubble
, bool aCancelable
)
155 if (NS_FAILED(CheckInnerWindowCorrectness())) {
159 nsCOMPtr
<nsIDOMEvent
> event
;
160 NS_NewDOMEvent(getter_AddRefs(event
), this, nullptr, nullptr);
161 nsresult rv
= event
->InitEvent(aType
, aBubble
, aCancelable
);
166 event
->SetTrusted(true);
169 DispatchEvent(event
, &dummy
);
173 DOMRequest::RootResultVal()
175 mozilla::HoldJSObjects(this);
178 NS_IMPL_ISUPPORTS(DOMRequestService
, nsIDOMRequestService
)
181 DOMRequestService::CreateRequest(nsIDOMWindow
* aWindow
,
182 nsIDOMDOMRequest
** aRequest
)
184 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(aWindow
));
185 NS_ENSURE_STATE(win
);
186 NS_ADDREF(*aRequest
= new DOMRequest(win
));
192 DOMRequestService::CreateCursor(nsIDOMWindow
* aWindow
,
193 nsICursorContinueCallback
* aCallback
,
194 nsIDOMDOMCursor
** aCursor
)
196 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(aWindow
));
197 NS_ENSURE_STATE(win
);
198 NS_ADDREF(*aCursor
= new DOMCursor(win
, aCallback
));
204 DOMRequestService::FireSuccess(nsIDOMDOMRequest
* aRequest
,
205 JS::Handle
<JS::Value
> aResult
)
207 NS_ENSURE_STATE(aRequest
);
208 static_cast<DOMRequest
*>(aRequest
)->FireSuccess(aResult
);
214 DOMRequestService::FireError(nsIDOMDOMRequest
* aRequest
,
215 const nsAString
& aError
)
217 NS_ENSURE_STATE(aRequest
);
218 static_cast<DOMRequest
*>(aRequest
)->FireError(aError
);
224 DOMRequestService::FireDetailedError(nsIDOMDOMRequest
* aRequest
,
227 NS_ENSURE_STATE(aRequest
);
228 nsCOMPtr
<DOMError
> err
= do_QueryInterface(aError
);
229 NS_ENSURE_STATE(err
);
230 static_cast<DOMRequest
*>(aRequest
)->FireDetailedError(err
);
235 class FireSuccessAsyncTask
: public nsRunnable
238 FireSuccessAsyncTask(JSContext
* aCx
,
239 DOMRequest
* aRequest
,
240 const JS::Value
& aResult
) :
242 mResult(aCx
, aResult
)
248 // Due to the fact that initialization can fail during shutdown (since we
249 // can't fetch a js context), set up an initiatization function to make sure
250 // we can return the failure appropriately
252 Dispatch(DOMRequest
* aRequest
,
253 const JS::Value
& aResult
)
255 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
256 AutoSafeJSContext cx
;
257 nsRefPtr
<FireSuccessAsyncTask
> asyncTask
= new FireSuccessAsyncTask(cx
, aRequest
, aResult
);
258 if (NS_FAILED(NS_DispatchToMainThread(asyncTask
))) {
259 NS_WARNING("Failed to dispatch to main thread!");
260 return NS_ERROR_FAILURE
;
268 mReq
->FireSuccess(JS::Handle
<JS::Value
>::fromMarkedLocation(mResult
.address()));
272 ~FireSuccessAsyncTask()
274 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
278 nsRefPtr
<DOMRequest
> mReq
;
279 JS::PersistentRooted
<JS::Value
> mResult
;
282 class FireErrorAsyncTask
: public nsRunnable
285 FireErrorAsyncTask(DOMRequest
* aRequest
,
286 const nsAString
& aError
) :
295 mReq
->FireError(mError
);
299 nsRefPtr
<DOMRequest
> mReq
;
304 DOMRequestService::FireSuccessAsync(nsIDOMDOMRequest
* aRequest
,
305 JS::Handle
<JS::Value
> aResult
)
307 NS_ENSURE_STATE(aRequest
);
308 return FireSuccessAsyncTask::Dispatch(static_cast<DOMRequest
*>(aRequest
), aResult
);
312 DOMRequestService::FireErrorAsync(nsIDOMDOMRequest
* aRequest
,
313 const nsAString
& aError
)
315 NS_ENSURE_STATE(aRequest
);
316 nsCOMPtr
<nsIRunnable
> asyncTask
=
317 new FireErrorAsyncTask(static_cast<DOMRequest
*>(aRequest
), aError
);
318 if (NS_FAILED(NS_DispatchToMainThread(asyncTask
))) {
319 NS_WARNING("Failed to dispatch to main thread!");
320 return NS_ERROR_FAILURE
;
326 DOMRequestService::FireDone(nsIDOMDOMCursor
* aCursor
) {
327 NS_ENSURE_STATE(aCursor
);
328 static_cast<DOMCursor
*>(aCursor
)->FireDone();