2006-04-20 07:37:39 +04:00
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version : NPL 1.1 / GPL 2.0 / LGPL 2.1
2006-04-20 07:36:50 +04:00
*
2006-04-20 07:37:39 +04:00
* The contents of this file are subject to the Netscape 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/NPL/
2006-04-20 07:36:50 +04:00
*
2006-04-20 07:37:39 +04:00
* 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 .
2006-04-20 07:36:50 +04:00
*
* The Original Code is mozilla . org code .
*
2006-04-20 07:37:39 +04:00
* The Initial Developer of the Original Code is
* Netscape Communications Corporation .
* Portions created by the Initial Developer are Copyright ( C ) 1998
* the Initial Developer . All Rights Reserved .
2006-04-20 07:36:50 +04:00
*
2006-04-20 07:37:39 +04:00
* Contributor ( s ) :
*
*
* 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 NPL , 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 NPL , the GPL or the LGPL .
*
* * * * * * END LICENSE BLOCK * * * * * */
2006-04-20 07:36:50 +04:00
# include "nsXMLHttpRequest.h"
# include "nsISimpleEnumerator.h"
# include "nsIXPConnect.h"
# include "nsIByteArrayInputStream.h"
# include "nsIUnicodeEncoder.h"
# include "nsIServiceManager.h"
# include "nsICharsetConverterManager.h"
# include "nsLayoutCID.h"
# include "nsIDOMDOMImplementation.h"
# include "nsIPrivateDOMImplementation.h"
# include "nsXPIDLString.h"
2006-04-20 07:37:41 +04:00
# include "nsReadableUtils.h"
2006-04-20 07:37:53 +04:00
# include "nsPrintfCString.h"
2006-04-20 07:38:00 +04:00
# include "nsCRT.h"
2006-04-20 07:36:50 +04:00
# include "nsIURI.h"
# include "nsILoadGroup.h"
# include "nsNetUtil.h"
2006-04-20 07:37:32 +04:00
# include "nsIUploadChannel.h"
2006-04-20 07:36:50 +04:00
# include "nsIDOMSerializer.h"
# include "nsISupportsPrimitives.h"
2006-04-20 07:36:54 +04:00
# include "nsIDOMEventReceiver.h"
2006-04-20 07:37:34 +04:00
# include "nsIEventListenerManager.h"
# include "nsGUIEvent.h"
# include "nsIPrivateDOMEvent.h"
2006-04-20 07:36:50 +04:00
# include "prprf.h"
# include "nsIDOMEventListener.h"
# include "nsIJSContextStack.h"
2006-04-20 07:36:51 +04:00
# include "nsIScriptSecurityManager.h"
# include "nsICodebasePrincipal.h"
2006-04-20 07:36:54 +04:00
# include "nsWeakPtr.h"
2006-04-20 07:37:08 +04:00
# include "nsICharsetAlias.h"
2006-04-20 07:36:54 +04:00
# ifdef IMPLEMENT_SYNC_LOAD
# include "nsIScriptContext.h"
# include "nsIScriptGlobalObject.h"
# include "nsIDocShell.h"
# include "nsIDocShellTreeItem.h"
2006-04-20 07:37:11 +04:00
# include "nsIDocShellTreeOwner.h"
2006-04-20 07:36:54 +04:00
# include "nsIEventQueueService.h"
2006-04-20 07:37:11 +04:00
# include "nsIInterfaceRequestor.h"
2006-04-20 07:37:33 +04:00
# include "nsIInterfaceRequestorUtils.h"
2006-04-20 07:36:54 +04:00
# endif
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
# include "nsIDOMClassInfo.h"
2006-04-20 07:37:25 +04:00
# include "nsIDOMElement.h"
2006-04-20 07:37:45 +04:00
# include "nsIVariant.h"
2006-04-20 07:37:35 +04:00
# include "nsIParser.h"
# include "nsLoadListenerProxy.h"
2006-04-20 07:38:01 +04:00
# include "nsIWindowWatcher.h"
# include "nsIAuthPrompt.h"
2006-04-20 07:36:50 +04:00
static const char * kLoadAsData = " loadAsData " ;
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
# define LOADSTR NS_LITERAL_STRING("load")
# define ERRORSTR NS_LITERAL_STRING("error")
2006-04-20 07:36:50 +04:00
2006-04-20 07:36:54 +04:00
// CIDs
2006-04-20 07:36:50 +04:00
static NS_DEFINE_CID ( kIDOMDOMImplementationCID , NS_DOM_IMPLEMENTATION_CID ) ;
static NS_DEFINE_CID ( kCharsetConverterManagerCID , NS_ICHARSETCONVERTERMANAGER_CID ) ;
2006-04-20 07:36:54 +04:00
# ifdef IMPLEMENT_SYNC_LOAD
static NS_DEFINE_IID ( kEventQueueServiceCID , NS_EVENTQUEUESERVICE_CID ) ;
# endif
2006-04-20 07:36:50 +04:00
2006-04-20 07:37:23 +04:00
static void
GetCurrentContext ( nsIScriptContext * * aScriptContext )
2006-04-20 07:36:50 +04:00
{
2006-04-20 07:37:23 +04:00
* aScriptContext = nsnull ;
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
2006-04-20 07:36:50 +04:00
// Get JSContext from stack.
2006-04-20 07:37:23 +04:00
nsCOMPtr < nsIJSContextStack > stack =
do_GetService ( " @mozilla.org/js/xpc/ContextStack;1 " ) ;
2006-04-20 07:36:50 +04:00
2006-04-20 07:37:23 +04:00
if ( ! stack ) {
return ;
2006-04-20 07:36:50 +04:00
}
2006-04-20 07:37:23 +04:00
JSContext * cx ;
2006-04-20 07:36:50 +04:00
2006-04-20 07:37:23 +04:00
if ( NS_FAILED ( stack - > Peek ( & cx ) ) ) {
return ;
}
2006-04-20 07:36:50 +04:00
if ( ! cx ) {
2006-04-20 07:37:23 +04:00
return ;
2006-04-20 07:36:50 +04:00
}
2006-04-20 07:37:23 +04:00
nsISupports * priv = ( nsISupports * ) : : JS_GetContextPrivate ( cx ) ;
if ( ! priv ) {
return ;
2006-04-20 07:36:50 +04:00
}
2006-04-20 07:37:23 +04:00
CallQueryInterface ( priv , aScriptContext ) ;
return ;
2006-04-20 07:36:50 +04:00
}
2006-04-20 07:36:54 +04:00
2006-04-20 07:36:50 +04:00
/////////////////////////////////////////////
//
//
/////////////////////////////////////////////
nsXMLHttpRequest : : nsXMLHttpRequest ( )
{
NS_INIT_ISUPPORTS ( ) ;
2006-04-20 07:37:31 +04:00
ChangeState ( XML_HTTP_REQUEST_UNINITIALIZED , PR_FALSE ) ;
2006-04-20 07:36:51 +04:00
mAsync = PR_TRUE ;
2006-04-20 07:38:01 +04:00
mCrossSiteAccessEnabled = PR_FALSE ;
2006-04-20 07:36:50 +04:00
}
nsXMLHttpRequest : : ~ nsXMLHttpRequest ( )
{
2006-04-20 07:36:54 +04:00
if ( XML_HTTP_REQUEST_SENT = = mStatus ) {
Abort ( ) ;
}
# ifdef IMPLEMENT_SYNC_LOAD
2006-04-20 07:37:11 +04:00
if ( mChromeWindow ) {
mChromeWindow - > ExitModalEventLoop ( NS_OK ) ;
2006-04-20 07:36:54 +04:00
}
# endif
2006-04-20 07:36:50 +04:00
}
2006-04-20 07:36:54 +04:00
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
// QueryInterface implementation for nsXMLHttpRequest
2006-04-20 07:36:54 +04:00
NS_INTERFACE_MAP_BEGIN ( nsXMLHttpRequest )
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS ( nsISupports , nsIXMLHttpRequest )
NS_INTERFACE_MAP_ENTRY ( nsIXMLHttpRequest )
2006-04-20 07:37:23 +04:00
NS_INTERFACE_MAP_ENTRY ( nsIJSXMLHttpRequest )
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
NS_INTERFACE_MAP_ENTRY ( nsIDOMLoadListener )
NS_INTERFACE_MAP_ENTRY ( nsIDOMEventTarget )
NS_INTERFACE_MAP_ENTRY ( nsIRequestObserver )
NS_INTERFACE_MAP_ENTRY ( nsIStreamListener )
2006-04-20 07:38:01 +04:00
NS_INTERFACE_MAP_ENTRY ( nsIHttpEventSink )
NS_INTERFACE_MAP_ENTRY ( nsIInterfaceRequestor )
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
NS_INTERFACE_MAP_ENTRY ( nsISupportsWeakReference )
2006-04-20 07:37:50 +04:00
NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO ( XMLHttpRequest )
2006-04-20 07:36:54 +04:00
NS_INTERFACE_MAP_END
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
NS_IMPL_ADDREF ( nsXMLHttpRequest )
NS_IMPL_RELEASE ( nsXMLHttpRequest )
2006-04-20 07:37:23 +04:00
/* void addEventListener (in string type, in nsIDOMEventListener
listener ) ; */
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
NS_IMETHODIMP
2006-04-20 07:37:57 +04:00
nsXMLHttpRequest : : AddEventListener ( const nsAString & type ,
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
nsIDOMEventListener * listener ,
PRBool useCapture )
2006-04-20 07:36:50 +04:00
{
NS_ENSURE_ARG ( listener ) ;
nsresult rv ;
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
if ( type . Equals ( LOADSTR ) ) {
2006-04-20 07:36:50 +04:00
if ( ! mLoadEventListeners ) {
rv = NS_NewISupportsArray ( getter_AddRefs ( mLoadEventListeners ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
mLoadEventListeners - > AppendElement ( listener ) ;
}
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
else if ( type . Equals ( ERRORSTR ) ) {
2006-04-20 07:36:50 +04:00
if ( ! mErrorEventListeners ) {
rv = NS_NewISupportsArray ( getter_AddRefs ( mErrorEventListeners ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
mErrorEventListeners - > AppendElement ( listener ) ;
}
else {
return NS_ERROR_INVALID_ARG ;
}
2006-04-20 07:37:47 +04:00
GetCurrentContext ( getter_AddRefs ( mScriptContext ) ) ;
2006-04-20 07:36:50 +04:00
return NS_OK ;
}
2006-04-20 07:37:23 +04:00
/* void removeEventListener (in string type, in nsIDOMEventListener
listener ) ; */
2006-04-20 07:36:50 +04:00
NS_IMETHODIMP
2006-04-20 07:37:57 +04:00
nsXMLHttpRequest : : RemoveEventListener ( const nsAString & type ,
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
nsIDOMEventListener * listener ,
PRBool useCapture )
2006-04-20 07:36:50 +04:00
{
NS_ENSURE_ARG ( listener ) ;
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
if ( type . Equals ( LOADSTR ) ) {
2006-04-20 07:36:50 +04:00
if ( mLoadEventListeners ) {
mLoadEventListeners - > RemoveElement ( listener ) ;
}
}
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
else if ( type . Equals ( ERRORSTR ) ) {
2006-04-20 07:36:50 +04:00
if ( mErrorEventListeners ) {
mErrorEventListeners - > RemoveElement ( listener ) ;
}
}
else {
return NS_ERROR_INVALID_ARG ;
}
return NS_OK ;
}
2006-04-20 07:37:40 +04:00
/* boolean dispatchEvent (in nsIDOMEvent evt); */
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
NS_IMETHODIMP
2006-04-20 07:37:40 +04:00
nsXMLHttpRequest : : DispatchEvent ( nsIDOMEvent * evt , PRBool * _retval )
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
{
// Ignored
return NS_OK ;
}
2006-04-20 07:37:31 +04:00
/* 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 ;
}
2006-04-20 07:36:50 +04:00
/* attribute nsIDOMEventListener onload; */
NS_IMETHODIMP
2006-04-20 07:37:23 +04:00
nsXMLHttpRequest : : GetOnload ( nsIDOMEventListener * * aOnLoad )
2006-04-20 07:36:50 +04:00
{
NS_ENSURE_ARG_POINTER ( aOnLoad ) ;
2006-04-20 07:37:23 +04:00
* aOnLoad = mOnLoadListener ;
2006-04-20 07:36:50 +04:00
return NS_OK ;
}
NS_IMETHODIMP
2006-04-20 07:37:23 +04:00
nsXMLHttpRequest : : SetOnload ( nsIDOMEventListener * aOnLoad )
2006-04-20 07:36:50 +04:00
{
2006-04-20 07:37:23 +04:00
mOnLoadListener = aOnLoad ;
2006-04-20 07:36:50 +04:00
2006-04-20 07:37:23 +04:00
GetCurrentContext ( getter_AddRefs ( mScriptContext ) ) ;
2006-04-20 07:36:50 +04:00
2006-04-20 07:37:23 +04:00
return NS_OK ;
2006-04-20 07:36:50 +04:00
}
/* attribute nsIDOMEventListener onerror; */
NS_IMETHODIMP
2006-04-20 07:37:23 +04:00
nsXMLHttpRequest : : GetOnerror ( nsIDOMEventListener * * aOnerror )
2006-04-20 07:36:50 +04:00
{
NS_ENSURE_ARG_POINTER ( aOnerror ) ;
2006-04-20 07:37:23 +04:00
* aOnerror = mOnErrorListener ;
2006-04-20 07:36:50 +04:00
return NS_OK ;
}
NS_IMETHODIMP
2006-04-20 07:37:23 +04:00
nsXMLHttpRequest : : SetOnerror ( nsIDOMEventListener * aOnerror )
2006-04-20 07:36:50 +04:00
{
2006-04-20 07:37:23 +04:00
mOnErrorListener = aOnerror ;
2006-04-20 07:36:50 +04:00
2006-04-20 07:37:23 +04:00
GetCurrentContext ( getter_AddRefs ( mScriptContext ) ) ;
2006-04-20 07:36:50 +04:00
2006-04-20 07:37:23 +04:00
return NS_OK ;
2006-04-20 07:36:50 +04:00
}
2006-04-20 07:37:29 +04:00
/* readonly attribute nsIChannel channel; */
NS_IMETHODIMP nsXMLHttpRequest : : GetChannel ( nsIChannel * * aChannel )
2006-04-20 07:37:01 +04:00
{
NS_ENSURE_ARG_POINTER ( aChannel ) ;
* aChannel = mChannel ;
NS_IF_ADDREF ( * aChannel ) ;
return NS_OK ;
}
2006-04-20 07:36:50 +04:00
/* readonly attribute nsIDOMDocument responseXML; */
NS_IMETHODIMP nsXMLHttpRequest : : GetResponseXML ( nsIDOMDocument * * aResponseXML )
{
NS_ENSURE_ARG_POINTER ( aResponseXML ) ;
* aResponseXML = nsnull ;
2006-04-20 07:36:54 +04:00
if ( ( XML_HTTP_REQUEST_COMPLETED = = mStatus ) & & mDocument ) {
2006-04-20 07:36:50 +04:00
* aResponseXML = mDocument ;
NS_ADDREF ( * aResponseXML ) ;
}
return NS_OK ;
}
2006-04-20 07:37:08 +04:00
/*
* This piece copied from nsXMLDocument , we try to get the charset
* from HTTP headers .
*/
nsresult
2006-04-20 07:37:57 +04:00
nsXMLHttpRequest : : DetectCharset ( nsAString & aCharset )
2006-04-20 07:37:08 +04:00
{
aCharset . Truncate ( ) ;
nsresult rv ;
2006-04-20 07:37:53 +04:00
nsCAutoString charsetVal ;
rv = mChannel - > GetContentCharset ( charsetVal ) ;
if ( NS_SUCCEEDED ( rv ) ) {
nsCOMPtr < nsICharsetAlias > calias ( do_GetService ( kCharsetAliasCID , & rv ) ) ;
if ( NS_SUCCEEDED ( rv ) & & calias ) {
nsAutoString preferred ;
rv = calias - > GetPreferred ( NS_ConvertASCIItoUCS2 ( charsetVal ) , preferred ) ;
if ( NS_SUCCEEDED ( rv ) ) {
aCharset . Assign ( preferred ) ;
2006-04-20 07:37:08 +04:00
}
}
}
return rv ;
}
nsresult
nsXMLHttpRequest : : ConvertBodyToText ( PRUnichar * * aOutBuffer )
{
2006-04-20 07:37:54 +04:00
// This code here is basically a copy of a similar thing in
// nsScanner::Append(const char* aBuffer, PRUint32 aLen).
// If we get illegal characters in the input we replace
// them and don't just fail.
2006-04-20 07:37:08 +04:00
* aOutBuffer = nsnull ;
2006-04-20 07:37:22 +04:00
PRInt32 dataLen = mResponseBody . Length ( ) ;
2006-04-20 07:37:08 +04:00
if ( ! dataLen )
return NS_OK ;
nsresult rv = NS_OK ;
nsAutoString dataCharset ;
nsCOMPtr < nsIDocument > document ( do_QueryInterface ( mDocument ) ) ;
if ( document ) {
rv = document - > GetDocumentCharacterSet ( dataCharset ) ;
if ( NS_FAILED ( rv ) )
return rv ;
} else {
if ( NS_FAILED ( DetectCharset ( dataCharset ) ) | | dataCharset . IsEmpty ( ) ) {
dataCharset . Assign ( NS_LITERAL_STRING ( " ISO-8859-1 " ) ) ; // Parser assumes ISO-8859-1
}
}
if ( dataCharset . Equals ( NS_LITERAL_STRING ( " ASCII " ) ) ) {
2006-04-20 07:37:41 +04:00
* aOutBuffer = ToNewUnicode ( nsDependentCString ( mResponseBody . get ( ) , dataLen ) ) ;
2006-04-20 07:37:08 +04:00
if ( ! * aOutBuffer )
return NS_ERROR_OUT_OF_MEMORY ;
return NS_OK ;
}
nsCOMPtr < nsICharsetConverterManager > ccm ( do_GetService ( NS_CHARSETCONVERTERMANAGER_CONTRACTID , & rv ) ) ;
if ( NS_FAILED ( rv ) )
return rv ;
nsCOMPtr < nsIUnicodeDecoder > decoder ;
rv = ccm - > GetUnicodeDecoder ( & dataCharset , getter_AddRefs ( decoder ) ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2006-04-20 07:37:22 +04:00
const char * inBuffer = mResponseBody . get ( ) ;
2006-04-20 07:37:54 +04:00
PRInt32 outBufferLength ;
rv = decoder - > GetMaxLength ( inBuffer , dataLen , & outBufferLength ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2006-04-20 07:37:08 +04:00
2006-04-20 07:37:54 +04:00
PRUnichar * outBuffer =
NS_STATIC_CAST ( PRUnichar * , nsMemory : : Alloc ( ( outBufferLength + 1 ) *
sizeof ( PRUnichar ) ) ) ;
if ( ! outBuffer ) {
return NS_ERROR_OUT_OF_MEMORY ;
}
2006-04-20 07:37:08 +04:00
2006-04-20 07:37:54 +04:00
PRInt32 totalChars = 0 ,
outBufferIndex = 0 ,
outLen = outBufferLength ;
do {
PRInt32 inBufferLength = dataLen ;
rv = decoder - > Convert ( inBuffer ,
& inBufferLength ,
& outBuffer [ outBufferIndex ] ,
& outLen ) ;
totalChars + = outLen ;
if ( NS_FAILED ( rv ) ) {
2006-04-20 07:37:08 +04:00
// We consume one byte, replace it with U+FFFD
// and try the conversion again.
2006-04-20 07:37:54 +04:00
outBuffer [ outBufferIndex + outLen + + ] = ( PRUnichar ) 0xFFFD ;
2006-04-20 07:37:08 +04:00
outBufferIndex + = outLen ;
2006-04-20 07:37:54 +04:00
outLen = outBufferLength - ( + + totalChars ) ;
decoder - > Reset ( ) ;
if ( ( inBufferLength + 1 ) > dataLen ) {
inBufferLength = dataLen ;
} else {
inBufferLength + + ;
}
inBuffer = & inBuffer [ inBufferLength ] ;
dataLen - = inBufferLength ;
2006-04-20 07:37:08 +04:00
}
2006-04-20 07:37:54 +04:00
} while ( NS_FAILED ( rv ) & & ( dataLen > 0 ) ) ;
outBuffer [ totalChars ] = ' \0 ' ;
2006-04-20 07:37:08 +04:00
* aOutBuffer = outBuffer ;
return NS_OK ;
}
/* readonly attribute wstring responseText; */
NS_IMETHODIMP nsXMLHttpRequest : : GetResponseText ( PRUnichar * * aResponseText )
{
NS_ENSURE_ARG_POINTER ( aResponseText ) ;
* aResponseText = nsnull ;
2006-04-20 07:37:31 +04:00
if ( ( XML_HTTP_REQUEST_COMPLETED = = mStatus ) | |
( XML_HTTP_REQUEST_INTERACTIVE = = mStatus ) ) {
2006-04-20 07:37:22 +04:00
// First check if we can represent the data as a string - if it contains
// nulls we won't try.
if ( mResponseBody . FindChar ( ' \0 ' ) > = 0 )
2006-04-20 07:37:31 +04:00
return NS_OK ;
2006-04-20 07:37:08 +04:00
nsresult rv = ConvertBodyToText ( aResponseText ) ;
if ( NS_FAILED ( rv ) )
return rv ;
}
return NS_OK ;
}
2006-04-20 07:36:50 +04:00
/* readonly attribute unsigned long status; */
NS_IMETHODIMP
nsXMLHttpRequest : : GetStatus ( PRUint32 * aStatus )
{
2006-04-20 07:37:29 +04:00
nsCOMPtr < nsIHttpChannel > httpChannel ( do_QueryInterface ( mChannel ) ) ;
if ( httpChannel ) {
return httpChannel - > GetResponseStatus ( aStatus ) ;
}
* aStatus = 0 ;
2006-04-20 07:36:50 +04:00
return NS_OK ;
}
/* readonly attribute string statusText; */
NS_IMETHODIMP
nsXMLHttpRequest : : GetStatusText ( char * * aStatusText )
{
2006-04-20 07:36:55 +04:00
NS_ENSURE_ARG_POINTER ( aStatusText ) ;
2006-04-20 07:37:29 +04:00
nsCOMPtr < nsIHttpChannel > httpChannel ( do_QueryInterface ( mChannel ) ) ;
2006-04-20 07:37:53 +04:00
* aStatusText = nsnull ;
2006-04-20 07:37:29 +04:00
if ( httpChannel ) {
2006-04-20 07:37:53 +04:00
nsCAutoString text ;
nsresult rv = httpChannel - > GetResponseStatusText ( text ) ;
if ( NS_FAILED ( rv ) ) return rv ;
* aStatusText = ToNewCString ( text ) ;
return * aStatusText ? NS_OK : NS_ERROR_OUT_OF_MEMORY ;
2006-04-20 07:36:50 +04:00
}
return NS_OK ;
}
/* void abort (); */
NS_IMETHODIMP
nsXMLHttpRequest : : Abort ( )
{
2006-04-20 07:37:07 +04:00
if ( mReadRequest ) {
2006-04-20 07:37:51 +04:00
mReadRequest - > Cancel ( NS_BINDING_ABORTED ) ;
}
if ( mChannel ) {
mChannel - > Cancel ( NS_BINDING_ABORTED ) ;
2006-04-20 07:36:50 +04:00
}
return NS_OK ;
}
/* string getAllResponseHeaders (); */
NS_IMETHODIMP
nsXMLHttpRequest : : GetAllResponseHeaders ( char * * _retval )
{
NS_ENSURE_ARG_POINTER ( _retval ) ;
2006-04-20 07:36:55 +04:00
* _retval = nsnull ;
2006-04-20 07:37:29 +04:00
nsCOMPtr < nsIHttpChannel > httpChannel ( do_QueryInterface ( mChannel ) ) ;
if ( httpChannel ) {
2006-04-20 07:37:18 +04:00
nsHeaderVisitor * visitor = nsnull ;
NS_NEWXPCOM ( visitor , nsHeaderVisitor ) ;
if ( ! visitor )
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF ( visitor ) ;
2006-04-20 07:36:50 +04:00
2006-04-20 07:37:29 +04:00
nsresult rv = httpChannel - > VisitResponseHeaders ( visitor ) ;
2006-04-20 07:37:18 +04:00
if ( NS_SUCCEEDED ( rv ) )
* _retval = ToNewCString ( visitor - > Headers ( ) ) ;
NS_RELEASE ( visitor ) ;
return rv ;
2006-04-20 07:36:50 +04:00
}
return NS_OK ;
}
/* string getResponseHeader (in string header); */
NS_IMETHODIMP
nsXMLHttpRequest : : GetResponseHeader ( const char * header , char * * _retval )
{
NS_ENSURE_ARG ( header ) ;
NS_ENSURE_ARG_POINTER ( _retval ) ;
2006-04-20 07:37:29 +04:00
nsCOMPtr < nsIHttpChannel > httpChannel ( do_QueryInterface ( mChannel ) ) ;
2006-04-20 07:36:50 +04:00
2006-04-20 07:36:55 +04:00
* _retval = nsnull ;
2006-04-20 07:37:53 +04:00
if ( httpChannel ) {
nsCAutoString buf ;
nsresult rv = httpChannel - > GetResponseHeader ( nsDependentCString ( header ) , buf ) ;
if ( NS_FAILED ( rv ) ) return rv ;
* _retval = ToNewCString ( buf ) ;
return * _retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY ;
}
2006-04-20 07:36:50 +04:00
return NS_OK ;
}
2006-04-20 07:36:55 +04:00
/* noscript void openRequest (in string method, in string url, in boolean async, in string user, in string password); */
2006-04-20 07:36:50 +04:00
NS_IMETHODIMP
nsXMLHttpRequest : : OpenRequest ( const char * method ,
2006-04-20 07:36:55 +04:00
const char * url ,
2006-04-20 07:36:50 +04:00
PRBool async ,
const char * user ,
const char * password )
{
NS_ENSURE_ARG ( method ) ;
NS_ENSURE_ARG ( url ) ;
nsresult rv ;
2006-04-20 07:36:51 +04:00
nsCOMPtr < nsIURI > uri ;
2006-04-20 07:36:50 +04:00
PRBool authp = PR_FALSE ;
2006-04-20 07:37:22 +04:00
// Return error if we're already processing a request
2006-04-20 07:36:54 +04:00
if ( XML_HTTP_REQUEST_SENT = = mStatus ) {
return NS_ERROR_FAILURE ;
}
2006-04-20 07:36:50 +04:00
mAsync = async ;
2006-04-20 07:36:55 +04:00
rv = NS_NewURI ( getter_AddRefs ( uri ) , url , mBaseURI ) ;
2006-04-20 07:36:50 +04:00
if ( NS_FAILED ( rv ) ) return rv ;
if ( user ) {
2006-04-20 07:37:52 +04:00
nsCAutoString userpass ;
userpass . Assign ( user ) ;
2006-04-20 07:36:50 +04:00
if ( password ) {
2006-04-20 07:37:52 +04:00
userpass . Append ( " : " ) ;
userpass . Append ( password ) ;
2006-04-20 07:36:50 +04:00
}
2006-04-20 07:37:52 +04:00
uri - > SetUserPass ( userpass ) ;
2006-04-20 07:36:50 +04:00
authp = PR_TRUE ;
}
2006-04-20 07:37:52 +04:00
rv = NS_NewChannel ( getter_AddRefs ( mChannel ) , uri , nsnull , nsnull ) ;
2006-04-20 07:36:50 +04:00
if ( NS_FAILED ( rv ) ) return rv ;
2006-04-20 07:37:18 +04:00
//mChannel->SetAuthTriedWithPrehost(authp);
2006-04-20 07:36:51 +04:00
2006-04-20 07:37:29 +04:00
nsCOMPtr < nsIHttpChannel > httpChannel ( do_QueryInterface ( mChannel ) ) ;
if ( httpChannel ) {
2006-04-20 07:37:53 +04:00
rv = httpChannel - > SetRequestMethod ( nsDependentCString ( method ) ) ;
2006-04-20 07:37:29 +04:00
}
2006-04-20 07:36:54 +04:00
2006-04-20 07:37:31 +04:00
ChangeState ( XML_HTTP_REQUEST_OPENED ) ;
2006-04-20 07:36:54 +04:00
2006-04-20 07:36:50 +04:00
return rv ;
}
2006-04-20 07:36:55 +04:00
/* void open (in string method, in string url); */
2006-04-20 07:36:50 +04:00
NS_IMETHODIMP
2006-04-20 07:36:55 +04:00
nsXMLHttpRequest : : Open ( const char * method , const char * url )
2006-04-20 07:36:50 +04:00
{
nsresult rv ;
PRBool async = PR_TRUE ;
char * user = nsnull ;
char * password = nsnull ;
nsCOMPtr < nsIXPCNativeCallContext > cc ;
2006-04-20 07:37:27 +04:00
nsCOMPtr < nsIXPConnect > xpc ( do_GetService ( nsIXPConnect : : GetCID ( ) , & rv ) ) ;
2006-04-20 07:36:50 +04:00
if ( NS_SUCCEEDED ( rv ) ) {
rv = xpc - > GetCurrentNativeCallContext ( getter_AddRefs ( cc ) ) ;
}
if ( NS_SUCCEEDED ( rv ) & & cc ) {
PRUint32 argc ;
rv = cc - > GetArgc ( & argc ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
jsval * argv ;
rv = cc - > GetArgvPtr ( & argv ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
2006-04-20 07:36:50 +04:00
JSContext * cx ;
rv = cc - > GetJSContext ( & cx ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
2006-04-20 07:37:27 +04:00
nsCOMPtr < nsIScriptSecurityManager > secMan =
do_GetService ( NS_SCRIPTSECURITYMANAGER_CONTRACTID , & rv ) ;
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
2006-04-20 07:37:21 +04:00
2006-04-20 07:37:22 +04:00
nsCOMPtr < nsIPrincipal > principal ;
rv = secMan - > GetSubjectPrincipal ( getter_AddRefs ( principal ) ) ;
if ( NS_SUCCEEDED ( rv ) ) {
nsCOMPtr < nsICodebasePrincipal > codebase = do_QueryInterface ( principal ) ;
if ( codebase ) {
codebase - > GetURI ( getter_AddRefs ( mBaseURI ) ) ;
}
}
2006-04-20 07:37:21 +04:00
nsCOMPtr < nsIURI > targetURI ;
2006-04-20 07:37:22 +04:00
rv = NS_NewURI ( getter_AddRefs ( targetURI ) , url , mBaseURI ) ;
2006-04-20 07:37:21 +04:00
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
rv = secMan - > CheckConnect ( cx , targetURI , " XMLHttpRequest " , " open " ) ;
if ( NS_FAILED ( rv ) )
{
2006-04-20 07:37:30 +04:00
// Security check failed.
2006-04-20 07:37:21 +04:00
return NS_OK ;
}
2006-04-20 07:38:01 +04:00
// Find out if UniversalBrowserRead privileges are enabled
// we will need this in case of a redirect
rv = secMan - > IsCapabilityEnabled ( " UniversalBrowserRead " ,
& mCrossSiteAccessEnabled ) ;
if ( NS_FAILED ( rv ) ) return rv ;
2006-04-20 07:36:50 +04:00
if ( argc > 2 ) {
2006-04-20 07:36:52 +04:00
JSBool asyncBool ;
JS_ValueToBoolean ( cx , argv [ 2 ] , & asyncBool ) ;
async = ( PRBool ) asyncBool ;
2006-04-20 07:36:50 +04:00
if ( argc > 3 ) {
JSString * userStr ;
userStr = JS_ValueToString ( cx , argv [ 3 ] ) ;
if ( userStr ) {
user = JS_GetStringBytes ( userStr ) ;
}
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
2006-04-20 07:36:50 +04:00
if ( argc > 4 ) {
JSString * passwordStr ;
Landing the XPCDOM_20010329_BRANCH branch, changes mostly done by jband@netscape.com and jst@netscape.com, also some changes done by shaver@mozilla.org, peterv@netscape.com and markh@activestate.com. r= and sr= by vidur@netscape.com, jband@netscape.com, jst@netscpae.com, danm@netscape.com, hyatt@netscape.com, shaver@mozilla.org, dbradley@netscape.com, rpotts@netscape.com.
2006-04-20 07:37:17 +04:00
2006-04-20 07:36:50 +04:00
passwordStr = JS_ValueToString ( cx , argv [ 4 ] ) ;
if ( passwordStr ) {
password = JS_GetStringBytes ( passwordStr ) ;
}
}
}
}
}
return OpenRequest ( method , url , async , user , password ) ;
}
nsresult
nsXMLHttpRequest : : GetStreamForWString ( const PRUnichar * aStr ,
PRInt32 aLength ,
nsIInputStream * * aStream )
{
nsresult rv ;
nsCOMPtr < nsIUnicodeEncoder > encoder ;
nsAutoString charsetStr ;
char * postData ;
// We want to encode the string as utf-8, so get the right encoder
2006-04-20 07:37:27 +04:00
nsCOMPtr < nsICharsetConverterManager > charsetConv =
do_GetService ( kCharsetConverterManagerCID , & rv ) ;
2006-04-20 07:36:50 +04:00
NS_ENSURE_SUCCESS ( rv , NS_ERROR_FAILURE ) ;
2006-04-20 07:37:46 +04:00
charsetStr . Assign ( NS_LITERAL_STRING ( " UTF-8 " ) ) ;
2006-04-20 07:36:50 +04:00
rv = charsetConv - > GetUnicodeEncoder ( & charsetStr ,
getter_AddRefs ( encoder ) ) ;
NS_ENSURE_SUCCESS ( rv , NS_ERROR_FAILURE ) ;
// Convert to utf-8
PRInt32 charLength ;
const PRUnichar * unicodeBuf = aStr ;
PRInt32 unicodeLength = aLength ;
rv = encoder - > GetMaxLength ( unicodeBuf , unicodeLength , & charLength ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
2006-04-20 07:37:28 +04:00
// Allocate extra space for the trailing and leading CRLF
postData = ( char * ) nsMemory : : Alloc ( charLength + 5 ) ;
2006-04-20 07:36:50 +04:00
if ( ! postData ) {
return NS_ERROR_OUT_OF_MEMORY ;
}
rv = encoder - > Convert ( unicodeBuf ,
2006-04-20 07:37:28 +04:00
& unicodeLength , postData + 2 , & charLength ) ;
2006-04-20 07:36:50 +04:00
if ( NS_FAILED ( rv ) ) {
nsMemory : : Free ( postData ) ;
return NS_ERROR_FAILURE ;
}
2006-04-20 07:37:29 +04:00
nsCOMPtr < nsIHttpChannel > httpChannel ( do_QueryInterface ( mChannel ) ) ;
if ( ! httpChannel ) {
return NS_ERROR_FAILURE ;
}
2006-04-20 07:37:28 +04:00
// If no content type header was set by the client, we set it to text/xml.
2006-04-20 07:37:53 +04:00
nsCAutoString header ;
if ( NS_FAILED ( httpChannel - > GetRequestHeader ( NS_LITERAL_CSTRING ( " Content-Type " ) , header ) ) )
httpChannel - > SetRequestHeader ( NS_LITERAL_CSTRING ( " Content-Type " ) ,
NS_LITERAL_CSTRING ( " text/xml " ) ) ;
2006-04-20 07:37:28 +04:00
// set the content length header
2006-04-20 07:37:53 +04:00
httpChannel - > SetRequestHeader ( NS_LITERAL_CSTRING ( " Content-Length " ) , nsPrintfCString ( " %d " , charLength ) ) ;
2006-04-20 07:37:28 +04:00
// Shove in the trailing and leading CRLF
postData [ 0 ] = nsCRT : : CR ;
postData [ 1 ] = nsCRT : : LF ;
postData [ 2 + charLength ] = nsCRT : : CR ;
postData [ 2 + charLength + 1 ] = nsCRT : : LF ;
postData [ 2 + charLength + 2 ] = ' \0 ' ;
2006-04-20 07:36:50 +04:00
// The new stream takes ownership of the buffer
rv = NS_NewByteArrayInputStream ( ( nsIByteArrayInputStream * * ) aStream ,
postData ,
2006-04-20 07:37:28 +04:00
charLength + 4 ) ;
2006-04-20 07:36:50 +04:00
if ( NS_FAILED ( rv ) ) {
nsMemory : : Free ( postData ) ;
return NS_ERROR_FAILURE ;
}
return NS_OK ;
}
2006-04-20 07:37:08 +04:00
/*
2006-04-20 07:37:22 +04:00
* " Copy " from a stream .
2006-04-20 07:37:08 +04:00
*/
NS_METHOD
nsXMLHttpRequest : : StreamReaderFunc ( nsIInputStream * in ,
void * closure ,
const char * fromRawSegment ,
PRUint32 toOffset ,
PRUint32 count ,
PRUint32 * writeCount )
{
nsXMLHttpRequest * xmlHttpRequest = NS_STATIC_CAST ( nsXMLHttpRequest * , closure ) ;
2006-04-20 07:37:22 +04:00
if ( ! xmlHttpRequest | | ! writeCount ) {
NS_WARNING ( " XMLHttpRequest cannot read from stream: no closure or writeCount " ) ;
2006-04-20 07:37:08 +04:00
return NS_ERROR_FAILURE ;
}
// Copy for our own use
2006-04-20 07:37:22 +04:00
xmlHttpRequest - > mResponseBody . Append ( fromRawSegment , count ) ;
2006-04-20 07:37:08 +04:00
2006-04-20 07:37:59 +04:00
nsresult rv = NS_OK ;
2006-04-20 07:37:22 +04:00
2006-04-20 07:37:59 +04:00
if ( xmlHttpRequest - > mParseResponseBody ) {
// Give the same data to the parser.
2006-04-20 07:37:22 +04:00
2006-04-20 07:37:59 +04:00
// We need to wrap the data in a new lightweight stream and pass that
// to the parser, because calling ReadSegments() recursively on the same
// stream is not supported.
nsCOMPtr < nsISupports > supportsStream ;
rv = NS_NewByteInputStream ( getter_AddRefs ( supportsStream ) , fromRawSegment , count ) ;
2006-04-20 07:37:22 +04:00
2006-04-20 07:37:59 +04:00
if ( NS_SUCCEEDED ( rv ) ) {
nsCOMPtr < nsIInputStream > copyStream ( do_QueryInterface ( supportsStream ) ) ;
if ( copyStream ) {
rv = xmlHttpRequest - > mXMLParserStreamListener - > OnDataAvailable ( xmlHttpRequest - > mReadRequest , xmlHttpRequest - > mContext , copyStream , toOffset , count ) ;
} else {
NS_ERROR ( " NS_NewByteInputStream did not give out nsIInputStream! " ) ;
rv = NS_ERROR_UNEXPECTED ;
}
2006-04-20 07:37:22 +04:00
}
}
2006-04-20 07:37:08 +04:00
2006-04-20 07:37:31 +04:00
xmlHttpRequest - > ChangeState ( XML_HTTP_REQUEST_INTERACTIVE ) ;
2006-04-20 07:37:22 +04:00
if ( NS_SUCCEEDED ( rv ) ) {
* writeCount = count ;
} else {
* writeCount = 0 ;
}
2006-04-20 07:37:08 +04:00
return rv ;
}
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */
NS_IMETHODIMP
nsXMLHttpRequest : : OnDataAvailable ( nsIRequest * request , nsISupports * ctxt , nsIInputStream * inStr , PRUint32 sourceOffset , PRUint32 count )
{
2006-04-20 07:37:22 +04:00
NS_ENSURE_ARG_POINTER ( inStr ) ;
2006-04-20 07:37:08 +04:00
NS_ABORT_IF_FALSE ( mContext . get ( ) = = ctxt , " start context different from OnDataAvailable context " ) ;
PRUint32 totalRead ;
2006-04-20 07:37:36 +04:00
return inStr - > ReadSegments ( nsXMLHttpRequest : : StreamReaderFunc , ( void * ) this , count , & totalRead ) ;
2006-04-20 07:37:08 +04:00
}
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP
nsXMLHttpRequest : : OnStartRequest ( nsIRequest * request , nsISupports * ctxt )
{
mReadRequest = request ;
mContext = ctxt ;
2006-04-20 07:37:59 +04:00
mParseResponseBody = PR_TRUE ;
2006-04-20 07:37:31 +04:00
ChangeState ( XML_HTTP_REQUEST_LOADED ) ;
2006-04-20 07:37:59 +04:00
if ( mOverrideMimeType . IsEmpty ( ) ) {
// If we are not overriding the mime type, we can gain a huge performance
// win by not even trying to parse non-XML data. This also protects us
// from the situation where we have an XML document and sink, but HTML (or other)
// parser, which can produce unreliable results.
nsCAutoString type ;
mChannel - > GetContentType ( type ) ;
nsACString : : const_iterator start , end ;
type . BeginReading ( start ) ;
type . EndReading ( end ) ;
if ( ! FindInReadable ( NS_LITERAL_CSTRING ( " xml " ) , start , end ) ) {
mParseResponseBody = PR_FALSE ;
}
} else {
2006-04-20 07:37:48 +04:00
nsresult status ;
request - > GetStatus ( & status ) ;
nsCOMPtr < nsIChannel > channel = do_QueryInterface ( request ) ;
if ( channel & & NS_SUCCEEDED ( status ) ) {
2006-04-20 07:37:53 +04:00
channel - > SetContentType ( mOverrideMimeType ) ;
2006-04-20 07:37:48 +04:00
}
}
2006-04-20 07:37:59 +04:00
return mParseResponseBody ? mXMLParserStreamListener - > OnStartRequest ( request , ctxt ) : NS_OK ;
2006-04-20 07:37:08 +04:00
}
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status, in wstring statusArg); */
NS_IMETHODIMP
2006-04-20 07:37:13 +04:00
nsXMLHttpRequest : : OnStopRequest ( nsIRequest * request , nsISupports * ctxt , nsresult status )
2006-04-20 07:37:08 +04:00
{
2006-04-20 07:37:35 +04:00
nsCOMPtr < nsIParser > parser ( do_QueryInterface ( mXMLParserStreamListener ) ) ;
NS_ABORT_IF_FALSE ( parser , " stream listener was expected to be a parser " ) ;
2006-04-20 07:37:59 +04:00
nsresult rv = mParseResponseBody ? mXMLParserStreamListener - > OnStopRequest ( request , ctxt , status ) : NS_OK ;
2006-04-20 07:37:08 +04:00
mXMLParserStreamListener = nsnull ;
mReadRequest = nsnull ;
mContext = nsnull ;
2006-04-20 07:37:31 +04:00
2006-04-20 07:37:35 +04:00
// The parser needs to be enabled for us to safely call RequestCompleted().
// If the parser is not enabled, it means it was blocked, by xml-stylesheet PI
// for example, and is still building the document. RequestCompleted() must be
// called later, when we get the load event from the document.
if ( parser & & parser - > IsParserEnabled ( ) ) {
RequestCompleted ( ) ;
} else {
ChangeState ( XML_HTTP_REQUEST_STOPPED , PR_FALSE ) ;
}
2006-04-20 07:37:31 +04:00
return rv ;
}
nsresult
nsXMLHttpRequest : : RequestCompleted ( )
{
nsresult rv = NS_OK ;
2006-04-20 07:37:34 +04:00
// If we're uninitialized at this point, we encountered an error
2006-04-20 07:37:35 +04:00
// earlier and listeners have already been notified. Also we do
// not want to do this if we already completed.
if ( ( mStatus = = XML_HTTP_REQUEST_UNINITIALIZED ) | |
( mStatus = = XML_HTTP_REQUEST_COMPLETED ) ) {
2006-04-20 07:37:34 +04:00
return NS_OK ;
}
nsCOMPtr < nsIDOMEvent > domevent ;
nsCOMPtr < nsIDOMEventReceiver > receiver ( do_QueryInterface ( mDocument ) ) ;
if ( ! receiver ) {
return NS_ERROR_FAILURE ;
}
nsCOMPtr < nsIEventListenerManager > manager ;
rv = receiver - > GetListenerManager ( getter_AddRefs ( manager ) ) ;
if ( ! manager ) {
return NS_ERROR_FAILURE ;
}
nsEvent event ;
event . eventStructType = NS_EVENT ;
event . message = NS_PAGE_LOAD ;
rv = manager - > CreateEvent ( nsnull , & event ,
NS_LITERAL_STRING ( " HTMLEvents " ) ,
getter_AddRefs ( domevent ) ) ;
if ( NS_FAILED ( rv ) ) {
return rv ;
}
nsCOMPtr < nsIPrivateDOMEvent > privevent ( do_QueryInterface ( domevent ) ) ;
if ( ! privevent ) {
return NS_ERROR_FAILURE ;
}
privevent - > SetTarget ( this ) ;
2006-04-20 07:37:31 +04:00
// 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 ) ;
}
}
}
2006-04-20 07:37:34 +04:00
if ( mOnLoadListener ) {
mOnLoadListener - > HandleEvent ( domevent ) ;
2006-04-20 07:37:31 +04:00
}
2006-04-20 07:37:34 +04:00
if ( mLoadEventListeners ) {
2006-04-20 07:37:31 +04:00
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 ) {
2006-04-20 07:37:34 +04:00
listener - > HandleEvent ( domevent ) ;
2006-04-20 07:37:31 +04:00
}
}
}
if ( cx ) {
stack - > Pop ( & cx ) ;
}
2006-04-20 07:37:08 +04:00
return rv ;
}
2006-04-20 07:37:45 +04:00
/* void send (in nsIVariant aBody); */
2006-04-20 07:36:50 +04:00
NS_IMETHODIMP
2006-04-20 07:37:45 +04:00
nsXMLHttpRequest : : Send ( nsIVariant * aBody )
2006-04-20 07:36:50 +04:00
{
nsresult rv ;
2006-04-20 07:37:28 +04:00
2006-04-20 07:37:08 +04:00
// Return error if we're already processing a request
2006-04-20 07:36:54 +04:00
if ( XML_HTTP_REQUEST_SENT = = mStatus ) {
return NS_ERROR_FAILURE ;
}
// Make sure we've been opened
2006-04-20 07:37:31 +04:00
if ( ! mChannel | | XML_HTTP_REQUEST_OPENED ! = mStatus ) {
2006-04-20 07:36:50 +04:00
return NS_ERROR_NOT_INITIALIZED ;
}
2006-04-20 07:37:22 +04:00
// Ignore argument if method is GET, there is no point in trying to upload anything
2006-04-20 07:37:53 +04:00
nsCAutoString method ;
2006-04-20 07:37:29 +04:00
nsCOMPtr < nsIHttpChannel > httpChannel ( do_QueryInterface ( mChannel ) ) ;
if ( httpChannel ) {
2006-04-20 07:37:53 +04:00
httpChannel - > GetRequestMethod ( method ) ; // If GET, method name will be uppercase
2006-04-20 07:37:29 +04:00
}
2006-04-20 07:37:22 +04:00
2006-04-20 07:37:53 +04:00
if ( aBody & & httpChannel & & ! method . Equals ( NS_LITERAL_CSTRING ( " GET " ) ) ) {
2006-04-20 07:37:45 +04:00
nsXPIDLString serial ;
2006-04-20 07:37:22 +04:00
nsCOMPtr < nsIInputStream > postDataStream ;
2006-04-20 07:37:45 +04:00
PRUint16 dataType ;
rv = aBody - > GetDataType ( & dataType ) ;
if ( NS_FAILED ( rv ) )
return NS_ERROR_FAILURE ;
2006-04-20 07:37:58 +04:00
switch ( dataType ) {
case nsIDataType : : VTYPE_INTERFACE :
case nsIDataType : : VTYPE_INTERFACE_IS :
{
nsCOMPtr < nsISupports > supports ;
nsID * iid ;
rv = aBody - > GetAsInterface ( & iid , getter_AddRefs ( supports ) ) ;
2006-04-20 07:37:45 +04:00
if ( NS_FAILED ( rv ) )
return NS_ERROR_FAILURE ;
2006-04-20 07:37:58 +04:00
if ( iid )
nsMemory : : Free ( iid ) ;
// document?
nsCOMPtr < nsIDOMDocument > doc ( do_QueryInterface ( supports ) ) ;
if ( doc ) {
nsCOMPtr < nsIDOMSerializer > serializer ( do_CreateInstance ( NS_XMLSERIALIZER_CONTRACTID , & rv ) ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
rv = serializer - > SerializeToString ( doc , getter_Copies ( serial ) ) ;
if ( NS_FAILED ( rv ) )
return NS_ERROR_FAILURE ;
2006-04-20 07:37:45 +04:00
} else {
2006-04-20 07:38:05 +04:00
// nsISupportsString?
nsCOMPtr < nsISupportsString > wstr ( do_QueryInterface ( supports ) ) ;
2006-04-20 07:37:58 +04:00
if ( wstr ) {
wstr - > GetData ( getter_Copies ( serial ) ) ;
} else {
// stream?
nsCOMPtr < nsIInputStream > stream ( do_QueryInterface ( supports ) ) ;
if ( stream ) {
postDataStream = stream ;
}
2006-04-20 07:37:45 +04:00
}
}
}
2006-04-20 07:37:59 +04:00
break ;
2006-04-20 07:37:58 +04:00
case nsIDataType : : VTYPE_VOID :
case nsIDataType : : VTYPE_EMPTY :
// Makes us act as if !aBody, don't upload anything
break ;
case nsIDataType : : VTYPE_EMPTY_ARRAY :
case nsIDataType : : VTYPE_ARRAY :
// IE6 throws error here, so we do that as well
return NS_ERROR_INVALID_ARG ;
default :
2006-04-20 07:37:45 +04:00
// try variant string
rv = aBody - > GetAsWString ( getter_Copies ( serial ) ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2006-04-20 07:37:58 +04:00
break ;
2006-04-20 07:37:45 +04:00
}
if ( serial ) {
2006-04-20 07:36:51 +04:00
// Convert to a byte stream
2006-04-20 07:37:22 +04:00
rv = GetStreamForWString ( serial . get ( ) ,
nsCRT : : strlen ( serial . get ( ) ) ,
2006-04-20 07:36:51 +04:00
getter_AddRefs ( postDataStream ) ) ;
2006-04-20 07:37:45 +04:00
if ( NS_FAILED ( rv ) )
return rv ;
2006-04-20 07:36:50 +04:00
}
2006-04-20 07:36:51 +04:00
if ( postDataStream ) {
2006-04-20 07:37:32 +04:00
nsCOMPtr < nsIUploadChannel > uploadChannel ( do_QueryInterface ( httpChannel ) ) ;
NS_ASSERTION ( uploadChannel , " http must support nsIUploadChannel " ) ;
rv = uploadChannel - > SetUploadStream ( postDataStream , nsnull , - 1 ) ;
2006-04-20 07:37:49 +04:00
// Reset the method to its original value
if ( httpChannel ) {
httpChannel - > SetRequestMethod ( method ) ;
}
2006-04-20 07:36:51 +04:00
}
2006-04-20 07:36:50 +04:00
}
// Get and initialize a DOMImplementation
2006-04-20 07:37:08 +04:00
nsCOMPtr < nsIDOMDOMImplementation > implementation ( do_CreateInstance ( kIDOMDOMImplementationCID , & rv ) ) ;
2006-04-20 07:36:50 +04:00
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
2006-04-20 07:36:51 +04:00
if ( mBaseURI ) {
2006-04-20 07:37:08 +04:00
nsCOMPtr < nsIPrivateDOMImplementation > privImpl ( do_QueryInterface ( implementation ) ) ;
2006-04-20 07:36:50 +04:00
if ( privImpl ) {
2006-04-20 07:36:51 +04:00
privImpl - > Init ( mBaseURI ) ;
2006-04-20 07:36:50 +04:00
}
}
2006-04-20 07:37:08 +04:00
// Create an empty document from it (resets current document as well)
2006-04-20 07:36:50 +04:00
nsAutoString emptyStr ;
rv = implementation - > CreateDocument ( emptyStr ,
emptyStr ,
nsnull ,
getter_AddRefs ( mDocument ) ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
2006-04-20 07:37:08 +04:00
// Reset responseBody
mResponseBody . Truncate ( ) ;
2006-04-20 07:36:50 +04:00
// Register as a load listener on the document
2006-04-20 07:37:08 +04:00
nsCOMPtr < nsIDOMEventReceiver > target ( do_QueryInterface ( mDocument ) ) ;
2006-04-20 07:36:50 +04:00
if ( target ) {
2006-04-20 07:37:08 +04:00
nsWeakPtr requestWeak ( getter_AddRefs ( NS_GetWeakReference ( NS_STATIC_CAST ( nsIXMLHttpRequest * , this ) ) ) ) ;
2006-04-20 07:36:56 +04:00
nsLoadListenerProxy * proxy = new nsLoadListenerProxy ( requestWeak ) ;
2006-04-20 07:36:54 +04:00
if ( ! proxy ) return NS_ERROR_OUT_OF_MEMORY ;
// This will addref the proxy
rv = target - > AddEventListenerByIID ( NS_STATIC_CAST ( nsIDOMEventListener * ,
proxy ) ,
NS_GET_IID ( nsIDOMLoadListener ) ) ;
2006-04-20 07:36:50 +04:00
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
}
// Tell the document to start loading
nsCOMPtr < nsIStreamListener > listener ;
2006-04-20 07:37:08 +04:00
nsCOMPtr < nsIDocument > document ( do_QueryInterface ( mDocument ) ) ;
2006-04-20 07:36:50 +04:00
if ( ! document ) {
return NS_ERROR_FAILURE ;
}
2006-04-20 07:36:54 +04:00
# ifdef IMPLEMENT_SYNC_LOAD
nsCOMPtr < nsIEventQueue > modalEventQueue ;
nsCOMPtr < nsIEventQueueService > eventQService ;
if ( ! mAsync ) {
nsCOMPtr < nsIXPCNativeCallContext > cc ;
2006-04-20 07:37:27 +04:00
nsCOMPtr < nsIXPConnect > xpc ( do_GetService ( nsIXPConnect : : GetCID ( ) , & rv ) ) ;
2006-04-20 07:36:54 +04:00
if ( NS_SUCCEEDED ( rv ) ) {
rv = xpc - > GetCurrentNativeCallContext ( getter_AddRefs ( cc ) ) ;
}
if ( NS_SUCCEEDED ( rv ) & & cc ) {
JSContext * cx ;
rv = cc - > GetJSContext ( & cx ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
// We can only do this if we're called from a DOM script context
nsIScriptContext * scriptCX = ( nsIScriptContext * ) JS_GetContextPrivate ( cx ) ;
if ( ! scriptCX ) return NS_OK ;
// Get the nsIDocShellTreeOwner associated with the window
// containing this script context
// XXX Need to find a better way to do this rather than
// chaining through a bunch of getters and QIs
nsCOMPtr < nsIScriptGlobalObject > global ;
2006-04-20 07:37:24 +04:00
scriptCX - > GetGlobalObject ( getter_AddRefs ( global ) ) ;
2006-04-20 07:36:54 +04:00
if ( ! global ) return NS_ERROR_FAILURE ;
nsCOMPtr < nsIDocShell > docshell ;
rv = global - > GetDocShell ( getter_AddRefs ( docshell ) ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
nsCOMPtr < nsIDocShellTreeItem > item = do_QueryInterface ( docshell ) ;
if ( ! item ) return NS_ERROR_FAILURE ;
2006-04-20 07:37:11 +04:00
nsCOMPtr < nsIDocShellTreeOwner > treeOwner ;
rv = item - > GetTreeOwner ( getter_AddRefs ( treeOwner ) ) ;
2006-04-20 07:36:54 +04:00
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
2006-04-20 07:37:11 +04:00
nsCOMPtr < nsIInterfaceRequestor > treeRequestor ( do_GetInterface ( treeOwner ) ) ;
if ( ! treeRequestor ) return NS_ERROR_FAILURE ;
treeRequestor - > GetInterface ( NS_GET_IID ( nsIWebBrowserChrome ) , getter_AddRefs ( mChromeWindow ) ) ;
if ( ! mChromeWindow ) return NS_ERROR_FAILURE ;
2006-04-20 07:36:54 +04:00
eventQService = do_GetService ( kEventQueueServiceCID ) ;
if ( ! eventQService | |
NS_FAILED ( eventQService - > PushThreadEventQueue ( getter_AddRefs ( modalEventQueue ) ) ) ) {
return NS_ERROR_FAILURE ;
}
}
}
# endif
2006-04-20 07:38:01 +04:00
if ( ! mScriptContext ) {
// We need a context to check if redirect (if any) is allowed
GetCurrentContext ( getter_AddRefs ( mScriptContext ) ) ;
}
2006-04-20 07:36:50 +04:00
rv = document - > StartDocumentLoad ( kLoadAsData , mChannel ,
nsnull , nsnull ,
getter_AddRefs ( listener ) ,
PR_FALSE ) ;
2006-04-20 07:36:54 +04:00
# ifdef IMPLEMENT_SYNC_LOAD
if ( NS_FAILED ( rv ) ) {
if ( modalEventQueue ) {
eventQService - > PopThreadEventQueue ( modalEventQueue ) ;
}
return NS_ERROR_FAILURE ;
}
# else
2006-04-20 07:36:50 +04:00
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
2006-04-20 07:36:54 +04:00
# endif
2006-04-20 07:36:50 +04:00
2006-04-20 07:38:01 +04:00
// Hook us up to listen to redirects and the like
mChannel - > SetNotificationCallbacks ( this ) ;
2006-04-20 07:36:50 +04:00
// Start reading from the channel
2006-04-20 07:37:31 +04:00
ChangeState ( XML_HTTP_REQUEST_SENT ) ;
2006-04-20 07:37:08 +04:00
mXMLParserStreamListener = listener ;
rv = mChannel - > AsyncOpen ( this , nsnull ) ;
2006-04-20 07:36:54 +04:00
# ifdef IMPLEMENT_SYNC_LOAD
if ( NS_FAILED ( rv ) ) {
if ( modalEventQueue ) {
eventQService - > PopThreadEventQueue ( modalEventQueue ) ;
}
return NS_ERROR_FAILURE ;
}
# else
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
# endif
# ifdef IMPLEMENT_SYNC_LOAD
// If we're synchronous, spin an event loop here and wait
2006-04-20 07:37:11 +04:00
if ( ! mAsync & & mChromeWindow ) {
rv = mChromeWindow - > ShowAsModal ( ) ;
2006-04-20 07:36:54 +04:00
eventQService - > PopThreadEventQueue ( modalEventQueue ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
2006-04-20 07:36:50 +04:00
}
2006-04-20 07:36:54 +04:00
# endif
2006-04-20 07:36:50 +04:00
2006-04-20 07:36:54 +04:00
return NS_OK ;
2006-04-20 07:36:50 +04:00
}
/* void setRequestHeader (in string header, in string value); */
NS_IMETHODIMP
nsXMLHttpRequest : : SetRequestHeader ( const char * header , const char * value )
{
2006-04-20 07:37:31 +04:00
if ( ! mChannel ) // open() initializes mChannel, and open()
return NS_ERROR_FAILURE ; // must be called before first setRequestHeader()
2006-04-20 07:37:29 +04:00
nsCOMPtr < nsIHttpChannel > httpChannel ( do_QueryInterface ( mChannel ) ) ;
if ( httpChannel )
2006-04-20 07:37:53 +04:00
return httpChannel - > SetRequestHeader ( nsDependentCString ( header ) ,
nsDependentCString ( value ) ) ;
2006-04-20 07:36:50 +04:00
return NS_OK ;
}
2006-04-20 07:37:31 +04:00
/* readonly attribute long readyState; */
NS_IMETHODIMP
nsXMLHttpRequest : : GetReadyState ( PRInt32 * aState )
{
NS_ENSURE_ARG_POINTER ( aState ) ;
2006-04-20 07:37:35 +04:00
// Translate some of our internal states for external consumers
switch ( mStatus ) {
case XML_HTTP_REQUEST_SENT :
* aState = XML_HTTP_REQUEST_OPENED ;
break ;
case XML_HTTP_REQUEST_STOPPED :
* aState = XML_HTTP_REQUEST_INTERACTIVE ;
break ;
default :
* aState = mStatus ;
break ;
2006-04-20 07:37:31 +04:00
}
return NS_OK ;
}
2006-04-20 07:37:48 +04:00
/* void overrideMimeType(in string mimetype); */
NS_IMETHODIMP
nsXMLHttpRequest : : OverrideMimeType ( const char * aMimeType )
{
// XXX Should we do some validation here?
mOverrideMimeType . Assign ( aMimeType ) ;
return NS_OK ;
}
2006-04-20 07:36:50 +04:00
// nsIDOMEventListener
nsresult
nsXMLHttpRequest : : HandleEvent ( nsIDOMEvent * aEvent )
{
return NS_OK ;
}
// nsIDOMLoadListener
nsresult
nsXMLHttpRequest : : Load ( nsIDOMEvent * aEvent )
{
2006-04-20 07:37:31 +04:00
// 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.
2006-04-20 07:37:35 +04:00
//
// However, if the data we were loading caused the parser to stop,
// for example when loading external stylesheets, we can receive
// the OnStopRequest() call before the parser has finished building
// the document. In that case, we obviously should not fire the event
// in OnStopRequest(). For those documents, we must wait for the load
// event from the document to fire our RequestCompleted().
if ( mStatus = = XML_HTTP_REQUEST_STOPPED ) {
RequestCompleted ( ) ;
}
2006-04-20 07:36:50 +04:00
return NS_OK ;
}
nsresult
nsXMLHttpRequest : : Unload ( nsIDOMEvent * aEvent )
{
return NS_OK ;
}
nsresult
nsXMLHttpRequest : : Abort ( nsIDOMEvent * aEvent )
{
2006-04-20 07:37:51 +04:00
if ( mReadRequest ) {
mReadRequest - > Cancel ( NS_BINDING_ABORTED ) ;
}
if ( mChannel ) {
mChannel - > Cancel ( NS_BINDING_ABORTED ) ;
}
2006-04-20 07:37:25 +04:00
mDocument = nsnull ;
2006-04-20 07:37:31 +04:00
ChangeState ( XML_HTTP_REQUEST_UNINITIALIZED ) ;
2006-04-20 07:36:54 +04:00
# ifdef IMPLEMENT_SYNC_LOAD
2006-04-20 07:37:11 +04:00
if ( mChromeWindow ) {
mChromeWindow - > ExitModalEventLoop ( NS_OK ) ;
mChromeWindow = 0 ;
2006-04-20 07:36:54 +04:00
}
# endif
2006-04-20 07:36:50 +04:00
return NS_OK ;
}
nsresult
nsXMLHttpRequest : : Error ( nsIDOMEvent * aEvent )
{
2006-04-20 07:37:25 +04:00
mDocument = nsnull ;
2006-04-20 07:37:31 +04:00
ChangeState ( XML_HTTP_REQUEST_UNINITIALIZED ) ;
2006-04-20 07:36:54 +04:00
# ifdef IMPLEMENT_SYNC_LOAD
2006-04-20 07:37:11 +04:00
if ( mChromeWindow ) {
mChromeWindow - > ExitModalEventLoop ( NS_OK ) ;
mChromeWindow = 0 ;
2006-04-20 07:36:54 +04:00
}
# endif
2006-04-20 07:36:50 +04:00
2006-04-20 07:37:23 +04:00
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 ) ;
2006-04-20 07:36:50 +04:00
}
}
}
2006-04-20 07:37:23 +04:00
if ( mOnErrorListener ) {
mOnErrorListener - > HandleEvent ( aEvent ) ;
2006-04-20 07:36:53 +04:00
}
2006-04-20 07:37:23 +04:00
if ( mErrorEventListeners ) {
PRUint32 index , count ;
2006-04-20 07:36:53 +04:00
2006-04-20 07:37:23 +04:00
mErrorEventListeners - > Count ( & count ) ;
for ( index = 0 ; index < count ; index + + ) {
nsCOMPtr < nsIDOMEventListener > listener ;
2006-04-20 07:36:53 +04:00
2006-04-20 07:37:23 +04:00
mErrorEventListeners - > QueryElementAt ( index ,
NS_GET_IID ( nsIDOMEventListener ) ,
getter_AddRefs ( listener ) ) ;
2006-04-20 07:36:53 +04:00
2006-04-20 07:37:23 +04:00
if ( listener ) {
listener - > HandleEvent ( aEvent ) ;
}
}
2006-04-20 07:36:53 +04:00
}
2006-04-20 07:37:23 +04:00
if ( cx ) {
stack - > Pop ( & cx ) ;
2006-04-20 07:36:53 +04:00
}
return NS_OK ;
}
2006-04-20 07:37:18 +04:00
2006-04-20 07:37:31 +04:00
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 ;
}
2006-04-20 07:38:01 +04:00
/////////////////////////////////////////////////////
// nsIHttpEventSink methods:
//
NS_IMETHODIMP
nsXMLHttpRequest : : OnRedirect ( nsIHttpChannel * aHttpChannel , nsIChannel * aNewChannel )
{
NS_ENSURE_ARG_POINTER ( aNewChannel ) ;
if ( mScriptContext & & ! mCrossSiteAccessEnabled ) {
nsresult rv = NS_ERROR_FAILURE ;
nsCOMPtr < nsIJSContextStack > stack ( do_GetService ( " @mozilla.org/js/xpc/ContextStack;1 " , & rv ) ) ;
if ( NS_FAILED ( rv ) )
return rv ;
JSContext * cx = ( JSContext * ) mScriptContext - > GetNativeContext ( ) ;
if ( ! cx )
return NS_ERROR_UNEXPECTED ;
nsCOMPtr < nsIScriptSecurityManager > secMan =
do_GetService ( NS_SCRIPTSECURITYMANAGER_CONTRACTID , & rv ) ;
if ( NS_FAILED ( rv ) )
return rv ;
nsCOMPtr < nsIURI > newURI ;
rv = aNewChannel - > GetURI ( getter_AddRefs ( newURI ) ) ; // The redirected URI
if ( NS_FAILED ( rv ) )
return rv ;
stack - > Push ( cx ) ;
rv = secMan - > CheckSameOrigin ( cx , newURI ) ;
stack - > Pop ( & cx ) ;
if ( NS_FAILED ( rv ) )
return rv ;
}
mChannel = aNewChannel ;
return NS_OK ;
}
/////////////////////////////////////////////////////
// nsIInterfaceRequestor methods:
//
NS_IMETHODIMP
nsXMLHttpRequest : : GetInterface ( const nsIID & aIID , void * * aResult )
{
if ( aIID . Equals ( NS_GET_IID ( nsIAuthPrompt ) ) ) {
NS_ENSURE_ARG_POINTER ( aResult ) ;
* aResult = nsnull ;
nsresult rv ;
2006-04-20 07:38:06 +04:00
nsCOMPtr < nsIWindowWatcher > ww ( do_GetService ( NS_WINDOWWATCHER_CONTRACTID , & rv ) ) ;
2006-04-20 07:38:01 +04:00
if ( NS_FAILED ( rv ) )
return rv ;
nsCOMPtr < nsIAuthPrompt > prompt ;
rv = ww - > GetNewAuthPrompter ( nsnull , getter_AddRefs ( prompt ) ) ;
if ( NS_FAILED ( rv ) )
return rv ;
nsIAuthPrompt * p = prompt . get ( ) ;
NS_ADDREF ( p ) ;
* aResult = p ;
return NS_OK ;
}
return QueryInterface ( aIID , aResult ) ;
}
2006-04-20 07:37:18 +04:00
NS_IMPL_ISUPPORTS1 ( nsXMLHttpRequest : : nsHeaderVisitor , nsIHttpHeaderVisitor )
NS_IMETHODIMP nsXMLHttpRequest : :
2006-04-20 07:37:53 +04:00
nsHeaderVisitor : : VisitHeader ( const nsACString & header , const nsACString & value )
2006-04-20 07:37:18 +04:00
{
mHeaders . Append ( header ) ;
mHeaders . Append ( " : " ) ;
mHeaders . Append ( value ) ;
mHeaders . Append ( ' \n ' ) ;
return NS_OK ;
}
2006-04-20 07:37:31 +04:00