mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
Bug 96459, bug 96307 and Bugscape 8288. Implement readyState and onreadystatechange members to enable progress indicators for download. Make it possible to call send() again in onload without crashing. Send load event only after everything done (was sent too early if XML errors). Make some functions throw error if called at the wrong time (match IE). Make it possible to build SOAP again (patch from peterv, r=heikki). r=harishd, sr=vidur, a=asa.
This commit is contained in:
parent
28fa0cd179
commit
441896a2b3
@ -339,6 +339,13 @@ nsXMLContentSink::DidBuildModel(PRInt32 aQualityLevel)
|
||||
mDocument->EndLoad();
|
||||
}
|
||||
|
||||
// Ref. Bug 49115
|
||||
// Do this hack to make sure that the parser
|
||||
// doesn't get destroyed, accidently, before
|
||||
// the circularity, between sink & parser, is
|
||||
// actually borken.
|
||||
nsCOMPtr<nsIParser> kungFuDeathGrip(mParser);
|
||||
|
||||
// Drop our reference to the parser to get rid of a circular
|
||||
// reference.
|
||||
NS_IF_RELEASE(mParser);
|
||||
|
@ -23,6 +23,10 @@
|
||||
#include "nsHTTPSOAPTransport.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
|
||||
#define LOADSTR NS_LITERAL_STRING("load")
|
||||
#define ERRORSTR NS_LITERAL_STRING("error")
|
||||
|
||||
nsHTTPSOAPTransport::nsHTTPSOAPTransport()
|
||||
{
|
||||
@ -106,10 +110,13 @@ nsHTTPSOAPTransport::AsyncCall(const char *url,
|
||||
|
||||
mListener = listener;
|
||||
|
||||
mRequest->AddEventListener("load",
|
||||
NS_STATIC_CAST(nsIDOMEventListener*, this));
|
||||
mRequest->AddEventListener("error",
|
||||
NS_STATIC_CAST(nsIDOMEventListener*, this));
|
||||
nsCOMPtr<nsIDOMEventTarget> eventTarget(do_QueryInterface(mRequest, &rv));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
eventTarget->AddEventListener(LOADSTR,
|
||||
NS_STATIC_CAST(nsIDOMEventListener*, this), PR_FALSE);
|
||||
eventTarget->AddEventListener(ERRORSTR,
|
||||
NS_STATIC_CAST(nsIDOMEventListener*, this), PR_FALSE);
|
||||
|
||||
rv = mRequest->Send(messageDocument);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
@ -26,6 +26,42 @@ interface nsIDOMDocument;
|
||||
interface nsIDOMEventListener;
|
||||
interface nsIChannel;
|
||||
|
||||
/**
|
||||
* 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 <jst@netscape.com>:
|
||||
*
|
||||
* 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<nsIDOMEventTarget> target(do_QuertyInterface(myxmlhttpreq));
|
||||
*
|
||||
* target->AddEventListener(NS_LITERAL_STRING("load"), mylistener,
|
||||
* PR_FALSE)
|
||||
*
|
||||
* where mylistener is your event listener object that implements the
|
||||
* interface nsIDOMEventListener.
|
||||
*
|
||||
* The 'onload' and 'onerror' attributes moved to nsIJSXMLHttRequest,
|
||||
* but if you're coding in C++ you should avoid using those.
|
||||
*/
|
||||
[scriptable, uuid(b7215e70-4157-11d4-9a42-000064657374)]
|
||||
interface nsIXMLHttpRequest : nsISupports {
|
||||
/**
|
||||
@ -33,6 +69,8 @@ interface nsIXMLHttpRequest : nsISupports {
|
||||
* request. This attribute represents the channel used
|
||||
* for the request. NULL if the channel has not yet been
|
||||
* created.
|
||||
*
|
||||
* Mozilla only.
|
||||
*/
|
||||
readonly attribute nsIChannel channel;
|
||||
|
||||
@ -150,15 +188,37 @@ interface nsIXMLHttpRequest : nsISupports {
|
||||
void send(in nsISupports body);
|
||||
|
||||
/**
|
||||
* Sets a HTTP request header for HTTP requests.
|
||||
* Sets a HTTP request header for HTTP requests. You must call open
|
||||
* before setting the request headers.
|
||||
*
|
||||
* @param header The name of the header to set in the request.
|
||||
* @param value The body of the header.
|
||||
*/
|
||||
void setRequestHeader(in string header, in string value);
|
||||
|
||||
/**
|
||||
* The state of the request.
|
||||
*
|
||||
* Possible values:
|
||||
* 0 UNINITIALIZED open() has not been called yet.
|
||||
* 1 LOADING send() has not been called yet.
|
||||
* 2 LOADED send() has been called, headers and status are available.
|
||||
* 3 INTERACTIVE Downloading, responseText holds the partial data.
|
||||
* 4 COMPLETED Finished with all operations.
|
||||
*/
|
||||
readonly attribute long readyState;
|
||||
};
|
||||
|
||||
|
||||
[scriptable, function, uuid(6459B7CE-6B57-4934-A0AF-0133BA6F9085)]
|
||||
interface nsIOnReadystatechangeHandler : nsISupports {
|
||||
/**
|
||||
* Helper to implement the onreadystatechange callback member.
|
||||
* You should not need to use this.
|
||||
*/
|
||||
void handleEvent();
|
||||
};
|
||||
|
||||
[scriptable, uuid(9deabc90-28d5-41d3-a660-474f2254f4ba)]
|
||||
interface nsIJSXMLHttpRequest : nsISupports {
|
||||
/**
|
||||
@ -166,6 +226,8 @@ interface nsIJSXMLHttpRequest : nsISupports {
|
||||
* 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!!
|
||||
*
|
||||
* Mozilla only.
|
||||
*/
|
||||
attribute nsIDOMEventListener onload;
|
||||
|
||||
@ -174,8 +236,18 @@ interface nsIJSXMLHttpRequest : nsISupports {
|
||||
* 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!!
|
||||
*
|
||||
* Mozilla only.
|
||||
*/
|
||||
attribute nsIDOMEventListener onerror;
|
||||
|
||||
/**
|
||||
* 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!!
|
||||
*/
|
||||
attribute nsIOnReadystatechangeHandler onreadystatechange;
|
||||
};
|
||||
|
||||
%{ C++
|
||||
|
@ -213,7 +213,7 @@ nsLoadListenerProxy::Error(nsIDOMEvent* aEvent)
|
||||
nsXMLHttpRequest::nsXMLHttpRequest()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
mStatus = XML_HTTP_REQUEST_INITIALIZED;
|
||||
ChangeState(XML_HTTP_REQUEST_UNINITIALIZED,PR_FALSE);
|
||||
mAsync = PR_TRUE;
|
||||
}
|
||||
|
||||
@ -316,6 +316,28 @@ nsXMLHttpRequest::DispatchEvent(nsIDOMEvent *evt)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsIOnReadystatechangeHandler onreadystatechange; */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetOnreadystatechange(nsIOnReadystatechangeHandler * *aOnreadystatechange)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOnreadystatechange);
|
||||
|
||||
*aOnreadystatechange = mOnReadystatechangeListener;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::SetOnreadystatechange(nsIOnReadystatechangeHandler * aOnreadystatechange)
|
||||
{
|
||||
mOnReadystatechangeListener = aOnreadystatechange;
|
||||
|
||||
GetCurrentContext(getter_AddRefs(mScriptContext));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* attribute nsIDOMEventListener onload; */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetOnload(nsIDOMEventListener * *aOnLoad)
|
||||
@ -518,11 +540,14 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponseText(PRUnichar **aResponseText)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResponseText);
|
||||
*aResponseText = nsnull;
|
||||
if ((XML_HTTP_REQUEST_COMPLETED == mStatus)) {
|
||||
|
||||
if ((XML_HTTP_REQUEST_COMPLETED == mStatus) ||
|
||||
(XML_HTTP_REQUEST_INTERACTIVE == mStatus)) {
|
||||
// First check if we can represent the data as a string - if it contains
|
||||
// nulls we won't try.
|
||||
if (mResponseBody.FindChar('\0') >= 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = ConvertBodyToText(aResponseText);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
@ -657,7 +682,7 @@ nsXMLHttpRequest::OpenRequest(const char *method,
|
||||
rv = httpChannel->SetRequestMethod(method);
|
||||
}
|
||||
|
||||
mStatus = XML_HTTP_REQUEST_OPENED;
|
||||
ChangeState(XML_HTTP_REQUEST_OPENED);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -857,6 +882,8 @@ nsXMLHttpRequest::StreamReaderFunc(nsIInputStream* in,
|
||||
}
|
||||
}
|
||||
|
||||
xmlHttpRequest->ChangeState(XML_HTTP_REQUEST_INTERACTIVE);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*writeCount = count;
|
||||
} else {
|
||||
@ -889,6 +916,7 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
||||
{
|
||||
mReadRequest = request;
|
||||
mContext = ctxt;
|
||||
ChangeState(XML_HTTP_REQUEST_LOADED);
|
||||
return mXMLParserStreamListener->OnStartRequest(request,ctxt);
|
||||
}
|
||||
|
||||
@ -900,6 +928,82 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
|
||||
mXMLParserStreamListener = nsnull;
|
||||
mReadRequest = nsnull;
|
||||
mContext = nsnull;
|
||||
|
||||
RequestCompleted();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::RequestCompleted()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
NS_WARN_IF_FALSE(mDelayedEvent,"no delayed event");
|
||||
|
||||
// We might have been sent non-XML data. If that was the case,
|
||||
// we should null out the document member. The idea in this
|
||||
// check here is that if there is no document element it is not
|
||||
// an XML document. We might need a fancier check...
|
||||
if (mDocument) {
|
||||
nsCOMPtr<nsIDOMElement> root;
|
||||
mDocument->GetDocumentElement(getter_AddRefs(root));
|
||||
if (!root) {
|
||||
mDocument = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
ChangeState(XML_HTTP_REQUEST_COMPLETED);
|
||||
|
||||
#ifdef IMPLEMENT_SYNC_LOAD
|
||||
if (mChromeWindow) {
|
||||
mChromeWindow->ExitModalEventLoop(NS_OK);
|
||||
mChromeWindow = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIJSContextStack> stack;
|
||||
JSContext *cx = nsnull;
|
||||
|
||||
if (mScriptContext) {
|
||||
stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
|
||||
if (stack) {
|
||||
cx = (JSContext *)mScriptContext->GetNativeContext();
|
||||
|
||||
if (cx) {
|
||||
stack->Push(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mOnLoadListener && mDelayedEvent) {
|
||||
mOnLoadListener->HandleEvent(mDelayedEvent);
|
||||
}
|
||||
|
||||
if (mLoadEventListeners && mDelayedEvent) {
|
||||
PRUint32 index, count;
|
||||
|
||||
mLoadEventListeners->Count(&count);
|
||||
for (index = 0; index < count; index++) {
|
||||
nsCOMPtr<nsIDOMEventListener> listener;
|
||||
|
||||
mLoadEventListeners->QueryElementAt(index,
|
||||
NS_GET_IID(nsIDOMEventListener),
|
||||
getter_AddRefs(listener));
|
||||
|
||||
if (listener) {
|
||||
listener->HandleEvent(mDelayedEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cx) {
|
||||
stack->Pop(&cx);
|
||||
}
|
||||
|
||||
mDelayedEvent = nsnull;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -915,7 +1019,7 @@ nsXMLHttpRequest::Send(nsISupports *body)
|
||||
}
|
||||
|
||||
// Make sure we've been opened
|
||||
if (!mChannel) {
|
||||
if (!mChannel || XML_HTTP_REQUEST_OPENED != mStatus) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
@ -1084,7 +1188,7 @@ nsXMLHttpRequest::Send(nsISupports *body)
|
||||
#endif
|
||||
|
||||
// Start reading from the channel
|
||||
mStatus = XML_HTTP_REQUEST_SENT;
|
||||
ChangeState(XML_HTTP_REQUEST_SENT);
|
||||
mXMLParserStreamListener = listener;
|
||||
rv = mChannel->AsyncOpen(this, nsnull);
|
||||
|
||||
@ -1117,6 +1221,9 @@ nsXMLHttpRequest::Send(nsISupports *body)
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::SetRequestHeader(const char *header, const char *value)
|
||||
{
|
||||
if (!mChannel) // open() initializes mChannel, and open()
|
||||
return NS_ERROR_FAILURE; // must be called before first setRequestHeader()
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel));
|
||||
|
||||
if (httpChannel)
|
||||
@ -1125,6 +1232,19 @@ nsXMLHttpRequest::SetRequestHeader(const char *header, const char *value)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute long readyState; */
|
||||
NS_IMETHODIMP
|
||||
nsXMLHttpRequest::GetReadyState(PRInt32 *aState)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aState);
|
||||
if (mStatus == XML_HTTP_REQUEST_SENT) {
|
||||
*aState = XML_HTTP_REQUEST_OPENED;
|
||||
} else {
|
||||
*aState = mStatus;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDOMEventListener
|
||||
nsresult
|
||||
nsXMLHttpRequest::HandleEvent(nsIDOMEvent* aEvent)
|
||||
@ -1137,67 +1257,14 @@ nsXMLHttpRequest::HandleEvent(nsIDOMEvent* aEvent)
|
||||
nsresult
|
||||
nsXMLHttpRequest::Load(nsIDOMEvent* aEvent)
|
||||
{
|
||||
mStatus = XML_HTTP_REQUEST_COMPLETED;
|
||||
|
||||
// We might have been sent non-XML data. If that was the case,
|
||||
// we should null out the document member. The idea in this
|
||||
// check here is that if there is no document element it is not
|
||||
// an XML document. We might need a fancier check...
|
||||
if (mDocument) {
|
||||
nsCOMPtr<nsIDOMElement> root;
|
||||
mDocument->GetDocumentElement(getter_AddRefs(root));
|
||||
if (!root) {
|
||||
mDocument = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IMPLEMENT_SYNC_LOAD
|
||||
if (mChromeWindow) {
|
||||
mChromeWindow->ExitModalEventLoop(NS_OK);
|
||||
mChromeWindow = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIJSContextStack> stack;
|
||||
JSContext *cx = nsnull;
|
||||
|
||||
if (mScriptContext) {
|
||||
stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
|
||||
if (stack) {
|
||||
cx = (JSContext *)mScriptContext->GetNativeContext();
|
||||
|
||||
if (cx) {
|
||||
stack->Push(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mOnLoadListener) {
|
||||
mOnLoadListener->HandleEvent(aEvent);
|
||||
}
|
||||
|
||||
if (mLoadEventListeners) {
|
||||
PRUint32 index, count;
|
||||
|
||||
mLoadEventListeners->Count(&count);
|
||||
for (index = 0; index < count; index++) {
|
||||
nsCOMPtr<nsIDOMEventListener> listener;
|
||||
|
||||
mLoadEventListeners->QueryElementAt(index,
|
||||
NS_GET_IID(nsIDOMEventListener),
|
||||
getter_AddRefs(listener));
|
||||
|
||||
if (listener) {
|
||||
listener->HandleEvent(aEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cx) {
|
||||
stack->Pop(&cx);
|
||||
}
|
||||
|
||||
// If we had an XML error in the data, the parser terminated and
|
||||
// we received the load event, even though we might still be
|
||||
// loading data into responseBody/responseText. We will delay
|
||||
// sending the load event until OnStopRequest(). In normal case
|
||||
// there is no harm done, we will get OnStopRequest() immediately
|
||||
// after the load event.
|
||||
NS_WARN_IF_FALSE(!mDelayedEvent,"there should be no delayed event");
|
||||
mDelayedEvent = aEvent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1210,8 +1277,8 @@ nsXMLHttpRequest::Unload(nsIDOMEvent* aEvent)
|
||||
nsresult
|
||||
nsXMLHttpRequest::Abort(nsIDOMEvent* aEvent)
|
||||
{
|
||||
mStatus = XML_HTTP_REQUEST_ABORTED;
|
||||
mDocument = nsnull;
|
||||
ChangeState(XML_HTTP_REQUEST_UNINITIALIZED);
|
||||
#ifdef IMPLEMENT_SYNC_LOAD
|
||||
if (mChromeWindow) {
|
||||
mChromeWindow->ExitModalEventLoop(NS_OK);
|
||||
@ -1225,8 +1292,8 @@ nsXMLHttpRequest::Abort(nsIDOMEvent* aEvent)
|
||||
nsresult
|
||||
nsXMLHttpRequest::Error(nsIDOMEvent* aEvent)
|
||||
{
|
||||
mStatus = XML_HTTP_REQUEST_ABORTED;
|
||||
mDocument = nsnull;
|
||||
ChangeState(XML_HTTP_REQUEST_UNINITIALIZED);
|
||||
#ifdef IMPLEMENT_SYNC_LOAD
|
||||
if (mChromeWindow) {
|
||||
mChromeWindow->ExitModalEventLoop(NS_OK);
|
||||
@ -1277,6 +1344,37 @@ nsXMLHttpRequest::Error(nsIDOMEvent* aEvent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXMLHttpRequest::ChangeState(nsXMLHttpRequestState aState, PRBool aBroadcast)
|
||||
{
|
||||
mStatus = aState;
|
||||
nsresult rv = NS_OK;
|
||||
if (mAsync && aBroadcast && mOnReadystatechangeListener) {
|
||||
nsCOMPtr<nsIJSContextStack> stack;
|
||||
JSContext *cx = nsnull;
|
||||
|
||||
if (mScriptContext) {
|
||||
stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
|
||||
if (stack) {
|
||||
cx = (JSContext *)mScriptContext->GetNativeContext();
|
||||
|
||||
if (cx) {
|
||||
stack->Push(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = mOnReadystatechangeListener->HandleEvent();
|
||||
|
||||
if (cx) {
|
||||
stack->Pop(&cx);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXMLHttpRequest::nsHeaderVisitor, nsIHttpHeaderVisitor)
|
||||
|
||||
NS_IMETHODIMP nsXMLHttpRequest::
|
||||
@ -1288,3 +1386,4 @@ nsHeaderVisitor::VisitHeader(const char *header, const char *value)
|
||||
mHeaders.Append('\n');
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -45,12 +45,13 @@
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
|
||||
enum {
|
||||
XML_HTTP_REQUEST_INITIALIZED,
|
||||
XML_HTTP_REQUEST_OPENED,
|
||||
XML_HTTP_REQUEST_SENT,
|
||||
enum nsXMLHttpRequestState {
|
||||
XML_HTTP_REQUEST_UNINITIALIZED = 0,
|
||||
XML_HTTP_REQUEST_OPENED, // aka LOADING
|
||||
XML_HTTP_REQUEST_LOADED,
|
||||
XML_HTTP_REQUEST_INTERACTIVE,
|
||||
XML_HTTP_REQUEST_COMPLETED,
|
||||
XML_HTTP_REQUEST_ABORTED
|
||||
XML_HTTP_REQUEST_SENT // This is Mozilla-internal only, LOADING in IE and external view
|
||||
};
|
||||
|
||||
class nsXMLHttpRequest : public nsIXMLHttpRequest,
|
||||
@ -102,6 +103,10 @@ protected:
|
||||
PRUint32 toOffset,
|
||||
PRUint32 count,
|
||||
PRUint32 *writeCount);
|
||||
// Change the state of the object with this. The broadcast member determines
|
||||
// if the onreadystatechange listener should be called.
|
||||
nsresult ChangeState(nsXMLHttpRequestState aState, PRBool aBroadcast = PR_TRUE);
|
||||
nsresult RequestCompleted();
|
||||
|
||||
nsCOMPtr<nsISupports> mContext;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
@ -118,7 +123,11 @@ protected:
|
||||
|
||||
nsCOMPtr<nsIDOMEventListener> mOnLoadListener;
|
||||
nsCOMPtr<nsIDOMEventListener> mOnErrorListener;
|
||||
|
||||
|
||||
nsCOMPtr<nsIOnReadystatechangeHandler> mOnReadystatechangeListener;
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> mDelayedEvent;
|
||||
|
||||
// used to implement getAllResponseHeaders()
|
||||
class nsHeaderVisitor : public nsIHttpHeaderVisitor {
|
||||
public:
|
||||
|
@ -23,6 +23,10 @@
|
||||
#include "nsHTTPSOAPTransport.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
|
||||
#define LOADSTR NS_LITERAL_STRING("load")
|
||||
#define ERRORSTR NS_LITERAL_STRING("error")
|
||||
|
||||
nsHTTPSOAPTransport::nsHTTPSOAPTransport()
|
||||
{
|
||||
@ -106,10 +110,13 @@ nsHTTPSOAPTransport::AsyncCall(const char *url,
|
||||
|
||||
mListener = listener;
|
||||
|
||||
mRequest->AddEventListener("load",
|
||||
NS_STATIC_CAST(nsIDOMEventListener*, this));
|
||||
mRequest->AddEventListener("error",
|
||||
NS_STATIC_CAST(nsIDOMEventListener*, this));
|
||||
nsCOMPtr<nsIDOMEventTarget> eventTarget(do_QueryInterface(mRequest, &rv));
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
eventTarget->AddEventListener(LOADSTR,
|
||||
NS_STATIC_CAST(nsIDOMEventListener*, this), PR_FALSE);
|
||||
eventTarget->AddEventListener(ERRORSTR,
|
||||
NS_STATIC_CAST(nsIDOMEventListener*, this), PR_FALSE);
|
||||
|
||||
rv = mRequest->Send(messageDocument);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
@ -28,6 +28,7 @@ function myfunc()
|
||||
document.getElementById("id3").firstChild.nodeValue = p.getAllResponseHeaders();
|
||||
document.getElementById("id4").firstChild.nodeValue = p.status;
|
||||
document.getElementById("id5").firstChild.nodeValue = p.statusText;
|
||||
document.getElementById("id6").firstChild.nodeValue = p.readyState;
|
||||
}
|
||||
|
||||
p.onload = myfunc;
|
||||
@ -54,6 +55,9 @@ p.send(null);
|
||||
<div class="box"><span class="boxheader">statusText</span>
|
||||
<pre id="id5">@@No result@@</pre>
|
||||
</div>
|
||||
<div class="box"><span class="boxheader">readyState</span>
|
||||
<pre id="id6">@@No result@@</pre>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -45,6 +45,7 @@ function myfunc()
|
||||
document.getElementById("id3").firstChild.nodeValue = p.getAllResponseHeaders();
|
||||
document.getElementById("id4").firstChild.nodeValue = p.status;
|
||||
document.getElementById("id5").firstChild.nodeValue = p.statusText;
|
||||
document.getElementById("id6").firstChild.nodeValue = p.readyState;
|
||||
}
|
||||
|
||||
p.onload = myfunc;
|
||||
@ -78,6 +79,9 @@ if (!sendPlainTextData) {
|
||||
<div class="box"><span class="boxheader">statusText</span>
|
||||
<pre id="id5">@@No result@@</pre>
|
||||
</div>
|
||||
<div class="box"><span class="boxheader">readyState</span>
|
||||
<pre id="id6">@@No result@@</pre>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -30,6 +30,7 @@ function execute()
|
||||
document.getElementById("id3").firstChild.nodeValue = p.getAllResponseHeaders();
|
||||
document.getElementById("id4").firstChild.nodeValue = p.status;
|
||||
document.getElementById("id5").firstChild.nodeValue = p.statusText;
|
||||
document.getElementById("id6").firstChild.nodeValue = p.readyState;
|
||||
}
|
||||
|
||||
setTimeout(execute,0); // Enable the rest of this document to load before executing
|
||||
@ -53,6 +54,9 @@ setTimeout(execute,0); // Enable the rest of this document to load before execut
|
||||
<div class="box"><span class="boxheader">statusText</span>
|
||||
<pre id="id5">@@No result@@</pre>
|
||||
</div>
|
||||
<div class="box"><span class="boxheader">readyState</span>
|
||||
<pre id="id6">@@No result@@</pre>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -36,6 +36,7 @@ function execute()
|
||||
document.getElementById("id3").firstChild.nodeValue = p.getAllResponseHeaders();
|
||||
document.getElementById("id4").firstChild.nodeValue = p.status;
|
||||
document.getElementById("id5").firstChild.nodeValue = p.statusText;
|
||||
document.getElementById("id6").firstChild.nodeValue = p.readyState;
|
||||
}
|
||||
|
||||
setTimeout(execute,0); // Enable the rest of this document to load before executing
|
||||
@ -59,6 +60,9 @@ setTimeout(execute,0); // Enable the rest of this document to load before execut
|
||||
<div class="box"><span class="boxheader">statusText</span>
|
||||
<pre id="id5">@@No result@@</pre>
|
||||
</div>
|
||||
<div class="box"><span class="boxheader">readyState</span>
|
||||
<pre id="id6">@@No result@@</pre>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
127
extensions/xmlextras/tests/xpost.html
Normal file
127
extensions/xmlextras/tests/xpost.html
Normal file
@ -0,0 +1,127 @@
|
||||
<html>
|
||||
<head><title>POST test</title>
|
||||
<style type="text/css">
|
||||
.box {
|
||||
display: box;
|
||||
border: 1px solid black;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.boxheader {
|
||||
font-weight: bold;
|
||||
color: maroon;
|
||||
}
|
||||
pre {
|
||||
margin-left: 2em;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
var p;
|
||||
try {
|
||||
p = new XMLHttpRequest();
|
||||
} catch (e) {
|
||||
p = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}
|
||||
|
||||
// In Mozilla, you can only create the text string if you can bybass security, like in chrome
|
||||
var sendPlainTextData = false;
|
||||
|
||||
var x;
|
||||
if (!sendPlainTextData) {
|
||||
try {
|
||||
x = document.implementation.createDocument("", "test", null);
|
||||
x.documentElement.appendChild(document.createElement("Foo"));
|
||||
x.documentElement.appendChild(document.createElement("Bar"));
|
||||
x.documentElement.firstChild.appendChild(document.createTextNode("My Stuff\nYeah"));
|
||||
} catch (e) {
|
||||
x = new ActiveXObject("Msxml2.DOMDocument");
|
||||
x.loadXML("<?xml version='1.0'?>\n<test><foo>My Stuff\nYeah</foo><bar/></test>");
|
||||
}
|
||||
}
|
||||
|
||||
function myfunc()
|
||||
{
|
||||
//alert("myfunc readyState=" + p.readyState);
|
||||
//if (p.readyState == 2) {
|
||||
// alert(p.getAllResponseHeaders());
|
||||
// alert(p.status);
|
||||
//}
|
||||
if (p.readyState != 4)
|
||||
return;
|
||||
|
||||
var str;
|
||||
|
||||
if (!sendPlainTextData) {
|
||||
try {
|
||||
var s = new XMLSerializer();
|
||||
var d = p.responseXML;
|
||||
str = s.serializeToString(d);
|
||||
} catch (e) {
|
||||
str = "@@TODO@@";
|
||||
}
|
||||
} else {
|
||||
str = p.responseText;
|
||||
}
|
||||
document.getElementById("id1").firstChild.nodeValue = p.responseText;
|
||||
document.getElementById("id2").firstChild.nodeValue = str;
|
||||
document.getElementById("id3").firstChild.nodeValue = p.getAllResponseHeaders();
|
||||
document.getElementById("id4").firstChild.nodeValue = p.status;
|
||||
document.getElementById("id5").firstChild.nodeValue = p.statusText;
|
||||
document.getElementById("id6").firstChild.nodeValue = p.readyState;
|
||||
}
|
||||
|
||||
// p.onload would also work in Mozilla
|
||||
p.onreadystatechange = myfunc;
|
||||
|
||||
try {
|
||||
// Needed for Mozilla if local file tries to access an http URL
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
//alert("before open():" +p.readyState);// 0 = UNINITIALIZED
|
||||
p.open("POST", "http://green/cgi-bin/echo_xml.cgi");
|
||||
//alert("after open():" +p.readyState);// 1 = LOADING
|
||||
|
||||
if (!sendPlainTextData) {
|
||||
//alert("Going to send");
|
||||
p.send(x);
|
||||
//alert("Done to send");
|
||||
} else {
|
||||
var mystr;
|
||||
try {
|
||||
var WSTRING_CONTRACTID = "@mozilla.org/supports-wstring;1";
|
||||
mystr = Components.classes[WSTRING_CONTRACTID].createInstance(Components.interfaces.nsISupportsWString);
|
||||
mystr.data = "Heikki's data";
|
||||
} catch (e) {
|
||||
mystr = "Heikki's data";
|
||||
}
|
||||
p.send(mystr);
|
||||
}
|
||||
//alert("after send():" +p.readyState);// 1 = LOADING
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>POST test</h1>
|
||||
|
||||
<div class="box"><span class="boxheader">responseText</span>
|
||||
<pre id="id1">@@No result@@</pre>
|
||||
</div>
|
||||
<div class="box"><span class="boxheader">responseXML serialized</span>
|
||||
<pre id="id2">@@No result@@</pre>
|
||||
</div>
|
||||
<div class="box"><span class="boxheader">getAllResponseHeaders()</span>
|
||||
<pre id="id3">@@No result@@</pre>
|
||||
</div>
|
||||
<div class="box"><span class="boxheader">status</span>
|
||||
<pre id="id4">@@No result@@</pre>
|
||||
</div>
|
||||
<div class="box"><span class="boxheader">statusText</span>
|
||||
<pre id="id5">@@No result@@</pre>
|
||||
</div>
|
||||
<div class="box"><span class="boxheader">readyState</span>
|
||||
<pre id="id6">@@No result@@</pre>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user