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 @@ -30,73 +30,58 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nsISupports.idl" +#include "nsIDOMEventTarget.idl" interface nsIChannel; interface nsIDOMDocument; interface nsIDOMEventListener; interface nsIPrincipal; interface nsIScriptContext; interface nsIVariant; interface nsPIDOMWindow; + +[scriptable, uuid(6ce0a193-b033-4c3d-b748-f851b09261f5)] +interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget { + // event handler attributes + attribute nsIDOMEventListener onabort; + attribute nsIDOMEventListener onerror; + attribute nsIDOMEventListener onload; + attribute nsIDOMEventListener onloadstart; + attribute nsIDOMEventListener onprogress; +}; + +[scriptable, uuid(09ff3682-7759-4441-a765-f70e1a1fabcf)] +interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget { + // for future use +}; /** * Mozilla's XMLHttpRequest is modelled after Microsoft's IXMLHttpRequest * object. The goal has been to make Mozilla's version match Microsoft's * version as closely as possible, but there are bound to be some differences. * * In general, Microsoft's documentation for IXMLHttpRequest can be used. * Mozilla's interface definitions provide some additional documentation. The * web page to look at is http://www.mozilla.org/xmlextras/ * * Mozilla's XMLHttpRequest object can be created in JavaScript like this: * new XMLHttpRequest() * compare to Internet Explorer: * new ActiveXObject("Msxml2.XMLHTTP") * - * From JavaScript, the methods and properties visible in the XMLHttpRequest - * object are a combination of nsIXMLHttpRequest and nsIJSXMLHttpRequest; - * there is no need to differentiate between those interfaces. - * - * From native code, the way to set up onload and onerror handlers is a bit - * different. Here is a comment from Johnny Stenback : - * - * The mozilla implementation of nsIXMLHttpRequest implements the interface - * nsIDOMEventTarget and that's how you're supported to add event listeners. - * Try something like this: - * - * nsCOMPtr target(do_QueryInterface(myxmlhttpreq)); - * - * target->AddEventListener(NS_LITERAL_STRING("load"), mylistener, - * PR_FALSE) - * - * where mylistener is your event listener object that implements the - * interface nsIDOMEventListener. - * - * The 'onload', 'onerror', and 'onreadystatechange' attributes moved to - * nsIJSXMLHttpRequest, but if you're coding in C++ you should avoid using - * those. - * - * Though actually, if you use addEventListener from C++ weird things will - * happen too, since the result will depend on what JS happens to be on the - * stack when you do it.... - * - * Conclusion: Do not use event listeners on XMLHttpRequest from C++, unless - * you're aware of all the security implications. And then think twice about - * it. */ -[scriptable, uuid(acda85ab-d06c-4176-b834-6d129ca97ca3)] -interface nsIXMLHttpRequest : nsISupports +[scriptable, uuid(aaf12811-45b3-4f10-aac1-41cffa9a6b46)] +interface nsIXMLHttpRequest : nsIXMLHttpRequestEventTarget { /** * The request uses a channel in order to perform the * request. This attribute represents the channel used * for the request. NULL if the channel has not yet been * created. * * In a multipart request case, this is the initial channel, not the @@ -318,93 +303,33 @@ interface nsIXMLHttpRequest : nsISupport * null. * @param scriptContext The script context to use for the request. May be * null. * @param ownerWindow The associated window for the request. May be null. */ [noscript] void init(in nsIPrincipal principal, in nsIScriptContext scriptContext, in nsPIDOMWindow ownerWindow); -}; - -[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. + * Upload process can be tracked by adding event listener to |upload|. */ - attribute nsIDOMEventListener onerror; + readonly attribute nsIXMLHttpRequestUpload upload; /** - * 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. + * Mozilla only */ attribute nsIDOMEventListener onuploadprogress; - /** - * Meant to be a script-only mechanism for setting a callback function. - * The attribute is expected to be JavaScript function object. When the - * readyState changes, the callback function will be called. - * 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 onreadystatechange listener. - */ attribute nsIDOMEventListener onreadystatechange; +}; + +// nsIJSXMLHttpRequest is here only for backward compatibility +[scriptable, uuid(260062e0-684e-4532-838b-2014b70d1238)] +interface nsIJSXMLHttpRequest : nsIXMLHttpRequest { }; %{ C++ #define NS_XMLHTTPREQUEST_CID \ { /* d164e770-4157-11d4-9a42-000064657374 */ \ 0xd164e770, 0x4157, 0x11d4, \ {0x9a, 0x42, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} } #define NS_XMLHTTPREQUEST_CONTRACTID \ 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 @@ -45,17 +45,16 @@ #include "nsIURI.h" #include "nsILoadGroup.h" #include "nsNetUtil.h" #include "nsThreadUtils.h" #include "nsIUploadChannel.h" #include "nsIDOMSerializer.h" #include "nsXPCOM.h" #include "nsISupportsPrimitives.h" -#include "nsIEventListenerManager.h" #include "nsGUIEvent.h" #include "nsIPrivateDOMEvent.h" #include "prprf.h" #include "nsIDOMEventListener.h" #include "nsIJSContextStack.h" #include "nsJSEnvironment.h" #include "nsIScriptSecurityManager.h" #include "nsWeakPtr.h" @@ -88,16 +87,18 @@ #include "nsIMultiPartChannel.h" #include "nsIScriptObjectPrincipal.h" #include "nsIStorageStream.h" #include "nsIPromptFactory.h" #include "nsIWindowWatcher.h" #define LOAD_STR "load" #define ERROR_STR "error" +#define ABORT_STR "abort" +#define LOADSTART_STR "loadstart" #define PROGRESS_STR "progress" #define UPLOADPROGRESS_STR "uploadprogress" #define READYSTATE_STR "readystatechange" // CIDs // State #define XML_HTTP_REQUEST_UNINITIALIZED (1 << 0) // 0 @@ -287,23 +288,324 @@ GetDocumentFromScriptContext(nsIScriptCo if (domdoc) { CallQueryInterface(domdoc, &doc); } } return doc; } ///////////////////////////////////////////// + +NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequestEventTarget) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXMLHttpRequestEventTarget) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadListener) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnAbortListener) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadStartListener) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnProgressListener) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListenerManager) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpRequestEventTarget) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadListener) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnAbortListener) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadStartListener) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnProgressListener) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLHttpRequestEventTarget) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXMLHttpRequestEventTarget) + NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget) + NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget) + NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXMLHttpRequestEventTarget, + nsIXMLHttpRequestEventTarget) +NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXMLHttpRequestEventTarget, + nsIXMLHttpRequestEventTarget) + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::AddEventListener(const nsAString& aType, + nsIDOMEventListener* aListener, + PRBool aUseCapture) +{ + nsCOMPtr context; + GetContextForEventHandlers(getter_AddRefs(context)); + nsCOMPtr doc = GetDocumentFromScriptContext(context); + PRBool wantsUntrusted = doc && !nsContentUtils::IsChromeDoc(doc); + return AddEventListener(aType, aListener, aUseCapture, wantsUntrusted); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::RemoveEventListener(const nsAString& aType, + nsIDOMEventListener* aListener, + PRBool aUseCapture) +{ + nsCOMPtr elm; + GetListenerManager(PR_FALSE, getter_AddRefs(elm)); + if (elm) { + PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE; + elm->RemoveEventListenerByType(aListener, aType, flags, nsnull); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::AddEventListener(const nsAString& aType, + nsIDOMEventListener *aListener, + PRBool aUseCapture, + PRBool aWantsUntrusted) +{ + nsCOMPtr elm; + GetListenerManager(PR_TRUE, getter_AddRefs(elm)); + NS_ENSURE_STATE(elm); + PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE; + if (aWantsUntrusted) { + flags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED; + } + return elm->AddEventListenerByType(aListener, aType, flags, nsnull); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::GetScriptTypeID(PRUint32 *aLang) +{ + *aLang = mLang; + return NS_OK; +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::SetScriptTypeID(PRUint32 aLang) +{ + mLang = aLang; + return NS_OK; +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::DispatchEvent(nsIDOMEvent* aEvent, PRBool* aRetVal) +{ + nsEventStatus status = nsEventStatus_eIgnore; + nsresult rv = + nsEventDispatcher::DispatchDOMEvent(static_cast(this), + nsnull, aEvent, nsnull, &status); + + *aRetVal = (status != nsEventStatus_eConsumeNoDefault); + return rv; +} + +nsresult +nsXMLHttpRequestEventTarget::RemoveAddEventListener(const nsAString& aType, + nsRefPtr& aCurrent, + nsIDOMEventListener* aNew) +{ + if (aCurrent) { + RemoveEventListener(aType, aCurrent, PR_FALSE); + aCurrent = nsnull; + } + if (aNew) { + aCurrent = new nsDOMEventListenerWrapper(aNew); + NS_ENSURE_TRUE(aCurrent, NS_ERROR_OUT_OF_MEMORY); + AddEventListener(aType, aCurrent, PR_FALSE); + } + return NS_OK; +} + +nsresult +nsXMLHttpRequestEventTarget::GetInnerEventListener(nsRefPtr& aWrapper, + nsIDOMEventListener** aListener) +{ + NS_ENSURE_ARG_POINTER(aListener); + if (aWrapper) { + NS_ADDREF(*aListener = aWrapper->GetInner()); + } else { + *aListener = nsnull; + } + return NS_OK; +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::GetOnload(nsIDOMEventListener** aOnLoad) +{ + return GetInnerEventListener(mOnLoadListener, aOnLoad); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::SetOnload(nsIDOMEventListener* aOnLoad) +{ + NS_NAMED_LITERAL_STRING(ls, LOAD_STR); + return RemoveAddEventListener(ls, mOnLoadListener, aOnLoad); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::GetOnerror(nsIDOMEventListener** aOnerror) +{ + return GetInnerEventListener(mOnErrorListener, aOnerror); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::SetOnerror(nsIDOMEventListener* aOnerror) +{ + NS_NAMED_LITERAL_STRING(es, ERROR_STR); + return RemoveAddEventListener(es, mOnErrorListener, aOnerror); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::GetOnabort(nsIDOMEventListener** aOnabort) +{ + return GetInnerEventListener(mOnAbortListener, aOnabort); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::SetOnabort(nsIDOMEventListener* aOnabort) +{ + NS_NAMED_LITERAL_STRING(as, ABORT_STR); + return RemoveAddEventListener(as, mOnAbortListener, aOnabort); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::GetOnloadstart(nsIDOMEventListener** aOnloadstart) +{ + return GetInnerEventListener(mOnLoadStartListener, aOnloadstart); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::SetOnloadstart(nsIDOMEventListener* aOnloadstart) +{ + NS_NAMED_LITERAL_STRING(lss, LOADSTART_STR); + return RemoveAddEventListener(lss, mOnLoadStartListener, aOnloadstart); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::GetOnprogress(nsIDOMEventListener** aOnprogress) +{ + return GetInnerEventListener(mOnProgressListener, aOnprogress); +} + +NS_IMETHODIMP +nsXMLHttpRequestEventTarget::SetOnprogress(nsIDOMEventListener* aOnprogress) +{ + NS_NAMED_LITERAL_STRING(ps, PROGRESS_STR); + return RemoveAddEventListener(ps, mOnProgressListener, aOnprogress); +} + +nsresult +nsXMLHttpRequestEventTarget::PreHandleEvent(nsEventChainPreVisitor& aVisitor) +{ + aVisitor.mCanHandle = PR_TRUE; + aVisitor.mParentTarget = nsnull; + return NS_OK; +} + +nsresult +nsXMLHttpRequestEventTarget::PostHandleEvent(nsEventChainPostVisitor& aVisitor) +{ + return NS_OK; +} + +nsresult +nsXMLHttpRequestEventTarget::DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, + nsPresContext* aPresContext, + nsEventStatus* aEventStatus) +{ + return + nsEventDispatcher::DispatchDOMEvent(static_cast(this), + aEvent, aDOMEvent, aPresContext, + aEventStatus); +} + +nsresult +nsXMLHttpRequestEventTarget::GetListenerManager(PRBool aCreateIfNotFound, + nsIEventListenerManager** aResult) +{ + if (!mListenerManager) { + if (!aCreateIfNotFound) { + *aResult = nsnull; + return NS_OK; + } + nsresult rv = NS_NewEventListenerManager(getter_AddRefs(mListenerManager)); + NS_ENSURE_SUCCESS(rv, rv); + mListenerManager->SetListenerTarget(static_cast(this)); + } + + NS_ADDREF(*aResult = mListenerManager); + return NS_OK; +} + +nsresult +nsXMLHttpRequestEventTarget::AddEventListenerByIID(nsIDOMEventListener *aListener, + const nsIID& aIID) +{ + nsCOMPtr elm; + GetListenerManager(PR_TRUE, getter_AddRefs(elm)); + if (elm) { + elm->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE); + } + return NS_OK; +} + +nsresult +nsXMLHttpRequestEventTarget::RemoveEventListenerByIID(nsIDOMEventListener *aListener, + const nsIID& aIID) +{ + nsCOMPtr elm; + GetListenerManager(PR_FALSE, getter_AddRefs(elm)); + if (elm) { + return elm->RemoveEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE); + } + return NS_OK; +} + +nsresult +nsXMLHttpRequestEventTarget::GetSystemEventGroup(nsIDOMEventGroup** aGroup) +{ + nsCOMPtr elm; + nsresult rv = GetListenerManager(PR_TRUE, getter_AddRefs(elm)); + if (elm) { + return elm->GetSystemEventGroupLM(aGroup); + } + return rv; +} + +///////////////////////////////////////////// +NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequestUpload) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequestUpload, nsXMLHttpRequestEventTarget) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOwner) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequestUpload, nsXMLHttpRequestEventTarget) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOwner) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLHttpRequestUpload) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXMLHttpRequestUpload) + NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestUpload) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XMLHttpRequestUpload) +NS_INTERFACE_MAP_END_INHERITING(nsXMLHttpRequestEventTarget) + +NS_IMPL_ADDREF_INHERITED(nsXMLHttpRequestUpload, nsXMLHttpRequestEventTarget) +NS_IMPL_RELEASE_INHERITED(nsXMLHttpRequestUpload, nsXMLHttpRequestEventTarget) + +nsresult +nsXMLHttpRequestUpload::GetContextForEventHandlers(nsIScriptContext** aContext) +{ + return mOwner->GetContextForEventHandlers(aContext); +} + +///////////////////////////////////////////// // // ///////////////////////////////////////////// nsXMLHttpRequest::nsXMLHttpRequest() - : mLang(nsIProgrammingLanguage::JAVASCRIPT), - mState(XML_HTTP_REQUEST_UNINITIALIZED) + : mState(XML_HTTP_REQUEST_UNINITIALIZED) { nsLayoutStatics::AddRef(); } nsXMLHttpRequest::~nsXMLHttpRequest() { if (mListenerManager) { mListenerManager->Disconnect(); @@ -410,244 +712,96 @@ nsXMLHttpRequest::Initialize(nsISupports NS_ENSURE_STATE(sgo); mScriptContext = sgo->GetContext(); NS_ENSURE_STATE(mScriptContext); return NS_OK; } NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXMLHttpRequest) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest, + nsXMLHttpRequestEventTarget) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReadRequest) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptContext) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadListener) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnProgressListener) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnUploadProgressListener) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnReadystatechangeListener) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListenerManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mXMLParserStreamListener) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannelEventSink) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressEventSink) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOwner) + + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnUploadProgressListener) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnReadystatechangeListener) + + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mUpload, + nsIXMLHttpRequestUpload) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpRequest) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest, + nsXMLHttpRequestEventTarget) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReadRequest) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mScriptContext) - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadListener) - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener) - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnProgressListener) - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnUploadProgressListener) - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnReadystatechangeListener) - NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXMLParserStreamListener) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannelEventSink) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressEventSink) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOwner) + + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnUploadProgressListener) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnReadystatechangeListener) + + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mUpload) NS_IMPL_CYCLE_COLLECTION_UNLINK_END // QueryInterface implementation for nsXMLHttpRequest -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLHttpRequest) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLHttpRequest) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXMLHttpRequest) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIXMLHttpRequestEventTarget, nsIXMLHttpRequest) NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequest) NS_INTERFACE_MAP_ENTRY(nsIJSXMLHttpRequest) NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener) - NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget) NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) - NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget) - NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget) NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) NS_INTERFACE_MAP_ENTRY(nsIStreamListener) NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink) NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer) NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XMLHttpRequest) -NS_INTERFACE_MAP_END +NS_INTERFACE_MAP_END_INHERITING(nsXMLHttpRequestEventTarget) - -NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXMLHttpRequest, nsIXMLHttpRequest) -NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXMLHttpRequest, nsIXMLHttpRequest) - - -/* void addEventListener (in string type, in nsIDOMEventListener - listener); */ -NS_IMETHODIMP -nsXMLHttpRequest::AddEventListener(const nsAString& aType, - nsIDOMEventListener* aListener, - PRBool aUseCapture) -{ - nsCOMPtr doc = GetDocumentFromScriptContext(mScriptContext); - PRBool wantsUntrusted = doc && !nsContentUtils::IsChromeDoc(doc); - return AddEventListener(aType, aListener, aUseCapture, wantsUntrusted); -} - -/* void removeEventListener (in string type, in nsIDOMEventListener - listener); */ -NS_IMETHODIMP -nsXMLHttpRequest::RemoveEventListener(const nsAString& aType, - nsIDOMEventListener* aListener, - PRBool aUseCapture) -{ - nsCOMPtr elm; - GetListenerManager(PR_FALSE, getter_AddRefs(elm)); - if (elm) { - PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE; - elm->RemoveEventListenerByType(aListener, aType, flags, nsnull); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsXMLHttpRequest::AddEventListener(const nsAString& aType, - nsIDOMEventListener *aListener, - PRBool aUseCapture, - PRBool aWantsUntrusted) -{ - nsCOMPtr elm; - GetListenerManager(PR_TRUE, getter_AddRefs(elm)); - NS_ENSURE_STATE(elm); - PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE; - if (aWantsUntrusted) { - flags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED; - } - return elm->AddEventListenerByType(aListener, aType, flags, nsnull); -} - -NS_IMETHODIMP -nsXMLHttpRequest::GetScriptTypeID(PRUint32 *aLang) -{ - *aLang = mLang; - return NS_OK; -} - -NS_IMETHODIMP -nsXMLHttpRequest::SetScriptTypeID(PRUint32 aLang) -{ - mLang = aLang; - return NS_OK; -} - -/* boolean dispatchEvent (in nsIDOMEvent evt); */ -NS_IMETHODIMP -nsXMLHttpRequest::DispatchEvent(nsIDOMEvent* aEvent, PRBool* aRetVal) -{ - nsEventStatus status = nsEventStatus_eIgnore; - nsresult rv = - nsEventDispatcher::DispatchDOMEvent(static_cast(this), - nsnull, aEvent, nsnull, &status); - - *aRetVal = (status != nsEventStatus_eConsumeNoDefault); - return rv; -} - -nsresult -nsXMLHttpRequest::RemoveAddEventListener(const nsAString& aType, - nsRefPtr& aCurrent, - nsIDOMEventListener* aNew) -{ - if (aCurrent) { - RemoveEventListener(aType, aCurrent, PR_FALSE); - aCurrent = nsnull; - } - if (aNew) { - aCurrent = new nsDOMEventListenerWrapper(aNew); - NS_ENSURE_TRUE(aCurrent, NS_ERROR_OUT_OF_MEMORY); - AddEventListener(aType, aCurrent, PR_FALSE); - } - return NS_OK; -} - -nsresult -nsXMLHttpRequest::GetInnerEventListener(nsRefPtr& aWrapper, - nsIDOMEventListener** aListener) -{ - NS_ENSURE_ARG_POINTER(aListener); - if (aWrapper) { - NS_ADDREF(*aListener = aWrapper->GetInner()); - } else { - *aListener = nsnull; - } - return NS_OK; -} +NS_IMPL_ADDREF_INHERITED(nsXMLHttpRequest, nsXMLHttpRequestEventTarget) +NS_IMPL_RELEASE_INHERITED(nsXMLHttpRequest, nsXMLHttpRequestEventTarget) /* attribute nsIDOMEventListener onreadystatechange; */ NS_IMETHODIMP nsXMLHttpRequest::GetOnreadystatechange(nsIDOMEventListener * *aOnreadystatechange) { return GetInnerEventListener(mOnReadystatechangeListener, aOnreadystatechange); } NS_IMETHODIMP nsXMLHttpRequest::SetOnreadystatechange(nsIDOMEventListener * aOnreadystatechange) { NS_NAMED_LITERAL_STRING(rs, READYSTATE_STR); return RemoveAddEventListener(rs, mOnReadystatechangeListener, aOnreadystatechange); -} - - -/* attribute nsIDOMEventListener onload; */ -NS_IMETHODIMP -nsXMLHttpRequest::GetOnload(nsIDOMEventListener * *aOnLoad) -{ - return GetInnerEventListener(mOnLoadListener, aOnLoad); -} - -NS_IMETHODIMP -nsXMLHttpRequest::SetOnload(nsIDOMEventListener * aOnLoad) -{ - NS_NAMED_LITERAL_STRING(ls, LOAD_STR); - return RemoveAddEventListener(ls, mOnLoadListener, aOnLoad); -} - -/* attribute nsIDOMEventListener onerror; */ -NS_IMETHODIMP -nsXMLHttpRequest::GetOnerror(nsIDOMEventListener * *aOnerror) -{ - return GetInnerEventListener(mOnErrorListener, aOnerror); -} - -NS_IMETHODIMP -nsXMLHttpRequest::SetOnerror(nsIDOMEventListener * aOnerror) -{ - NS_NAMED_LITERAL_STRING(es, ERROR_STR); - return RemoveAddEventListener(es, mOnErrorListener, aOnerror); -} - -/* attribute nsIDOMEventListener onprogress; */ -NS_IMETHODIMP -nsXMLHttpRequest::GetOnprogress(nsIDOMEventListener * *aOnprogress) -{ - return GetInnerEventListener(mOnProgressListener, aOnprogress); -} - -NS_IMETHODIMP -nsXMLHttpRequest::SetOnprogress(nsIDOMEventListener * aOnprogress) -{ - NS_NAMED_LITERAL_STRING(ps, PROGRESS_STR); - return RemoveAddEventListener(ps, mOnProgressListener, aOnprogress); } /* attribute nsIDOMEventListener onuploadprogress; */ NS_IMETHODIMP nsXMLHttpRequest::GetOnuploadprogress(nsIDOMEventListener * *aOnuploadprogress) { return GetInnerEventListener(mOnUploadProgressListener, aOnuploadprogress); } @@ -992,20 +1146,16 @@ nsXMLHttpRequest::CreateEvent(const nsAS if (!privevent) { NS_IF_RELEASE(*aDOMEvent); return NS_ERROR_FAILURE; } if (!aType.IsEmpty()) { (*aDOMEvent)->InitEvent(aType, PR_FALSE, PR_FALSE); } - - privevent->SetTarget(this); - privevent->SetCurrentTarget(this); - privevent->SetOriginalTarget(this); // We assume anyone who managed to call CreateEvent is trusted privevent->SetTrusted(PR_TRUE); return NS_OK; } already_AddRefed @@ -1148,19 +1298,19 @@ nsXMLHttpRequest::OpenRequest(const nsAC nsCOMPtr loadGroup; GetLoadGroup(getter_AddRefs(loadGroup)); // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, which // in turn keeps STOP button from becoming active. If the consumer passed in // a progress event handler we must load with nsIRequest::LOAD_NORMAL or // necko won't generate any progress notifications nsLoadFlags loadFlags; - if (mListenerManager && - (mListenerManager->HasListenersFor(NS_LITERAL_STRING(PROGRESS_STR)) || - mListenerManager->HasListenersFor(NS_LITERAL_STRING(UPLOADPROGRESS_STR)))) { + if (HasListenersFor(NS_LITERAL_STRING(PROGRESS_STR)) || + HasListenersFor(NS_LITERAL_STRING(UPLOADPROGRESS_STR)) || + (mUpload && mUpload->HasListenersFor(NS_LITERAL_STRING(PROGRESS_STR)))) { loadFlags = nsIRequest::LOAD_NORMAL; } else { loadFlags = nsIRequest::LOAD_BACKGROUND; } rv = NS_NewChannel(getter_AddRefs(mChannel), uri, nsnull, loadGroup, nsnull, loadFlags); if (NS_FAILED(rv)) return rv; @@ -2188,19 +2338,19 @@ nsXMLHttpRequest::OnChannelRedirect(nsIC // NS_IMETHODIMP nsXMLHttpRequest::OnProgress(nsIRequest *aRequest, nsISupports *aContext, PRUint64 aProgress, PRUint64 aProgressMax) { // We're uploading if our state is XML_HTTP_REQUEST_OPENED or // XML_HTTP_REQUEST_SENT nsCOMPtr event; - nsresult rv = CreateEvent(((XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT) & mState) - ? NS_LITERAL_STRING(UPLOADPROGRESS_STR) - : NS_LITERAL_STRING(PROGRESS_STR), + PRBool upload = !!((XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT) & mState); + nsresult rv = CreateEvent(upload ? NS_LITERAL_STRING(UPLOADPROGRESS_STR) + : NS_LITERAL_STRING(PROGRESS_STR), getter_AddRefs(event)); NS_ENSURE_SUCCESS(rv, rv); nsRefPtr progressEvent = new nsXMLHttpProgressEvent(event, aProgress, aProgressMax); if (!progressEvent) return NS_ERROR_OUT_OF_MEMORY; @@ -2288,97 +2438,31 @@ nsXMLHttpRequest::GetInterface(const nsI reinterpret_cast(aResult)); } return QueryInterface(aIID, aResult); } nsresult -nsXMLHttpRequest::PreHandleEvent(nsEventChainPreVisitor& aVisitor) +nsXMLHttpRequest::GetContextForEventHandlers(nsIScriptContext** aContext) { - aVisitor.mCanHandle = PR_TRUE; - aVisitor.mParentTarget = nsnull; + NS_IF_ADDREF(*aContext = mScriptContext); return NS_OK; } -nsresult -nsXMLHttpRequest::PostHandleEvent(nsEventChainPostVisitor& aVisitor) +NS_IMETHODIMP +nsXMLHttpRequest::GetUpload(nsIXMLHttpRequestUpload** aUpload) { - return NS_OK; -} - -nsresult -nsXMLHttpRequest::DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, - nsPresContext* aPresContext, - nsEventStatus* aEventStatus) -{ - return - nsEventDispatcher::DispatchDOMEvent(static_cast(this), - aEvent, aDOMEvent, aPresContext, - aEventStatus); -} - -nsresult -nsXMLHttpRequest::GetListenerManager(PRBool aCreateIfNotFound, - nsIEventListenerManager** aResult) -{ - if (!mListenerManager) { - if (!aCreateIfNotFound) { - *aResult = nsnull; - return NS_OK; - } - nsresult rv = NS_NewEventListenerManager(getter_AddRefs(mListenerManager)); - NS_ENSURE_SUCCESS(rv, rv); - mListenerManager->SetListenerTarget(static_cast(this)); + *aUpload = nsnull; + if (!mUpload) { + mUpload = new nsXMLHttpRequestUpload(this); + NS_ENSURE_TRUE(mUpload, NS_ERROR_OUT_OF_MEMORY); } - - NS_ADDREF(*aResult = mListenerManager); - return NS_OK; -} - -nsresult -nsXMLHttpRequest::AddEventListenerByIID(nsIDOMEventListener *aListener, - const nsIID& aIID) -{ - nsCOMPtr elm; - GetListenerManager(PR_TRUE, getter_AddRefs(elm)); - if (elm) { - elm->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE); - } - return NS_OK; -} - -nsresult -nsXMLHttpRequest::RemoveEventListenerByIID(nsIDOMEventListener *aListener, - const nsIID& aIID) -{ - nsCOMPtr elm; - GetListenerManager(PR_FALSE, getter_AddRefs(elm)); - if (elm) { - return elm->RemoveEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE); - } - return NS_OK; -} - -nsresult -nsXMLHttpRequest::GetSystemEventGroup(nsIDOMEventGroup** aGroup) -{ - nsCOMPtr elm; - nsresult rv = GetListenerManager(PR_TRUE, getter_AddRefs(elm)); - if (elm) { - return elm->GetSystemEventGroupLM(aGroup); - } - return rv; -} - -nsresult -nsXMLHttpRequest::GetContextForEventHandlers(nsIScriptContext** aContext) -{ - NS_IF_ADDREF(*aContext = mScriptContext); + NS_ADDREF(*aUpload = mUpload.get()); return NS_OK; } NS_IMPL_ISUPPORTS1(nsXMLHttpRequest::nsHeaderVisitor, nsIHttpHeaderVisitor) NS_IMETHODIMP nsXMLHttpRequest:: nsHeaderVisitor::VisitHeader(const nsACString &header, const nsACString &value) { diff --git a/content/base/src/nsXMLHttpRequest.h b/content/base/src/nsXMLHttpRequest.h --- a/content/base/src/nsXMLHttpRequest.h +++ b/content/base/src/nsXMLHttpRequest.h @@ -63,16 +63,17 @@ #include "nsCycleCollectionParticipant.h" #include "nsIJSNativeInitializer.h" #include "nsPIDOMWindow.h" #include "nsIDOMLSProgressEvent.h" #include "nsClassHashtable.h" #include "nsHashKeys.h" #include "prclist.h" #include "prtime.h" +#include "nsIEventListenerManager.h" class nsILoadGroup; class nsDOMEventListenerWrapper : public nsIDOMEventListener { public: nsDOMEventListenerWrapper(nsIDOMEventListener* aListener) : mListener(aListener) {} @@ -82,46 +83,102 @@ public: NS_DECL_NSIDOMEVENTLISTENER nsIDOMEventListener* GetInner() { return mListener; } protected: nsCOMPtr mListener; }; -class nsXMLHttpRequest : public nsIXMLHttpRequest, +class nsXMLHttpRequestEventTarget : public nsIXMLHttpRequestEventTarget, + public nsPIDOMEventTarget, + public nsIDOMNSEventTarget +{ +public: + nsXMLHttpRequestEventTarget() : mLang(nsIProgrammingLanguage::JAVASCRIPT) {} + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequestEventTarget, + nsIXMLHttpRequestEventTarget) + NS_DECL_NSIDOMNSEVENTTARGET + NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET + NS_DECL_NSIDOMEVENTTARGET + // nsPIDOMEventTarget + virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); + virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); + virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, + nsPresContext* aPresContext, + nsEventStatus* aEventStatus); + virtual nsresult GetListenerManager(PRBool aCreateIfNotFound, + nsIEventListenerManager** aResult); + virtual nsresult AddEventListenerByIID(nsIDOMEventListener *aListener, + const nsIID& aIID); + virtual nsresult RemoveEventListenerByIID(nsIDOMEventListener *aListener, + const nsIID& aIID); + virtual nsresult GetSystemEventGroup(nsIDOMEventGroup** aGroup); + virtual nsresult GetContextForEventHandlers(nsIScriptContext** aContext) = 0; + + PRBool HasListenersFor(const nsAString& aType) + { + return mListenerManager && mListenerManager->HasListenersFor(aType); + } +protected: + nsresult RemoveAddEventListener(const nsAString& aType, + nsRefPtr& aCurrent, + nsIDOMEventListener* aNew); + + nsresult GetInnerEventListener(nsRefPtr& aWrapper, + nsIDOMEventListener** aListener); + nsRefPtr mOnLoadListener; + nsRefPtr mOnErrorListener; + nsRefPtr mOnAbortListener; + nsRefPtr mOnLoadStartListener; + nsRefPtr mOnProgressListener; + nsCOMPtr mListenerManager; + PRUint32 mLang; +}; + +class nsXMLHttpRequestUpload : public nsXMLHttpRequestEventTarget, + public nsIXMLHttpRequestUpload +{ +public: + nsXMLHttpRequestUpload(nsPIDOMEventTarget* aOwner) : mOwner(aOwner) {} + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLHttpRequestUpload, + nsXMLHttpRequestEventTarget) + NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXMLHttpRequestEventTarget::) + NS_FORWARD_NSIDOMEVENTTARGET(nsXMLHttpRequestEventTarget::) + NS_FORWARD_NSIDOMNSEVENTTARGET(nsXMLHttpRequestEventTarget::) + NS_DECL_NSIXMLHTTPREQUESTUPLOAD + virtual nsresult GetContextForEventHandlers(nsIScriptContext** aContext); +protected: + nsCOMPtr mOwner; +}; + +class nsXMLHttpRequest : public nsXMLHttpRequestEventTarget, public nsIJSXMLHttpRequest, public nsIDOMLoadListener, - public nsIDOMEventTarget, - public nsIDOMNSEventTarget, - public nsPIDOMEventTarget, public nsIStreamListener, public nsIChannelEventSink, public nsIProgressEventSink, public nsIInterfaceRequestor, public nsSupportsWeakReference, public nsIJSNativeInitializer { public: nsXMLHttpRequest(); virtual ~nsXMLHttpRequest(); - NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_ISUPPORTS_INHERITED // nsIXMLHttpRequest NS_DECL_NSIXMLHTTPREQUEST - // nsIJSXMLHttpRequest - NS_DECL_NSIJSXMLHTTPREQUEST - - // nsIDOMEventTarget - NS_DECL_NSIDOMEVENTTARGET - - // nsIDOMNSEventTarget - NS_DECL_NSIDOMNSEVENTTARGET + NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXMLHttpRequestEventTarget::) + NS_FORWARD_NSIDOMEVENTTARGET(nsXMLHttpRequestEventTarget::) + NS_FORWARD_NSIDOMNSEVENTTARGET(nsXMLHttpRequestEventTarget::) // nsIDOMEventListener NS_DECL_NSIDOMEVENTLISTENER // nsIDOMLoadListener NS_IMETHOD Load(nsIDOMEvent* aEvent); NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent); NS_IMETHOD Unload(nsIDOMEvent* aEvent); @@ -143,36 +200,24 @@ public: // nsIInterfaceRequestor NS_DECL_NSIINTERFACEREQUESTOR // nsIJSNativeInitializer NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj, PRUint32 argc, jsval* argv); // nsPIDOMEventTarget - virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); - virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); - virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent, - nsPresContext* aPresContext, - nsEventStatus* aEventStatus); - virtual nsresult GetListenerManager(PRBool aCreateIfNotFound, - nsIEventListenerManager** aResult); - virtual nsresult AddEventListenerByIID(nsIDOMEventListener *aListener, - const nsIID& aIID); - virtual nsresult RemoveEventListenerByIID(nsIDOMEventListener *aListener, - const nsIID& aIID); - virtual nsresult GetSystemEventGroup(nsIDOMEventGroup** aGroup); virtual nsresult GetContextForEventHandlers(nsIScriptContext** aContext); // This is called by the factory constructor. nsresult Init(); - NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequest, nsIXMLHttpRequest) - + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLHttpRequest, + nsXMLHttpRequestEventTarget) protected: nsresult DetectCharset(nsACString& aCharset); nsresult ConvertBodyToText(nsAString& aOutBuffer); static NS_METHOD StreamReaderFunc(nsIInputStream* in, void* closure, const char* fromRawSegment, PRUint32 toOffset, PRUint32 count, @@ -224,24 +269,19 @@ protected: // mReadRequest is different from mChannel for multipart requests nsCOMPtr mReadRequest; nsCOMPtr mDocument; // These may be null (native callers or xpcshell). nsCOMPtr mScriptContext; nsCOMPtr mOwner; // Inner window. - nsRefPtr mOnLoadListener; - nsRefPtr mOnErrorListener; - nsRefPtr mOnProgressListener; nsRefPtr mOnUploadProgressListener; nsRefPtr mOnReadystatechangeListener; - nsCOMPtr mListenerManager; - PRUint32 mLang; nsCOMPtr mXMLParserStreamListener; // used to implement getAllResponseHeaders() class nsHeaderVisitor : public nsIHttpHeaderVisitor { public: NS_DECL_ISUPPORTS NS_DECL_NSIHTTPHEADERVISITOR @@ -269,18 +309,20 @@ protected: nsCOMPtr mChannelEventSink; nsCOMPtr mProgressEventSink; PRUint32 mState; // List of potentially dangerous headers explicitly set using // SetRequestHeader. nsTArray mExtraRequestHeaders; + + nsRefPtr mUpload; }; - + // helper class to expose a progress DOM Event class nsXMLHttpProgressEvent : public nsIDOMLSProgressEvent { public: nsXMLHttpProgressEvent(nsIDOMEvent * aInner, PRUint64 aCurrentProgress, PRUint64 aMaxProgress); virtual ~nsXMLHttpProgressEvent(); diff --git a/content/events/public/nsIPrivateDOMEvent.h b/content/events/public/nsIPrivateDOMEvent.h --- a/content/events/public/nsIPrivateDOMEvent.h +++ b/content/events/public/nsIPrivateDOMEvent.h @@ -99,10 +99,11 @@ NS_NewDOMSVGZoomEvent(nsIDOMEvent** aRes NS_NewDOMSVGZoomEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsGUIEvent* aEvent); #endif // MOZ_SVG nsresult NS_NewDOMXULCommandEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsXULCommandEvent* aEvent); nsresult NS_NewDOMCommandEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsCommandEvent* aEvent); nsresult NS_NewDOMMessageEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsEvent* aEvent); - +nsresult +NS_NewDOMProgressEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsEvent* aEvent); #endif // nsIPrivateDOMEvent_h__ diff --git a/content/events/src/Makefile.in b/content/events/src/Makefile.in --- a/content/events/src/Makefile.in +++ b/content/events/src/Makefile.in @@ -77,16 +77,17 @@ CPPSRCS = \ nsDOMMouseEvent.cpp \ nsDOMMutationEvent.cpp \ nsDOMPopupBlockedEvent.cpp \ nsDOMBeforeUnloadEvent.cpp \ nsDOMPageTransitionEvent.cpp \ nsDOMXULCommandEvent.cpp \ nsDOMCommandEvent.cpp \ nsDOMMessageEvent.cpp \ + nsDOMProgressEvent.cpp \ nsPrivateTextRange.cpp \ nsDOMEventGroup.cpp \ nsXMLEventsManager.cpp \ nsXMLEventsElement.cpp \ nsPLDOMEvent.cpp \ nsEventDispatcher.cpp \ nsIMEStateManager.cpp \ nsQueryContentEventHandler.cpp \ diff --git a/content/events/src/nsEventDispatcher.cpp b/content/events/src/nsEventDispatcher.cpp --- a/content/events/src/nsEventDispatcher.cpp +++ b/content/events/src/nsEventDispatcher.cpp @@ -648,11 +648,13 @@ nsEventDispatcher::CreateEvent(nsPresCon if (aEventType.LowerCaseEqualsLiteral("commandevent") || aEventType.LowerCaseEqualsLiteral("commandevents")) return NS_NewDOMCommandEvent(aDOMEvent, aPresContext, nsnull); if (aEventType.LowerCaseEqualsLiteral("datacontainerevent") || aEventType.LowerCaseEqualsLiteral("datacontainerevents")) return NS_NewDOMDataContainerEvent(aDOMEvent, aPresContext, nsnull); if (aEventType.LowerCaseEqualsLiteral("messageevent")) return NS_NewDOMMessageEvent(aDOMEvent, aPresContext, nsnull); + if (aEventType.LowerCaseEqualsLiteral("progressevent")) + return NS_NewDOMProgressEvent(aDOMEvent, aPresContext, nsnull); return NS_ERROR_DOM_NOT_SUPPORTED_ERR; } diff --git a/dom/public/idl/events/Makefile.in b/dom/public/idl/events/Makefile.in --- a/dom/public/idl/events/Makefile.in +++ b/dom/public/idl/events/Makefile.in @@ -67,11 +67,12 @@ XPIDLSRCS = \ nsIDOMNSUIEvent.idl \ nsIDOMPopupBlockedEvent.idl \ nsIDOMBeforeUnloadEvent.idl \ nsIDOMNSEventTarget.idl \ nsIDOMSmartCardEvent.idl \ nsIDOMPageTransitionEvent.idl \ nsIDOMCommandEvent.idl \ nsIDOMMessageEvent.idl \ + nsIDOMProgressEvent.idl \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/public/nsDOMClassInfoID.h b/dom/public/nsDOMClassInfoID.h --- a/dom/public/nsDOMClassInfoID.h +++ b/dom/public/nsDOMClassInfoID.h @@ -419,16 +419,20 @@ enum nsDOMClassInfoID { // Data Events eDOMClassInfo_DataContainerEvent_id, // event used for cross-domain message-passing and for server-sent events in // HTML5 eDOMClassInfo_MessageEvent_id, + eDOMClassInfo_XMLHttpRequestUpload_id, + + eDOMClassInfo_ProgressEvent_id, + // This one better be the last one in this list eDOMClassInfoIDCount }; /** * nsIClassInfo helper macros */ diff --git a/dom/src/base/nsDOMClassInfo.cpp b/dom/src/base/nsDOMClassInfo.cpp --- a/dom/src/base/nsDOMClassInfo.cpp +++ b/dom/src/base/nsDOMClassInfo.cpp @@ -237,16 +237,17 @@ #include "nsIDOMCommandEvent.h" #include "nsIDOMPopupBlockedEvent.h" #include "nsIDOMBeforeUnloadEvent.h" #include "nsIDOMMutationEvent.h" #include "nsIDOMSmartCardEvent.h" #include "nsIDOMXULCommandEvent.h" #include "nsIDOMPageTransitionEvent.h" #include "nsIDOMMessageEvent.h" +#include "nsIDOMProgressEvent.h" #include "nsIDOMNSDocumentStyle.h" #include "nsIDOMDocumentRange.h" #include "nsIDOMDocumentTraversal.h" #include "nsIDOMDocumentXBL.h" #include "nsIDOMDocumentView.h" #include "nsIDOMElementCSSInlineStyle.h" #include "nsIDOMLinkStyle.h" #include "nsIDOMHTMLDocument.h" @@ -1182,16 +1183,18 @@ static nsDOMClassInfoData sClassInfoData DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(XMLSerializer, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(XMLHttpProgressEvent, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(XMLHttpRequest, nsEventTargetSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(XMLHttpRequestUpload, nsEventTargetSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(ClientRect, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(ClientRectList, nsClientRectListSH, ARRAY_SCRIPTABLE_FLAGS) // Define MOZ_SVG_FOREIGNOBJECT here so that when it gets switched on, // we preserve binary compatibility. New classes should be added @@ -1227,16 +1230,19 @@ static nsDOMClassInfoData sClassInfoData NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH, DEFAULT_SCRIPTABLE_FLAGS | WINDOW_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(DataContainerEvent, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(MessageEvent, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) + + NS_DEFINE_CLASSINFO_DATA(ProgressEvent, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) }; // Objects that shuld be constructable through |new Name();| struct nsContractIDMapData { PRInt32 mDOMClassInfoID; const char *mContractID; @@ -3282,19 +3288,24 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XMLSerializer, nsIDOMSerializer) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSerializer) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(XMLHttpRequest, nsIXMLHttpRequest) DOM_CLASSINFO_MAP_ENTRY(nsIXMLHttpRequest) - DOM_CLASSINFO_MAP_ENTRY(nsIJSXMLHttpRequest) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_ENTRY(nsIInterfaceRequestor) + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(XMLHttpRequestUpload, nsIXMLHttpRequestUpload) + DOM_CLASSINFO_MAP_ENTRY(nsIXMLHttpRequestEventTarget) + DOM_CLASSINFO_MAP_ENTRY(nsIXMLHttpRequestUpload) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XMLHttpProgressEvent, nsIDOMEvent) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent) DOM_CLASSINFO_MAP_ENTRY(nsIDOMLSProgressEvent) DOM_CLASSINFO_MAP_END #if defined(MOZ_SVG) && defined(MOZ_SVG_FOREIGNOBJECT) @@ -3366,16 +3377,21 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(DataContainerEvent, nsIDOMDataContainerEvent) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataContainerEvent) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(MessageEvent, nsIDOMMessageEvent) DOM_CLASSINFO_MAP_ENTRY(nsIDOMMessageEvent) + DOM_CLASSINFO_EVENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(ProgressEvent, nsIDOMProgressEvent) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMProgressEvent) DOM_CLASSINFO_EVENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END #ifdef NS_DEBUG { PRUint32 i = NS_ARRAY_LENGTH(sClassInfoData); if (i != eDOMClassInfoIDCount) { --- /dev/null 2008-06-05 11:51:05.389205708 +0300 +++ mozilla/dom/public/idl/events/nsIDOMProgressEvent.idl 2008-06-05 21:24:25.000000000 +0300 @@ -0,0 +1,61 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Olli Pettay (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIDOMEvent.idl" + +[scriptable, uuid(06072bf2-2644-4042-9103-edc06df66ccf)] +interface nsIDOMProgressEvent : nsIDOMEvent +{ + readonly attribute boolean lengthComputable; + readonly attribute unsigned long loaded; + readonly attribute unsigned long total; + void initProgressEvent(in DOMString typeArg, + in boolean canBubbleArg, + in boolean cancelableArg, + in boolean lengthComputableArg, + in unsigned long loadedArg, + in unsigned long totalArg); + void initProgressEventNS(in DOMString namespaceURI, + in DOMString typeArg, + in boolean canBubbleArg, + in boolean cancelableArg, + in boolean lengthComputableArg, + in unsigned long loadedArg, + in unsigned long totalArg); + +}; --- /dev/null 2008-06-05 11:51:05.389205708 +0300 +++ mozilla/content/events/src/nsDOMProgressEvent.h 2008-06-05 21:24:25.000000000 +0300 @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Olli Pettay (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsDOMProgressEvent_h__ +#define nsDOMProgressEvent_h__ + +#include "nsIDOMProgressEvent.h" +#include "nsDOMEvent.h" +#include "nsCycleCollectionParticipant.h" + +class nsDOMProgressEvent : public nsIDOMProgressEvent, + public nsDOMEvent +{ +public: + nsDOMProgressEvent(nsPresContext* aPresContext, nsEvent* aEvent) + : nsDOMEvent(aPresContext, aEvent) + { + } + + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_NSIDOMPROGRESSEVENT + + // Forward to base class + NS_FORWARD_TO_NSDOMEVENT + +private: + PRBool mLengthComputable; + PRUint32 mLoaded; + PRUint32 mTotal; +}; + +#endif // nsDOMProgressEvent_h__ --- /dev/null 2008-06-05 11:51:05.389205708 +0300 +++ mozilla/content/events/src/nsDOMProgressEvent.cpp 2008-06-05 21:24:25.000000000 +0300 @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Olli Pettay (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsDOMProgressEvent.h" +#include "nsContentUtils.h" + +NS_INTERFACE_MAP_BEGIN(nsDOMProgressEvent) + NS_INTERFACE_MAP_ENTRY(nsIDOMProgressEvent) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(ProgressEvent) +NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent) + +NS_IMPL_ADDREF_INHERITED(nsDOMProgressEvent, nsDOMEvent) +NS_IMPL_RELEASE_INHERITED(nsDOMProgressEvent, nsDOMEvent) + +NS_IMETHODIMP +nsDOMProgressEvent::InitProgressEvent(const nsAString& aType, + PRBool aCanBubble, + PRBool aCancelable, + PRBool aLengthComputable, + PRUint32 aLoaded, + PRUint32 aTotal) +{ + nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable); + NS_ENSURE_SUCCESS(rv, rv); + + mLengthComputable = aLengthComputable; + mLoaded = aLoaded; + mTotal = aTotal; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMProgressEvent::InitProgressEventNS(const nsAString& aNamespaceURI, + const nsAString& aType, + PRBool aCanBubble, + PRBool aCancelable, + PRBool aLengthComputable, + PRUint32 aLoaded, + PRUint32 aTotal) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDOMProgressEvent::GetLengthComputable(PRBool* aComputable) +{ + *aComputable = mLengthComputable; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMProgressEvent::GetLoaded(PRUint32* aLoaded) +{ + *aLoaded = mLoaded; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMProgressEvent::GetTotal(PRUint32* aTotal) +{ + *aTotal = mTotal; + return NS_OK; +} + +nsresult +NS_NewDOMProgressEvent(nsIDOMEvent** aInstancePtrResult, + nsPresContext* aPresContext, + nsEvent* aEvent) +{ + nsDOMProgressEvent* it = new nsDOMProgressEvent(aPresContext, aEvent); + if (nsnull == it) + return NS_ERROR_OUT_OF_MEMORY; + + return CallQueryInterface(it, aInstancePtrResult); +}