2001-09-25 22:43:09 +00:00
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version : NPL 1.1 / GPL 2.0 / LGPL 2.1
1999-07-12 23:46:40 +00:00
*
2001-09-25 22:43:09 +00: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/
1999-07-12 23:46:40 +00:00
*
2001-09-25 22:43:09 +00: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 .
1999-07-12 23:46:40 +00:00
*
1999-11-06 03:40:37 +00:00
* The Original Code is mozilla . org code .
*
2001-09-25 22:43:09 +00: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 .
1999-11-06 03:40:37 +00:00
*
2000-06-14 04:57:49 +00:00
* Contributor ( s ) :
2000-01-11 20:49:15 +00:00
* Pierre Phaneuf < pp @ ludusdesign . com >
2001-09-25 22:43:09 +00:00
*
*
* 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 * * * * * */
1999-10-13 07:17:36 +00:00
# include "nsCOMPtr.h"
2003-05-15 01:23:26 +00:00
# include "nsAutoPtr.h"
1999-10-13 07:17:36 +00:00
# include "jsapi.h"
1999-07-12 23:46:40 +00:00
# include "nsCRT.h"
2001-06-29 00:40:45 +00:00
# include "nsDOMError.h"
# include "nsXPIDLString.h"
2001-09-29 08:28:41 +00:00
# include "nsReadableUtils.h"
2001-06-29 00:40:45 +00:00
# include "nsJSProtocolHandler.h"
# include "nsNetUtil.h"
1999-07-12 23:46:40 +00:00
# include "nsIComponentManager.h"
1999-08-26 22:45:55 +00:00
# include "nsIGenericFactory.h"
1999-07-12 23:46:40 +00:00
# include "nsIServiceManager.h"
# include "nsIURI.h"
# include "nsIScriptContext.h"
1999-10-20 00:12:04 +00:00
# include "nsIScriptGlobalObject.h"
1999-12-03 19:02:31 +00:00
# include "nsIScriptGlobalObjectOwner.h"
1999-09-15 20:58:41 +00:00
# include "nsIPrincipal.h"
# include "nsIScriptSecurityManager.h"
1999-11-18 07:36:41 +00:00
# include "nsIInterfaceRequestor.h"
2001-09-05 21:28:38 +00:00
# include "nsIInterfaceRequestorUtils.h"
2003-01-18 02:15:14 +00:00
# include "nsIStringStream.h"
2000-06-14 04:57:49 +00:00
# include "nsIWindowMediator.h"
2000-09-01 01:54:35 +00:00
# include "nsIDOMWindowInternal.h"
2002-06-27 18:07:32 +00:00
# include "nsIDOMDocument.h"
2001-05-11 01:52:11 +00:00
# include "nsIJSConsoleService.h"
2001-07-13 07:08:26 +00:00
# include "nsIConsoleService.h"
2001-08-31 21:01:10 +00:00
# include "nsXPIDLString.h"
2002-03-06 07:48:55 +00:00
# include "prprf.h"
2002-03-22 21:41:06 +00:00
# include "nsEscape.h"
2003-05-12 22:23:52 +00:00
# include "nsIJSContextStack.h"
2003-05-15 01:23:26 +00:00
# include "nsIWebNavigation.h"
1999-07-12 23:46:40 +00:00
static NS_DEFINE_CID ( kSimpleURICID , NS_SIMPLEURI_CID ) ;
2000-06-14 04:57:49 +00:00
static NS_DEFINE_CID ( kWindowMediatorCID , NS_WINDOWMEDIATOR_CID ) ;
2000-03-29 03:58:50 +00:00
2000-06-14 04:57:49 +00:00
2003-01-18 02:15:14 +00:00
class nsJSThunk : public nsIInputStream
2001-06-29 00:40:45 +00:00
{
2000-03-29 03:58:50 +00:00
public :
2001-06-29 00:40:45 +00:00
nsJSThunk ( ) ;
(13163, r=alecf, scc, waterson, others; names available on request)
- Fix most of bug 13163 (see TODO for rest). This entails adding a version-string argument to nsIScriptContext::EvaluateString and passing it around lots of places in content sinks.
- Fix leaks and confusion about mSecurityManager and mNameSpaceManager in nsJSEnvironment.cpp. These still need to move from nsJSContext to nsGlobalWindow or thereabouts, jband and vidur are looking at that.
- Added comments and expanded tabs in nsJSEnvironment.cpp, esp. to EvaluateString. Also changed various nsresult vars to be named rv. Also restored brace/style conformity to nsJSProtocolHandler.cpp.
- Factored CompileFunction from AddScriptEventListener to pave the way for brutal sharing of compiled JS event handlers via JS_CloneFunctionObject.
- Lots of nsCOMPtr uses added. I'm using one for mNameSpaceManager. Hold mSecurityManager as a service explicitly, on the other hand (awaiting scc's fix to allow comptrs for services), and release in nsJSContext's dtor (fixing a leak). These two managers should be moved to the window object -- TODO item below.
- Hold JSRuntimeService along with JSRuntime for live of nsJSEnvironment, fix for shaver.
- Fix window.setTimeout etc. so the filename and line number of the timeout expr is propagated. This meant factoring nsJSUtils.cpp code.
- Fix all content sinks to use the same, and up-to-date JavaScript version parsing (whether for script type or for old language attribute); also fix SplitMimeType clones to strip whitespace.
- With waterson, fix bug in brutal-sharing version of XUL content sink: script src= should not evaluate the inline content of its tag.
1999-10-31 00:43:30 +00:00
NS_DECL_ISUPPORTS
2003-01-18 02:15:14 +00:00
NS_FORWARD_SAFE_NSIINPUTSTREAM ( mInnerStream )
2001-06-29 00:40:45 +00:00
2002-08-21 23:01:23 +00:00
nsresult Init ( nsIURI * uri ) ;
nsresult EvaluateScript ( nsIChannel * aChannel ) ;
nsresult BringUpConsole ( nsIDOMWindow * aDomWindow ) ;
(13163, r=alecf, scc, waterson, others; names available on request)
- Fix most of bug 13163 (see TODO for rest). This entails adding a version-string argument to nsIScriptContext::EvaluateString and passing it around lots of places in content sinks.
- Fix leaks and confusion about mSecurityManager and mNameSpaceManager in nsJSEnvironment.cpp. These still need to move from nsJSContext to nsGlobalWindow or thereabouts, jband and vidur are looking at that.
- Added comments and expanded tabs in nsJSEnvironment.cpp, esp. to EvaluateString. Also changed various nsresult vars to be named rv. Also restored brace/style conformity to nsJSProtocolHandler.cpp.
- Factored CompileFunction from AddScriptEventListener to pave the way for brutal sharing of compiled JS event handlers via JS_CloneFunctionObject.
- Lots of nsCOMPtr uses added. I'm using one for mNameSpaceManager. Hold mSecurityManager as a service explicitly, on the other hand (awaiting scc's fix to allow comptrs for services), and release in nsJSContext's dtor (fixing a leak). These two managers should be moved to the window object -- TODO item below.
- Hold JSRuntimeService along with JSRuntime for live of nsJSEnvironment, fix for shaver.
- Fix window.setTimeout etc. so the filename and line number of the timeout expr is propagated. This meant factoring nsJSUtils.cpp code.
- Fix all content sinks to use the same, and up-to-date JavaScript version parsing (whether for script type or for old language attribute); also fix SplitMimeType clones to strip whitespace.
- With waterson, fix bug in brutal-sharing version of XUL content sink: script src= should not evaluate the inline content of its tag.
1999-10-31 00:43:30 +00:00
2000-03-29 03:58:50 +00:00
protected :
2001-06-29 00:40:45 +00:00
virtual ~ nsJSThunk ( ) ;
nsCOMPtr < nsIURI > mURI ;
2003-01-18 02:15:14 +00:00
nsCOMPtr < nsIInputStream > mInnerStream ;
1999-10-13 07:17:36 +00:00
} ;
1999-08-26 22:45:55 +00:00
2001-06-29 00:40:45 +00:00
//
// nsISupports implementation...
//
2003-09-07 22:05:34 +00:00
NS_IMPL_THREADSAFE_ISUPPORTS1 ( nsJSThunk , nsIInputStream )
2001-06-29 00:40:45 +00:00
nsJSThunk : : nsJSThunk ( )
1999-10-13 07:17:36 +00:00
{
}
1999-07-12 23:46:40 +00:00
2001-06-29 00:40:45 +00:00
nsJSThunk : : ~ nsJSThunk ( )
1999-10-13 07:17:36 +00:00
{
}
1999-07-12 23:46:40 +00:00
2002-08-21 23:01:23 +00:00
nsresult nsJSThunk : : Init ( nsIURI * uri )
2000-03-29 03:58:50 +00:00
{
2001-06-29 00:40:45 +00:00
NS_ENSURE_ARG_POINTER ( uri ) ;
mURI = uri ;
2000-03-29 03:58:50 +00:00
return NS_OK ;
}
1999-10-13 07:17:36 +00:00
2002-08-21 23:01:23 +00:00
nsresult nsJSThunk : : EvaluateScript ( nsIChannel * aChannel )
1999-07-12 23:46:40 +00:00
{
2001-06-29 00:40:45 +00:00
nsresult rv ;
2002-08-21 23:01:23 +00:00
NS_ENSURE_ARG_POINTER ( aChannel ) ;
2000-03-31 00:31:44 +00:00
2001-06-29 00:40:45 +00:00
// Get the script string to evaluate...
2002-03-06 07:48:55 +00:00
nsCAutoString script ;
rv = mURI - > GetPath ( script ) ;
2001-06-29 00:40:45 +00:00
if ( NS_FAILED ( rv ) ) return rv ;
2000-06-14 04:57:49 +00:00
// Get an interface requestor from the channel callbacks.
2000-03-29 03:58:50 +00:00
nsCOMPtr < nsIInterfaceRequestor > callbacks ;
2002-08-21 23:01:23 +00:00
rv = aChannel - > GetNotificationCallbacks ( getter_AddRefs ( callbacks ) ) ;
2001-06-29 00:40:45 +00:00
NS_ASSERTION ( NS_SUCCEEDED ( rv ) & & callbacks ,
" Unable to get an nsIInterfaceRequestor from the channel " ) ;
if ( NS_FAILED ( rv ) | | ! callbacks ) {
return NS_ERROR_FAILURE ;
}
2000-03-29 03:58:50 +00:00
2000-06-14 04:57:49 +00:00
// The requestor must be able to get a script global object owner.
2000-03-29 03:58:50 +00:00
nsCOMPtr < nsIScriptGlobalObjectOwner > globalOwner ;
2001-06-29 00:40:45 +00:00
rv = callbacks - > GetInterface ( NS_GET_IID ( nsIScriptGlobalObjectOwner ) ,
getter_AddRefs ( globalOwner ) ) ;
NS_ASSERTION ( NS_SUCCEEDED ( rv ) & & globalOwner ,
" Unable to get an nsIScriptGlobalObjectOwner from the "
" InterfaceRequestor! " ) ;
if ( NS_FAILED ( rv ) | | ! globalOwner ) {
return NS_ERROR_FAILURE ;
}
2000-03-29 03:58:50 +00:00
// So far so good: get the script context from its owner.
nsCOMPtr < nsIScriptGlobalObject > global ;
2001-06-29 00:40:45 +00:00
rv = globalOwner - > GetScriptGlobalObject ( getter_AddRefs ( global ) ) ;
NS_ASSERTION ( NS_SUCCEEDED ( rv ) & & global ,
" Unable to get an nsIScriptGlobalObject from the "
" ScriptGlobalObjectOwner! " ) ;
if ( NS_FAILED ( rv ) | | ! global ) {
return NS_ERROR_FAILURE ;
}
2003-05-12 22:23:52 +00:00
JSObject * globalJSObject = global - > GetGlobalJSObject ( ) ;
2002-08-21 23:01:23 +00:00
nsCOMPtr < nsIDOMWindow > domWindow ( do_QueryInterface ( global , & rv ) ) ;
if ( NS_FAILED ( rv ) ) {
return NS_ERROR_FAILURE ;
}
// If mURI is just "javascript:", we bring up the JavaScript console
// and return NS_ERROR_DOM_RETVAL_UNDEFINED.
if ( script . IsEmpty ( ) ) {
rv = BringUpConsole ( domWindow ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
return NS_ERROR_DOM_RETVAL_UNDEFINED ;
}
2002-06-27 18:07:32 +00:00
// Now get the DOM Document. Accessing the document will create one
// if necessary. So, basically, this call ensures that a document gets
// created -- if necessary.
2002-08-21 23:01:23 +00:00
nsCOMPtr < nsIDOMDocument > doc ;
rv = domWindow - > GetDocument ( getter_AddRefs ( doc ) ) ;
NS_ASSERTION ( doc , " No DOMDocument! " ) ;
2002-06-27 18:07:32 +00:00
if ( NS_FAILED ( rv ) ) {
return NS_ERROR_FAILURE ;
}
2000-03-29 03:58:50 +00:00
nsCOMPtr < nsIScriptContext > scriptContext ;
rv = global - > GetContext ( getter_AddRefs ( scriptContext ) ) ;
2001-07-13 07:08:26 +00:00
if ( NS_FAILED ( rv ) )
return rv ;
2000-03-29 03:58:50 +00:00
2001-07-19 05:48:49 +00:00
if ( ! scriptContext ) return NS_ERROR_FAILURE ;
2002-08-21 23:01:23 +00:00
// Unescape the script
NS_UnescapeURL ( script ) ;
// Get the url.
nsCAutoString url ;
rv = mURI - > GetSpec ( url ) ;
if ( NS_FAILED ( rv ) ) return rv ;
2000-03-29 03:58:50 +00:00
// Get principal of code for execution
2000-06-13 23:56:30 +00:00
nsCOMPtr < nsISupports > owner ;
2002-08-21 23:01:23 +00:00
rv = aChannel - > GetOwner ( getter_AddRefs ( owner ) ) ;
2000-03-29 03:58:50 +00:00
nsCOMPtr < nsIPrincipal > principal ;
2001-07-13 07:08:26 +00:00
if ( NS_FAILED ( rv ) )
return rv ;
nsCOMPtr < nsIScriptSecurityManager > securityManager ;
securityManager = do_GetService ( NS_SCRIPTSECURITYMANAGER_CONTRACTID , & rv ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2000-06-14 04:57:49 +00:00
if ( owner ) {
2000-06-13 23:56:30 +00:00
principal = do_QueryInterface ( owner , & rv ) ;
NS_ASSERTION ( principal , " Channel's owner is not a principal " ) ;
2001-07-13 07:08:26 +00:00
if ( ! principal )
return NS_ERROR_FAILURE ;
//-- Don't run if the script principal is different from the
2001-08-31 21:01:10 +00:00
// principal of the context, with two exceptions: we allow
// the script to run if the script has the system principal
// or the context is about:blank.
2001-07-13 07:08:26 +00:00
nsCOMPtr < nsIPrincipal > objectPrincipal ;
rv = securityManager - > GetObjectPrincipal (
( JSContext * ) scriptContext - > GetNativeContext ( ) ,
2003-05-12 22:23:52 +00:00
globalJSObject ,
2001-07-13 07:08:26 +00:00
getter_AddRefs ( objectPrincipal ) ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2001-08-31 21:01:10 +00:00
2003-10-21 22:11:49 +00:00
nsCOMPtr < nsIPrincipal > systemPrincipal ;
securityManager - > GetSystemPrincipal ( getter_AddRefs ( systemPrincipal ) ) ;
if ( principal ! = systemPrincipal ) {
rv = securityManager - > CheckSameOriginPrincipal ( principal ,
objectPrincipal ) ;
if ( NS_FAILED ( rv ) ) {
nsCOMPtr < nsIConsoleService > console =
do_GetService ( " @mozilla.org/consoleservice;1 " ) ;
if ( console ) {
// XXX Localize me!
console - > LogStringMessage (
NS_LITERAL_STRING ( " Attempt to load a javascript: URL from one host \n in a window displaying content from another host \n was blocked by the security manager. " ) . get ( ) ) ;
2001-08-31 21:01:10 +00:00
}
2003-10-21 22:11:49 +00:00
return NS_ERROR_DOM_RETVAL_UNDEFINED ;
2001-08-31 21:01:10 +00:00
}
2001-07-13 07:08:26 +00:00
}
2000-06-13 23:56:30 +00:00
}
2000-06-14 04:57:49 +00:00
else {
// No owner from channel, use the current URI to generate a principal
2001-06-29 00:40:45 +00:00
rv = securityManager - > GetCodebasePrincipal ( mURI ,
getter_AddRefs ( principal ) ) ;
if ( NS_FAILED ( rv ) | | ! principal ) {
return NS_ERROR_FAILURE ;
}
}
1999-10-13 07:17:36 +00:00
2000-03-29 03:58:50 +00:00
// Finally, we have everything needed to evaluate the expression.
nsString result ;
2001-06-29 00:40:45 +00:00
PRBool bIsUndefined ;
2003-05-12 22:23:52 +00:00
2003-05-21 23:51:03 +00:00
rv = scriptContext - > EvaluateString ( NS_ConvertUTF8toUCS2 ( script ) ,
globalJSObject , // obj
principal ,
url . get ( ) , // url
1 , // line no
nsnull ,
result ,
& bIsUndefined ) ;
2000-06-14 04:57:49 +00:00
2001-06-29 00:40:45 +00:00
if ( NS_FAILED ( rv ) ) {
rv = NS_ERROR_MALFORMED_URI ;
}
else if ( bIsUndefined ) {
rv = NS_ERROR_DOM_RETVAL_UNDEFINED ;
}
else {
2003-01-18 02:15:14 +00:00
// NS_NewStringInputStream calls ToNewCString
2001-06-29 00:40:45 +00:00
// XXXbe this should not decimate! pass back UCS-2 to necko
2003-01-18 02:15:14 +00:00
rv = NS_NewStringInputStream ( getter_AddRefs ( mInnerStream ) , result ) ;
2001-06-29 00:40:45 +00:00
}
1999-07-12 23:46:40 +00:00
return rv ;
}
2002-08-21 23:01:23 +00:00
nsresult nsJSThunk : : BringUpConsole ( nsIDOMWindow * aDomWindow )
2000-06-14 04:57:49 +00:00
{
nsresult rv ;
// First, get the Window Mediator service.
2003-10-21 22:11:49 +00:00
nsCOMPtr < nsIWindowMediator > windowMediator =
do_GetService ( kWindowMediatorCID , & rv ) ;
2001-06-29 00:40:45 +00:00
2000-06-14 04:57:49 +00:00
if ( NS_FAILED ( rv ) ) return rv ;
// Next, find out whether there's a console already open.
2000-09-01 01:54:35 +00:00
nsCOMPtr < nsIDOMWindowInternal > console ;
2000-09-13 02:48:08 +00:00
rv = windowMediator - > GetMostRecentWindow ( NS_LITERAL_STRING ( " global:console " ) . get ( ) ,
2000-06-14 04:57:49 +00:00
getter_AddRefs ( console ) ) ;
if ( NS_FAILED ( rv ) ) return rv ;
if ( console ) {
// If the console is already open, bring it to the top.
rv = console - > Focus ( ) ;
} else {
2001-06-29 00:40:45 +00:00
nsCOMPtr < nsIJSConsoleService > jsconsole ;
jsconsole = do_GetService ( " @mozilla.org/embedcomp/jsconsole-service;1 " , & rv ) ;
2001-05-11 01:52:11 +00:00
if ( NS_FAILED ( rv ) | | ! jsconsole ) return rv ;
2002-08-21 23:01:23 +00:00
jsconsole - > Open ( aDomWindow ) ;
2001-06-29 00:40:45 +00:00
}
return rv ;
}
1999-07-12 23:46:40 +00:00
////////////////////////////////////////////////////////////////////////////////
2001-06-29 00:40:45 +00:00
class nsJSChannel : public nsIChannel
2000-03-29 03:58:50 +00:00
{
public :
2001-06-29 00:40:45 +00:00
nsJSChannel ( ) ;
2000-03-29 03:58:50 +00:00
NS_DECL_ISUPPORTS
2001-06-29 00:40:45 +00:00
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
nsresult Init ( nsIURI * aURI ) ;
protected :
virtual ~ nsJSChannel ( ) ;
2003-05-15 01:23:26 +00:00
nsresult StopAll ( ) ;
2003-05-21 21:37:25 +00:00
nsresult InternalOpen ( PRBool aIsAsync , nsIStreamListener * aListener ,
nsISupports * aContext , nsIInputStream * * aResult ) ;
2001-06-29 00:40:45 +00:00
protected :
nsCOMPtr < nsIChannel > mStreamChannel ;
2003-05-21 21:37:25 +00:00
nsLoadFlags mLoadFlags ;
2003-05-15 01:23:26 +00:00
nsRefPtr < nsJSThunk > mIOThunk ;
2003-05-21 21:37:25 +00:00
PRPackedBool mIsActive ;
PRPackedBool mWasCanceled ;
2001-06-29 00:40:45 +00:00
} ;
nsJSChannel : : nsJSChannel ( ) :
2003-07-14 21:06:21 +00:00
mLoadFlags ( LOAD_NORMAL ) ,
2003-05-21 21:37:25 +00:00
mIsActive ( PR_FALSE ) ,
mWasCanceled ( PR_FALSE )
2001-06-29 00:40:45 +00:00
{
}
nsJSChannel : : ~ nsJSChannel ( )
{
}
2000-03-29 03:58:50 +00:00
2003-05-15 01:23:26 +00:00
nsresult nsJSChannel : : StopAll ( )
{
nsCOMPtr < nsIInterfaceRequestor > callbacks ;
mStreamChannel - > GetNotificationCallbacks ( getter_AddRefs ( callbacks ) ) ;
nsresult rv = NS_ERROR_UNEXPECTED ;
nsCOMPtr < nsIWebNavigation > webNav ( do_GetInterface ( callbacks ) ) ;
NS_ASSERTION ( webNav , " Can't get nsIWebNavigation from callbacks! " ) ;
if ( webNav ) {
rv = webNav - > Stop ( nsIWebNavigation : : STOP_ALL ) ;
}
return rv ;
}
2001-06-29 00:40:45 +00:00
nsresult nsJSChannel : : Init ( nsIURI * aURI )
{
nsresult rv ;
2003-05-15 01:23:26 +00:00
2001-06-29 00:40:45 +00:00
// Create the nsIStreamIO layer used by the nsIStreamIOChannel.
2003-05-15 01:23:26 +00:00
mIOThunk = new nsJSThunk ( ) ;
if ( ! mIOThunk )
2001-06-29 00:40:45 +00:00
return NS_ERROR_OUT_OF_MEMORY ;
2003-01-18 02:15:14 +00:00
// Create a stock input stream channel...
2001-06-29 00:40:45 +00:00
// Remember, until AsyncOpen is called, the script will not be evaluated
// and the underlying Input Stream will not be created...
2003-01-18 02:15:14 +00:00
nsCOMPtr < nsIChannel > channel ;
2001-06-29 00:40:45 +00:00
2003-01-18 02:15:14 +00:00
// If the resultant script evaluation actually does return a value, we
// treat it as html.
rv = NS_NewInputStreamChannel ( getter_AddRefs ( channel ) , aURI , mIOThunk ,
NS_LITERAL_CSTRING ( " text/html " ) ,
2004-01-29 22:04:45 +00:00
EmptyCString ( ) ) ;
2001-06-29 00:40:45 +00:00
if ( NS_FAILED ( rv ) ) return rv ;
2002-08-21 23:01:23 +00:00
rv = mIOThunk - > Init ( aURI ) ;
2001-06-29 00:40:45 +00:00
if ( NS_SUCCEEDED ( rv ) ) {
2003-01-18 02:15:14 +00:00
mStreamChannel = channel ;
2000-03-29 03:58:50 +00:00
}
2001-06-29 00:40:45 +00:00
return rv ;
}
//
// nsISupports implementation...
//
NS_IMPL_ADDREF ( nsJSChannel )
NS_IMPL_RELEASE ( nsJSChannel )
NS_INTERFACE_MAP_BEGIN ( nsJSChannel )
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS ( nsISupports , nsIChannel )
NS_INTERFACE_MAP_ENTRY ( nsIRequest )
NS_INTERFACE_MAP_ENTRY ( nsIChannel )
NS_INTERFACE_MAP_END
//
// nsIRequest implementation...
//
NS_IMETHODIMP
2002-03-20 22:50:33 +00:00
nsJSChannel : : GetName ( nsACString & aResult )
2001-06-29 00:40:45 +00:00
{
return mStreamChannel - > GetName ( aResult ) ;
}
NS_IMETHODIMP
nsJSChannel : : IsPending ( PRBool * aResult )
{
2003-05-21 21:37:25 +00:00
* aResult = mIsActive ;
return NS_OK ;
2001-06-29 00:40:45 +00:00
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : GetStatus ( nsresult * aResult )
{
2003-05-21 21:37:25 +00:00
// We're always ok. Our status is independent of our underlying
// stream's status.
* aResult = NS_OK ;
return NS_OK ;
2001-06-29 00:40:45 +00:00
}
2000-06-24 00:03:10 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : Cancel ( nsresult aStatus )
{
2003-05-21 21:37:25 +00:00
// If we're canceled just record the fact that we were canceled,
// the underlying stream will be canceled later, if needed. And we
// don't care about the reason for the canceling, i.e. ignore
// aStatus.
2003-05-15 01:23:26 +00:00
2003-05-21 21:37:25 +00:00
mWasCanceled = PR_TRUE ;
2003-05-15 01:23:26 +00:00
2003-05-21 21:37:25 +00:00
return NS_OK ;
2001-06-29 00:40:45 +00:00
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
2003-05-21 21:37:25 +00:00
nsJSChannel : : Suspend ( )
2001-06-29 00:40:45 +00:00
{
2003-10-30 21:23:15 +00:00
return mStreamChannel - > Suspend ( ) ;
2001-06-29 00:40:45 +00:00
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
2003-05-21 21:37:25 +00:00
nsJSChannel : : Resume ( )
2001-06-29 00:40:45 +00:00
{
2003-10-30 21:23:15 +00:00
return mStreamChannel - > Resume ( ) ;
2001-06-29 00:40:45 +00:00
}
2000-06-24 00:03:10 +00:00
2001-06-29 00:40:45 +00:00
//
// nsIChannel implementation
//
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : GetOriginalURI ( nsIURI * * aURI )
{
return mStreamChannel - > GetOriginalURI ( aURI ) ;
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : SetOriginalURI ( nsIURI * aURI )
{
return mStreamChannel - > SetOriginalURI ( aURI ) ;
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : GetURI ( nsIURI * * aURI )
{
return mStreamChannel - > GetURI ( aURI ) ;
}
2000-06-14 04:57:49 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
2001-08-21 06:20:53 +00:00
nsJSChannel : : Open ( nsIInputStream * * aResult )
2001-06-29 00:40:45 +00:00
{
2003-05-21 21:37:25 +00:00
return InternalOpen ( PR_FALSE , nsnull , nsnull , aResult ) ;
2001-06-29 00:40:45 +00:00
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : AsyncOpen ( nsIStreamListener * aListener , nsISupports * aContext )
{
2003-05-21 21:37:25 +00:00
return InternalOpen ( PR_TRUE , aListener , aContext , nsnull ) ;
}
2000-03-29 03:58:50 +00:00
2003-05-21 21:37:25 +00:00
nsresult
nsJSChannel : : InternalOpen ( PRBool aIsAsync , nsIStreamListener * aListener ,
nsISupports * aContext , nsIInputStream * * aResult )
{
2001-07-06 19:40:23 +00:00
nsCOMPtr < nsILoadGroup > loadGroup ;
2003-05-21 21:37:25 +00:00
// Add the javascript channel to its loadgroup so that we know if
// network loads were canceled or not...
mStreamChannel - > GetLoadGroup ( getter_AddRefs ( loadGroup ) ) ;
if ( loadGroup ) {
loadGroup - > AddRequest ( this , aContext ) ;
}
2001-06-29 00:40:45 +00:00
// Synchronously execute the script...
// mIsActive is used to indicate the the request is 'busy' during the
// the script evaluation phase. This means that IsPending() will
// indicate the the request is busy while the script is executing...
mIsActive = PR_TRUE ;
2003-05-21 21:37:25 +00:00
nsresult rv = mIOThunk - > EvaluateScript ( mStreamChannel ) ;
2000-04-21 05:18:15 +00:00
2003-05-21 21:37:25 +00:00
// Remove the javascript channel from its loadgroup...
if ( loadGroup ) {
loadGroup - > RemoveRequest ( this , aContext , rv ) ;
}
2003-05-15 01:23:26 +00:00
2003-05-21 21:37:25 +00:00
// We're no longer active, it's now up to the stream channel to do
// the loading, if needed.
mIsActive = PR_FALSE ;
if ( NS_SUCCEEDED ( rv ) & & ! mWasCanceled ) {
// EvaluateScript() succeeded, and we were not canceled, that
// means there's data to parse as a result of evaluating the
// script.
// Get the stream channels load flags (!= mLoadFlags).
2003-05-15 19:38:35 +00:00
nsLoadFlags loadFlags ;
mStreamChannel - > GetLoadFlags ( & loadFlags ) ;
if ( loadFlags & LOAD_DOCUMENT_URI ) {
// We're loaded as the document channel. Stop all pending
// network loads.
rv = StopAll ( ) ;
}
2003-05-15 01:23:26 +00:00
if ( NS_SUCCEEDED ( rv ) ) {
// This will add mStreamChannel to the load group.
2003-05-21 21:37:25 +00:00
if ( aIsAsync ) {
rv = mStreamChannel - > AsyncOpen ( aListener , aContext ) ;
} else {
rv = mStreamChannel - > Open ( aResult ) ;
}
2003-05-15 01:23:26 +00:00
}
2001-08-21 06:20:53 +00:00
} else {
// Propagate the failure down to the underlying channel...
2003-05-21 21:37:25 +00:00
mStreamChannel - > Cancel ( rv ) ;
2000-03-29 03:58:50 +00:00
}
2001-07-06 19:40:23 +00:00
2001-06-29 00:40:45 +00:00
return rv ;
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : GetLoadFlags ( nsLoadFlags * aLoadFlags )
{
2003-05-21 21:37:25 +00:00
* aLoadFlags = mLoadFlags ;
return NS_OK ;
2001-06-29 00:40:45 +00:00
}
2000-04-21 05:18:15 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : SetLoadFlags ( nsLoadFlags aLoadFlags )
{
2003-05-21 21:37:25 +00:00
// Since the javascript channel is never the actual channel that
// any data is loaded through, don't ever set the
// LOAD_DOCUMENT_URI flag on it, since that could lead to two
// 'document channels' in the loadgroup if a javascript: URL is
// loaded while a document is being loaded in the same window.
mLoadFlags = aLoadFlags & ~ LOAD_DOCUMENT_URI ;
// ... but the underlying stream channel should get this bit, if
// set, since that'll be the real document channel if the
// javascript: URL generated data.
2003-05-15 01:23:26 +00:00
return mStreamChannel - > SetLoadFlags ( aLoadFlags ) ;
2001-06-29 00:40:45 +00:00
}
2000-04-21 05:18:15 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : GetLoadGroup ( nsILoadGroup * * aLoadGroup )
{
return mStreamChannel - > GetLoadGroup ( aLoadGroup ) ;
}
2000-04-21 05:18:15 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : SetLoadGroup ( nsILoadGroup * aLoadGroup )
{
return mStreamChannel - > SetLoadGroup ( aLoadGroup ) ;
}
2000-04-21 05:18:15 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : GetOwner ( nsISupports * * aOwner )
{
return mStreamChannel - > GetOwner ( aOwner ) ;
}
NS_IMETHODIMP
nsJSChannel : : SetOwner ( nsISupports * aOwner )
{
return mStreamChannel - > SetOwner ( aOwner ) ;
}
NS_IMETHODIMP
nsJSChannel : : GetNotificationCallbacks ( nsIInterfaceRequestor * * aCallbacks )
{
return mStreamChannel - > GetNotificationCallbacks ( aCallbacks ) ;
}
NS_IMETHODIMP
nsJSChannel : : SetNotificationCallbacks ( nsIInterfaceRequestor * aCallbacks )
{
return mStreamChannel - > SetNotificationCallbacks ( aCallbacks ) ;
}
NS_IMETHODIMP
nsJSChannel : : GetSecurityInfo ( nsISupports * * aSecurityInfo )
{
return mStreamChannel - > GetSecurityInfo ( aSecurityInfo ) ;
}
NS_IMETHODIMP
2002-03-20 22:50:33 +00:00
nsJSChannel : : GetContentType ( nsACString & aContentType )
2001-06-29 00:40:45 +00:00
{
return mStreamChannel - > GetContentType ( aContentType ) ;
}
NS_IMETHODIMP
2002-03-20 22:50:33 +00:00
nsJSChannel : : SetContentType ( const nsACString & aContentType )
2001-06-29 00:40:45 +00:00
{
return mStreamChannel - > SetContentType ( aContentType ) ;
}
2002-03-20 22:50:33 +00:00
NS_IMETHODIMP
nsJSChannel : : GetContentCharset ( nsACString & aContentCharset )
{
return mStreamChannel - > GetContentCharset ( aContentCharset ) ;
}
NS_IMETHODIMP
nsJSChannel : : SetContentCharset ( const nsACString & aContentCharset )
{
return mStreamChannel - > SetContentCharset ( aContentCharset ) ;
}
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : GetContentLength ( PRInt32 * aContentLength )
{
return mStreamChannel - > GetContentLength ( aContentLength ) ;
}
NS_IMETHODIMP
nsJSChannel : : SetContentLength ( PRInt32 aContentLength )
{
return mStreamChannel - > SetContentLength ( aContentLength ) ;
}
2000-03-29 03:58:50 +00:00
////////////////////////////////////////////////////////////////////////////////
1999-07-12 23:46:40 +00:00
nsJSProtocolHandler : : nsJSProtocolHandler ( )
{
}
nsresult
nsJSProtocolHandler : : Init ( )
{
return NS_OK ;
}
nsJSProtocolHandler : : ~ nsJSProtocolHandler ( )
{
}
2001-08-21 01:48:11 +00:00
NS_IMPL_ISUPPORTS1 ( nsJSProtocolHandler , nsIProtocolHandler )
1999-07-12 23:46:40 +00:00
NS_METHOD
nsJSProtocolHandler : : Create ( nsISupports * aOuter , REFNSIID aIID , void * * aResult )
{
if ( aOuter )
return NS_ERROR_NO_AGGREGATION ;
nsJSProtocolHandler * ph = new nsJSProtocolHandler ( ) ;
1999-08-26 22:45:55 +00:00
if ( ! ph )
1999-07-12 23:46:40 +00:00
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF ( ph ) ;
nsresult rv = ph - > Init ( ) ;
if ( NS_SUCCEEDED ( rv ) ) {
rv = ph - > QueryInterface ( aIID , aResult ) ;
}
NS_RELEASE ( ph ) ;
return rv ;
}
2002-07-23 23:28:28 +00:00
nsresult
nsJSProtocolHandler : : EnsureUTF8Spec ( const nsAFlatCString & aSpec , const char * aCharset ,
nsACString & aUTF8Spec )
{
aUTF8Spec . Truncate ( ) ;
nsresult rv ;
2002-09-08 15:08:45 +00:00
if ( ! mTextToSubURI ) {
mTextToSubURI = do_GetService ( NS_ITEXTTOSUBURI_CONTRACTID , & rv ) ;
2002-07-23 23:28:28 +00:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
2002-09-08 15:08:45 +00:00
nsAutoString uStr ;
rv = mTextToSubURI - > UnEscapeNonAsciiURI ( nsDependentCString ( aCharset ) , aSpec , uStr ) ;
2002-07-23 23:28:28 +00:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2002-09-08 15:08:45 +00:00
if ( ! IsASCII ( uStr ) )
NS_EscapeURL ( NS_ConvertUCS2toUTF8 ( uStr ) , esc_AlwaysCopy | esc_OnlyNonASCII , aUTF8Spec ) ;
2002-07-23 23:28:28 +00:00
2002-09-08 15:08:45 +00:00
return NS_OK ;
2002-07-23 23:28:28 +00:00
}
1999-07-12 23:46:40 +00:00
////////////////////////////////////////////////////////////////////////////////
// nsIProtocolHandler methods:
NS_IMETHODIMP
2002-03-06 07:48:55 +00:00
nsJSProtocolHandler : : GetScheme ( nsACString & result )
1999-07-12 23:46:40 +00:00
{
2002-03-06 07:48:55 +00:00
result = " javascript " ;
1999-07-12 23:46:40 +00:00
return NS_OK ;
}
NS_IMETHODIMP
nsJSProtocolHandler : : GetDefaultPort ( PRInt32 * result )
{
* result = - 1 ; // no port for javascript: URLs
return NS_OK ;
}
2001-08-07 20:42:57 +00:00
NS_IMETHODIMP
2001-09-13 02:21:05 +00:00
nsJSProtocolHandler : : GetProtocolFlags ( PRUint32 * result )
2001-08-07 20:42:57 +00:00
{
* result = URI_NORELATIVE | URI_NOAUTH ;
return NS_OK ;
}
1999-07-12 23:46:40 +00:00
NS_IMETHODIMP
2002-03-06 07:48:55 +00:00
nsJSProtocolHandler : : NewURI ( const nsACString & aSpec ,
const char * aCharset , // ignore charset info
nsIURI * aBaseURI ,
1999-07-12 23:46:40 +00:00
nsIURI * * result )
{
nsresult rv ;
1999-08-26 22:45:55 +00:00
// javascript: URLs (currently) have no additional structure beyond that
// provided by standard URLs, so there is no "outer" object given to
// CreateInstance.
1999-07-12 23:46:40 +00:00
nsIURI * url ;
2002-09-02 22:15:07 +00:00
rv = nsComponentManager : : CreateInstance ( kSimpleURICID , nsnull ,
NS_GET_IID ( nsIURI ) ,
( void * * ) & url ) ;
1999-08-26 22:45:55 +00:00
if ( NS_FAILED ( rv ) )
return rv ;
1999-07-12 23:46:40 +00:00
2002-07-23 23:28:28 +00:00
if ( ! aCharset | | ! nsCRT : : strcasecmp ( " UTF-8 " , aCharset ) )
rv = url - > SetSpec ( aSpec ) ;
2002-03-06 07:48:55 +00:00
else {
2002-07-23 23:28:28 +00:00
nsCAutoString utf8Spec ;
rv = EnsureUTF8Spec ( PromiseFlatCString ( aSpec ) , aCharset , utf8Spec ) ;
if ( NS_SUCCEEDED ( rv ) ) {
if ( utf8Spec . IsEmpty ( ) )
rv = url - > SetSpec ( aSpec ) ;
else
rv = url - > SetSpec ( utf8Spec ) ;
}
2002-03-06 07:48:55 +00:00
}
1999-07-12 23:46:40 +00:00
if ( NS_FAILED ( rv ) ) {
NS_RELEASE ( url ) ;
return rv ;
}
* result = url ;
return rv ;
}
NS_IMETHODIMP
2000-03-29 03:58:50 +00:00
nsJSProtocolHandler : : NewChannel ( nsIURI * uri , nsIChannel * * result )
1999-07-12 23:46:40 +00:00
{
nsresult rv ;
2001-06-29 00:40:45 +00:00
nsJSChannel * channel ;
2000-03-29 03:58:50 +00:00
NS_ENSURE_ARG_POINTER ( uri ) ;
(13163, r=alecf, scc, waterson, others; names available on request)
- Fix most of bug 13163 (see TODO for rest). This entails adding a version-string argument to nsIScriptContext::EvaluateString and passing it around lots of places in content sinks.
- Fix leaks and confusion about mSecurityManager and mNameSpaceManager in nsJSEnvironment.cpp. These still need to move from nsJSContext to nsGlobalWindow or thereabouts, jband and vidur are looking at that.
- Added comments and expanded tabs in nsJSEnvironment.cpp, esp. to EvaluateString. Also changed various nsresult vars to be named rv. Also restored brace/style conformity to nsJSProtocolHandler.cpp.
- Factored CompileFunction from AddScriptEventListener to pave the way for brutal sharing of compiled JS event handlers via JS_CloneFunctionObject.
- Lots of nsCOMPtr uses added. I'm using one for mNameSpaceManager. Hold mSecurityManager as a service explicitly, on the other hand (awaiting scc's fix to allow comptrs for services), and release in nsJSContext's dtor (fixing a leak). These two managers should be moved to the window object -- TODO item below.
- Hold JSRuntimeService along with JSRuntime for live of nsJSEnvironment, fix for shaver.
- Fix window.setTimeout etc. so the filename and line number of the timeout expr is propagated. This meant factoring nsJSUtils.cpp code.
- Fix all content sinks to use the same, and up-to-date JavaScript version parsing (whether for script type or for old language attribute); also fix SplitMimeType clones to strip whitespace.
- With waterson, fix bug in brutal-sharing version of XUL content sink: script src= should not evaluate the inline content of its tag.
1999-10-31 00:43:30 +00:00
2001-06-29 00:40:45 +00:00
channel = new nsJSChannel ( ) ;
if ( ! channel ) {
1999-10-13 07:17:36 +00:00
return NS_ERROR_OUT_OF_MEMORY ;
2000-05-31 13:57:02 +00:00
}
2001-06-29 00:40:45 +00:00
NS_ADDREF ( channel ) ;
rv = channel - > Init ( uri ) ;
2000-04-14 07:18:36 +00:00
if ( NS_SUCCEEDED ( rv ) ) {
2001-06-29 00:40:45 +00:00
* result = channel ;
NS_ADDREF ( * result ) ;
2000-04-14 07:18:36 +00:00
}
2001-06-29 00:40:45 +00:00
NS_RELEASE ( channel ) ;
return rv ;
1999-07-12 23:46:40 +00:00
}
2001-06-06 00:10:09 +00:00
NS_IMETHODIMP
nsJSProtocolHandler : : AllowPort ( PRInt32 port , const char * scheme , PRBool * _retval )
{
// don't override anything.
* _retval = PR_FALSE ;
return NS_OK ;
}