зеркало из https://github.com/mozilla/pjs.git
Bug #251418 --> Expose progress notification events through nsIXMLHttpRequest. Allow consumers of nsIXMLHttpRequest to
set a progress event listener. Listen for the http channel's nsIProgressEventSink notification and fire our new progress event to the consumer. r/sr=jst
This commit is contained in:
Родитель
243b6a94e8
Коммит
ee33323708
|
@ -315,6 +315,20 @@ interface nsIJSXMLHttpRequest : nsISupports {
|
|||
*/
|
||||
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.
|
||||
* Call open() before setting new event listeners.
|
||||
*
|
||||
* Mozilla only.
|
||||
*/
|
||||
attribute nsIDOMEventListener onprogress;
|
||||
|
||||
/**
|
||||
* Meant to be a script-only mechanism for setting a callback function.
|
||||
* The attribute is expected to be JavaScript function object. When the
|
||||
|
|
|
@ -285,6 +285,7 @@ NS_INTERFACE_MAP_BEGIN(nsXMLHttpRequest)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIHttpEventSink)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(XMLHttpRequest)
|
||||
|
@ -429,6 +430,28 @@ nsXMLHttpRequest::SetOnerror(nsIDOMEventListener * aOnerror)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsIDOMEventListener onprogress; */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetOnprogress(nsIDOMEventListener * *aOnprogress)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnprogress);
|
||||
|
||||
*aOnprogress = mOnProgressListener;
|
||||
NS_IF_ADDREF(*aOnprogress);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::SetOnprogress(nsIDOMEventListener * aOnprogress)
|
||||
{
|
||||
mOnProgressListener = aOnprogress;
|
||||
|
||||
mScriptContext = GetCurrentContext();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIChannel channel; */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetChannel(nsIChannel **aChannel)
|
||||
|
@ -806,6 +829,8 @@ nsXMLHttpRequest::ClearEventListeners()
|
|||
mOnLoadListener = nsnull;
|
||||
mOnErrorListener = nsnull;
|
||||
mOnReadystatechangeListener = nsnull;
|
||||
mOnProgressListener = nsnull;
|
||||
|
||||
}
|
||||
|
||||
already_AddRefed<nsIHttpChannel>
|
||||
|
@ -891,9 +916,11 @@ nsXMLHttpRequest::OpenRequest(const nsACString& method,
|
|||
GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
|
||||
// nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active,
|
||||
// which in turn keeps STOP button 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
|
||||
rv = NS_NewChannel(getter_AddRefs(mChannel), uri, nsnull, loadGroup,
|
||||
nsnull, nsIRequest::LOAD_BACKGROUND);
|
||||
nsnull, mOnProgressListener ? nsIRequest::LOAD_NORMAL : nsIRequest::LOAD_BACKGROUND);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
//mChannel->SetAuthTriedWithPrehost(authp);
|
||||
|
@ -1778,6 +1805,38 @@ nsXMLHttpRequest::OnRedirect(nsIHttpChannel *aHttpChannel,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// nsIProgressEventSink methods:
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::OnProgress(nsIRequest *aRequest, nsISupports *aContext, PRUint32 aProgress, PRUint32 aProgressMax)
|
||||
{
|
||||
if (mOnProgressListener)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
nsEvent evt(NS_EVENT_NULL ); // what name do we make up here?
|
||||
nsresult rv = CreateEvent(&evt, getter_AddRefs(event));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXMLHttpProgressEvent * progressEvent = new nsXMLHttpProgressEvent(event, aProgress, aProgressMax);
|
||||
if (!progressEvent)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
event = do_QueryInterface(progressEvent);
|
||||
NotifyEventListeners(mOnProgressListener, nsnull, event);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::OnStatus(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatus, const PRUnichar *aStatusArg)
|
||||
{
|
||||
// nothing to do here...
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// nsIInterfaceRequestor methods:
|
||||
//
|
||||
|
@ -1807,7 +1866,6 @@ nsXMLHttpRequest::GetInterface(const nsIID & aIID, void **aResult)
|
|||
return QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXMLHttpRequest::nsHeaderVisitor, nsIHttpHeaderVisitor)
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpRequest::
|
||||
|
@ -1819,3 +1877,93 @@ nsHeaderVisitor::VisitHeader(const nsACString &header, const nsACString &value)
|
|||
mHeaders.Append('\n');
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// DOM event class to handle progress notifications
|
||||
nsXMLHttpProgressEvent::nsXMLHttpProgressEvent(nsIDOMEvent * aInner, PRUint32 aCurrentProgress, PRUint32 aMaxProgress)
|
||||
{
|
||||
mInner = aInner;
|
||||
mCurProgress = aCurrentProgress;
|
||||
mMaxProgress = aMaxProgress;
|
||||
}
|
||||
|
||||
nsXMLHttpProgressEvent::~nsXMLHttpProgressEvent()
|
||||
{}
|
||||
|
||||
// QueryInterface implementation for nsXMLHttpRequest
|
||||
NS_INTERFACE_MAP_BEGIN(nsXMLHttpProgressEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMLSProgressEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMLSProgressEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEvent)
|
||||
NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(XMLHttpProgressEvent)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_ADDREF(nsXMLHttpProgressEvent)
|
||||
NS_IMPL_RELEASE(nsXMLHttpProgressEvent)
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::GetInput(nsIDOMLSInput * *aInput)
|
||||
{
|
||||
*aInput = nsnull;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::GetPosition(PRUint32 *aPosition)
|
||||
{
|
||||
*aPosition = mCurProgress;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::GetTotalSize(PRUint32 *aTotalSize)
|
||||
{
|
||||
*aTotalSize = mMaxProgress;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::GetType(nsAString & aType)
|
||||
{
|
||||
return mInner->GetType(aType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::GetTarget(nsIDOMEventTarget * *aTarget)
|
||||
{
|
||||
return mInner->GetTarget(aTarget);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::GetCurrentTarget(nsIDOMEventTarget * *aCurrentTarget)
|
||||
{
|
||||
return mInner->GetCurrentTarget(aCurrentTarget);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::GetEventPhase(PRUint16 *aEventPhase)
|
||||
{
|
||||
return mInner->GetEventPhase(aEventPhase);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::GetBubbles(PRBool *aBubbles)
|
||||
{
|
||||
return mInner->GetBubbles(aBubbles);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::GetCancelable(PRBool *aCancelable)
|
||||
{
|
||||
return mInner->GetCancelable(aCancelable);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::GetTimeStamp(DOMTimeStamp *aTimeStamp)
|
||||
{
|
||||
return mInner->GetTimeStamp(aTimeStamp);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::StopPropagation()
|
||||
{
|
||||
return mInner->StopPropagation();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::PreventDefault()
|
||||
{
|
||||
return mInner->PreventDefault();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpProgressEvent::InitEvent(const nsAString & eventTypeArg, PRBool canBubbleArg, PRBool cancelableArg)
|
||||
{
|
||||
return mInner->InitEvent(eventTypeArg, canBubbleArg, cancelableArg);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,10 @@
|
|||
#include "nsIHttpEventSink.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIHttpHeaderVisitor.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
|
||||
#include "nsIDOMLSProgressEvent.h"
|
||||
|
||||
class nsILoadGroup;
|
||||
|
||||
class nsXMLHttpRequest : public nsIXMLHttpRequest,
|
||||
|
@ -66,6 +70,7 @@ class nsXMLHttpRequest : public nsIXMLHttpRequest,
|
|||
public nsIStreamListener,
|
||||
public nsIHttpEventSink,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIProgressEventSink,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
|
@ -102,6 +107,9 @@ public:
|
|||
// nsIHttpEventSink
|
||||
NS_DECL_NSIHTTPEVENTSINK
|
||||
|
||||
// nsIProgressEventSink
|
||||
NS_DECL_NSIPROGRESSEVENTSINK
|
||||
|
||||
// nsIInterfaceRequestor
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
protected:
|
||||
|
@ -139,6 +147,7 @@ protected:
|
|||
|
||||
nsCOMPtr<nsIDOMEventListener> mOnLoadListener;
|
||||
nsCOMPtr<nsIDOMEventListener> mOnErrorListener;
|
||||
nsCOMPtr<nsIDOMEventListener> mOnProgressListener;
|
||||
|
||||
nsCOMPtr<nsIOnReadyStateChangeHandler> mOnReadystatechangeListener;
|
||||
|
||||
|
@ -164,4 +173,23 @@ protected:
|
|||
PRUint32 mState;
|
||||
};
|
||||
|
||||
|
||||
// helper class to expose a progress DOM Event
|
||||
|
||||
class nsXMLHttpProgressEvent : public nsIDOMLSProgressEvent
|
||||
{
|
||||
public:
|
||||
nsXMLHttpProgressEvent(nsIDOMEvent * aInner, PRUint32 aCurrentProgress, PRUint32 aMaxProgress);
|
||||
virtual ~nsXMLHttpProgressEvent();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMLSPROGRESSEVENT
|
||||
NS_DECL_NSIDOMEVENT
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIDOMEvent> mInner;
|
||||
PRUint32 mCurProgress;
|
||||
PRUint32 mMaxProgress;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче