Closed
Bug 450452
Opened 16 years ago
Closed 16 years ago
Implement XHR ("minus X") for worker threads
Categories
(Core :: DOM: Events, defect)
Core
DOM: Events
Tracking
()
RESOLVED
FIXED
People
(Reporter: bent.mozilla, Assigned: bent.mozilla)
References
Details
Attachments
(6 files, 2 obsolete files)
108.10 KB,
patch
|
jst
:
review+
jst
:
superreview+
|
Details | Diff | Splinter Review |
45.10 KB,
patch
|
Details | Diff | Splinter Review | |
3.97 KB,
patch
|
jst
:
review+
jst
:
superreview+
|
Details | Diff | Splinter Review |
1.54 KB,
patch
|
Details | Diff | Splinter Review | |
110.64 KB,
patch
|
Details | Diff | Splinter Review | |
8.29 KB,
patch
|
Details | Diff | Splinter Review |
Implement XHR ("minus X") for worker threads.
Assignee | ||
Updated•16 years ago
|
Assignee: nobody → bent.mozilla
Status: ASSIGNED → NEW
Assignee | ||
Comment 1•16 years ago
|
||
Here we go!
Attachment #338759 -
Flags: superreview?(jst)
Attachment #338759 -
Flags: review?(jst)
Assignee | ||
Comment 2•16 years ago
|
||
Jonas, could you look over the changes I made to XHR?
Comment on attachment 338759 [details] [diff] [review]
Patch, v1
>diff --git a/content/base/public/nsIXMLHttpRequest.idl b/content/base/public/nsIXMLHttpRequest.idl
>--- a/content/base/public/nsIXMLHttpRequest.idl
>+++ b/content/base/public/nsIXMLHttpRequest.idl
>@@ -334,78 +334,11 @@ interface nsIXMLHttpRequest : nsISupport
> [noscript] void init(in nsIPrincipal principal,
> in nsIScriptContext scriptContext,
> in nsPIDOMWindow ownerWindow);
>-};
>
>-[scriptable, uuid(6e127bd2-b4c1-4a82-be0d-012bd24efb37)]
>-interface nsIXMLHttpRequestUploadGetter : nsISupports {
> /**
> * Upload process can be tracked by adding event listener to |upload|.
> */
> readonly attribute nsIXMLHttpRequestUpload upload;
>-};
>-
>-[scriptable, uuid(261676b4-d508-43bf-b099-74635a0ee2e9)]
>-interface nsIJSXMLHttpRequest : nsISupports {
>- /**
>- * Meant to be a script-only mechanism for setting a load event listener.
>- * The attribute is expected to be JavaScript function object. When
>- * the load event occurs, the function is invoked.
>- * This attribute should not be used from native code!!
>- *
>- * After the initial response, all event listeners will be cleared.
>- * // XXXbz what does that mean, exactly?
>- *
>- * Call open() before setting an onload listener.
>- *
>- * Mozilla only.
>- */
>- attribute nsIDOMEventListener onload;
>-
>- /**
>- * Meant to be a script-only mechanism for setting an error event listener.
>- * The attribute is expected to be JavaScript function object. When
>- * the error event occurs, the function is invoked.
>- * This attribute should not be used from native code!!
>- *
>- * After the initial response, all event listeners will be cleared.
>- * // XXXbz what does that mean, exactly?
>- *
>- * Call open() before setting an onerror listener.
>- *
>- * Mozilla only.
>- */
>- attribute nsIDOMEventListener onerror;
>-
>- /**
>- * Meant to be a script-only mechanism for setting a progress event listener.
>- * The attribute is expected to be JavaScript function object. When
>- * the error event occurs, the function is invoked.
>- * This attribute should not be used from native code!!
>- * This event listener may be called multiple times during the open request.
>- *
>- * After the initial response, all event listeners will be cleared.
>- * // XXXbz what does that mean, exactly?
>- *
>- * This event listener must be set BEFORE calling open().
>- *
>- * Mozilla only.
>- */
>- attribute nsIDOMEventListener onprogress;
>-
>- /**
>- * Meant to be a script-only mechanism for setting an upload progress event
>- * listener.
>- * This attribute should not be used from native code!!
>- * This event listener may be called multiple times during the upload..
>- *
>- * After the initial response, all event listeners will be cleared.
>- * // XXXbz what does that mean, exactly?
>- *
>- * This event listener must be set BEFORE calling open().
>- *
>- * Mozilla only.
>- */
>- attribute nsIDOMEventListener onuploadprogress;
>
> /**
> * Meant to be a script-only mechanism for setting a callback function.
>@@ -421,6 +354,27 @@ interface nsIJSXMLHttpRequest : nsISuppo
> attribute nsIDOMEventListener onreadystatechange;
> };
>
>+/**
>+ * DEPRECATED.
>+ */
>+[scriptable, uuid(261676b4-d508-43bf-b099-74635a0ee2e9)]
>+interface nsIJSXMLHttpRequest : nsISupports {
>+ /**
>+ * Meant to be a script-only mechanism for setting an upload progress event
>+ * listener.
>+ * This attribute should not be used from native code!!
>+ * This event listener may be called multiple times during the upload..
>+ *
>+ * After the initial response, all event listeners will be cleared.
>+ * // XXXbz what does that mean, exactly?
>+ *
>+ * This event listener must be set BEFORE calling open().
>+ *
>+ * Mozilla only.
>+ */
>+ attribute nsIDOMEventListener onuploadprogress;
>+};
>+
> %{ C++
> #define NS_XMLHTTPREQUEST_CID \
> { /* d164e770-4157-11d4-9a42-000064657374 */ \
>diff --git a/content/base/src/nsXMLHttpRequest.cpp b/content/base/src/nsXMLHttpRequest.cpp
>--- a/content/base/src/nsXMLHttpRequest.cpp
>+++ b/content/base/src/nsXMLHttpRequest.cpp
>@@ -611,8 +611,9 @@ nsXMLHttpRequestUpload::GetContextForEve
> /////////////////////////////////////////////
>
> nsXMLHttpRequest::nsXMLHttpRequest()
>- : mState(XML_HTTP_REQUEST_UNINITIALIZED), mUploadTransferred(0),
>- mUploadTotal(0), mUploadComplete(PR_TRUE), mErrorLoad(PR_FALSE)
>+ : mRequestObserver(nsnull), mState(XML_HTTP_REQUEST_UNINITIALIZED),
>+ mUploadTransferred(0), mUploadTotal(0), mUploadComplete(PR_TRUE),
>+ mErrorLoad(PR_FALSE), mFirstStartRequestSeen(PR_FALSE)
> {
> nsLayoutStatics::AddRef();
> }
>@@ -727,6 +728,12 @@ nsXMLHttpRequest::Initialize(nsISupports
> return NS_OK;
> }
>
>+void
>+nsXMLHttpRequest::SetRequestObserver(nsIRequestObserver* aObserver)
>+{
>+ mRequestObserver = aObserver;
>+}
>+
> NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest)
>
> NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
>@@ -776,7 +783,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
> NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLHttpRequest)
> NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequest)
> NS_INTERFACE_MAP_ENTRY(nsIJSXMLHttpRequest)
>- NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestUploadGetter)
> NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
> NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
> NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
>@@ -1565,6 +1571,11 @@ NS_IMETHODIMP
> NS_IMETHODIMP
> nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
> {
>+ if (!mFirstStartRequestSeen && mRequestObserver) {
>+ mFirstStartRequestSeen = PR_TRUE;
>+ mRequestObserver->OnStartRequest(request, ctxt);
>+ }
>+
> if (!IsSameOrBaseChannel(request, mChannel)) {
> return NS_OK;
> }
>@@ -1784,6 +1795,12 @@ nsXMLHttpRequest::OnStopRequest(nsIReque
> }
>
> mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
>+
>+ if (mRequestObserver && mState & XML_HTTP_REQUEST_GOT_FINAL_STOP) {
>+ NS_ASSERTION(mFirstStartRequestSeen, "Inconsistent state!");
>+ mFirstStartRequestSeen = PR_FALSE;
>+ mRequestObserver->OnStopRequest(request, ctxt, status);
>+ }
What will happen if we never end up with mState & XML_HTTP_REQUEST_GOT_FINAL_STOP? Will something terrible happen? As I recall it this could sometimes happen with malformed multipart requests.
Feel free to just file a bug on making this more robust such that we for sure always shut down things properly, we need to do that anyway for user friendlyness reasons.
(In general, make sure to test multipart requests inside the worker)
Comment 4•16 years ago
|
||
Comment on attachment 338759 [details] [diff] [review]
Patch, v1
- In nsGlobalWindow::FreeInnerObjects():
nsDOMThreadService* dts = nsDOMThreadService::get();
if (dts) {
+ nsIScriptContext *scx = GetContextInternal();
+
+ JSContext *cx = scx ? (JSContext *)scx->GetNativeContext() : nsnull;
+
+ JSAutoSuspendRequest asr(cx);
Add a comment explaining why this suspend request is needed.
- In nsDOMWorkerPool::nsDOMWorkerPool():
JSContext* cx = nsContentUtils::GetCurrentJSContext();
NS_ENSURE_TRUE(cx, NS_ERROR_UNEXPECTED);
- nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
- NS_ENSURE_STATE(scriptContext);
+ mScriptContext = GetScriptContextFromJSContext(cx);
+ NS_ENSURE_STATE(mScriptContext);
This should get the context out of the document rather than the context we're currently running on, in which case you might not even need to cache it here as you can get to it from the document at any point (well, until the document is torn down etc).
- In nsDOMWorkerThread::CancelXHRs():
+ nsAutoTArray<nsDOMWorkerXHR*, 20> xhrs;
+
+ // Must call Cancel outside the lock!
+ {
+ nsAutoLock lock(mLock);
+ xhrs.AppendElements(mXHRs);
+ }
+
+ PRUint32 xhrCount = xhrs.Length();
+ for (PRUint32 index = 0; index < xhrCount; index++) {
+ xhrs[index]->Cancel();
+ }
This races with NewXMLHttpRequest and the xhr contructor which adds itself to mXHRs.
class nsErrorReportingRunnable : public nsRunnable
New name maybe? This isn't actually reporting an error... Not sure what a better name would be tho...
And maybe the response runnable isn't even needed, as it could just set mResult and mDone once it has the result, as long as the waiting thread can't get stuck waiting for a message?
+class nsDOMWorkerXHREvent : public nsRunnable,
+ public nsIDOMEvent,
+ public nsIClassInfo
File a followup bug on exposing the other types of events and their data as well.
- In nsDOMWorkerXHREvent::GetTarget():
+ return CallQueryInterface(mXHRProxy->mWorkerXHR, aTarget);
Here, and all other places where script can call into a stored event, we need to not dereference mXHRProxy as it could've already been nulled out.
- In nsDOMWorkerXHRProxy::InitInternal():
+ // Call QI manually here to avoid keeping up with the cast madness of
+ // nsXMLHttpRequest.
+ nsCOMPtr<nsIXMLHttpRequest> xhr;
+ rv = xhrConcrete->QueryInterface(NS_GET_IID(nsIXMLHttpRequest),
+ getter_AddRefs(xhr));
+ NS_ENSURE_SUCCESS(rv, rv);
You should be able to simply cast to nsIXMLHttpRequest here and use the nsCOMPtr helpers, safely...
+ // We now own upload.
+ upload.swap(mUpload);
+
+ mXHR = xhr;
mXHR is weak, so maybe document above that the upload object owns the XHR object.
- In nsDOMWorkerXHRProxy::AddEventListener():
+ // Silently fail on juk events.
Typo, copied a couple of times :)
- In nsDOMWorkerXHRProxy::OnStartRequest():
+ NS_ASSERTION(!mOwnedByXHR, "Inconsistent state!");
+
+ FlipOwnership();
This could race with the flip call in Abort() on the worker, right?
Same thing in nsDOMWorkerXHRProxy::OnStopRequest().
r- based on that, but over all this looks really good, even if non-trivial :)
Attachment #338759 -
Flags: superreview?(jst)
Attachment #338759 -
Flags: superreview-
Attachment #338759 -
Flags: review?(jst)
Attachment #338759 -
Flags: review-
Assignee | ||
Comment 5•16 years ago
|
||
Comments addressed.
Attachment #338759 -
Attachment is obsolete: true
Attachment #339531 -
Flags: superreview?(jst)
Attachment #339531 -
Flags: review?(jst)
Assignee | ||
Comment 6•16 years ago
|
||
Here's the interdiff. It looks long but it's mainly because I sprinkled cancel checks all over the place to kill the XHR as soon as possible.
Comment 7•16 years ago
|
||
Comment on attachment 339531 [details] [diff] [review]
Patch, v2
So you're changing nsIXMLHttpRequest interface without updating its uuid.
Is that on purpose? I guess the vtable is still compatible. Though, because
there are new things on the interface, the caller can't know if those are available.
When adding support for .upload I explicitly decided to not to change nsIXMLHttpRequest,
because that is probably used in quite many extensions (also binary).
Updated•16 years ago
|
Attachment #339531 -
Flags: superreview?(jst)
Attachment #339531 -
Flags: superreview+
Attachment #339531 -
Flags: review?(jst)
Attachment #339531 -
Flags: review+
Comment 8•16 years ago
|
||
Comment on attachment 339531 [details] [diff] [review]
Patch, v2
nsDOMWorkerXHREventTarget::DispatchEvent():
+ nsRefPtr<nsDOMWorkerXHREventWrapper> wrapper =
+ new nsDOMWorkerXHREventWrapper(aEvent);
Do we need to worry about the case where the event already is an nsDOMWorkerXHREventWrapper? If not, script could theoretically create indefinitely long chains of these things and slow things down considerably, maybe?
r+sr=jst with that considered.
Assignee | ||
Comment 9•16 years ago
|
||
This applies on top of attachment 339531 [details] [diff] [review] and addresses the event re-wrap.
Attachment #339987 -
Flags: superreview?(jst)
Attachment #339987 -
Flags: review?(jst)
Updated•16 years ago
|
Attachment #339987 -
Flags: superreview?(jst)
Attachment #339987 -
Flags: superreview+
Attachment #339987 -
Flags: review?(jst)
Attachment #339987 -
Flags: review+
Assignee | ||
Comment 10•16 years ago
|
||
Assignee | ||
Comment 11•16 years ago
|
||
(In reply to comment #7)
> So you're changing nsIXMLHttpRequest interface without updating its uuid.
Oops, I'll bump that on checkin, it was not intentional. Discussed the modification of nsIXMLHttpRequest with jst and sicking and they both voted to change it rather than making a new interface.
Assignee | ||
Comment 12•16 years ago
|
||
Assignee | ||
Comment 13•16 years ago
|
||
Attachment #340260 -
Attachment is obsolete: true
Assignee | ||
Comment 14•16 years ago
|
||
Slight changes were necessary after bug 382871 landed.
Assignee | ||
Comment 15•16 years ago
|
||
Fixed.
Status: NEW → RESOLVED
Closed: 16 years ago
Resolution: --- → FIXED
You need to log in
before you can comment on or make changes to this bug.
Description
•