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"
# 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"
2001-08-31 21:01:10 +00:00
# include "nsICodebasePrincipal.h"
1999-11-18 07:36:41 +00:00
# include "nsIInterfaceRequestor.h"
2001-09-05 21:28:38 +00:00
# include "nsIInterfaceRequestorUtils.h"
2000-04-21 05:18:15 +00:00
# include "nsIByteArrayInputStream.h"
2000-06-14 04:57:49 +00:00
# include "nsIWindowMediator.h"
2000-09-01 01:54:35 +00:00
# include "nsIDOMWindowInternal.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"
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
2001-06-29 00:40:45 +00:00
class nsJSThunk : public nsIStreamIO
{
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
2001-06-29 00:40:45 +00:00
NS_DECL_NSISTREAMIO
nsresult Init ( nsIURI * uri , nsIChannel * channel ) ;
nsresult EvaluateScript ( ) ;
nsresult BringUpConsole ( ) ;
(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 ;
nsCOMPtr < nsIChannel > mChannel ;
char * mResult ;
PRUint32 mLength ;
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...
//
NS_IMPL_THREADSAFE_ISUPPORTS1 ( nsJSThunk , nsIStreamIO ) ;
nsJSThunk : : nsJSThunk ( )
: mChannel ( nsnull ) , mResult ( nsnull ) , mLength ( 0 )
1999-10-13 07:17:36 +00:00
{
2001-06-29 00:40:45 +00:00
NS_INIT_ISUPPORTS ( ) ;
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
{
2001-06-29 00:40:45 +00:00
( void ) Close ( NS_BASE_STREAM_CLOSED ) ;
1999-10-13 07:17:36 +00:00
}
1999-07-12 23:46:40 +00:00
2001-06-29 00:40:45 +00:00
nsresult nsJSThunk : : Init ( nsIURI * uri , nsIChannel * channel )
2000-03-29 03:58:50 +00:00
{
2001-06-29 00:40:45 +00:00
NS_ENSURE_ARG_POINTER ( uri ) ;
NS_ENSURE_ARG_POINTER ( channel ) ;
mURI = uri ;
2000-03-29 03:58:50 +00:00
mChannel = channel ;
return NS_OK ;
}
1999-10-13 07:17:36 +00:00
2001-06-29 00:40:45 +00:00
nsresult nsJSThunk : : EvaluateScript ( )
1999-07-12 23:46:40 +00:00
{
2001-06-29 00:40:45 +00:00
nsresult rv ;
2000-03-31 00:31:44 +00:00
NS_ENSURE_ARG_POINTER ( mChannel ) ;
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 ;
// If mURI is just "javascript:", we bring up the JavaScript console
// and return NS_ERROR_DOM_RETVAL_UNDEFINED.
2002-03-06 07:48:55 +00:00
if ( script . IsEmpty ( ) ) {
2001-06-29 00:40:45 +00:00
rv = BringUpConsole ( ) ;
if ( NS_FAILED ( rv ) ) return NS_ERROR_FAILURE ;
return NS_ERROR_DOM_RETVAL_UNDEFINED ;
}
2000-06-14 04:57:49 +00:00
2002-02-08 01:06:25 +00:00
// Get the url.
2002-03-06 07:48:55 +00:00
nsCAutoString url ;
rv = mURI - > GetSpec ( url ) ;
2002-02-08 01:06:25 +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 ;
rv = mChannel - > 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 ;
}
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 ;
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 ;
rv = mChannel - > 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 ( ) ,
global - > GetGlobalJSObject ( ) ,
getter_AddRefs ( objectPrincipal ) ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2001-08-31 21:01:10 +00:00
2001-07-13 07:08:26 +00:00
PRBool equals = PR_FALSE ;
2001-08-31 21:01:10 +00:00
if ( ( NS_FAILED ( objectPrincipal - > Equals ( principal , & equals ) ) | | ! equals ) ) {
// If the principals aren't equal
nsCOMPtr < nsIPrincipal > systemPrincipal ;
securityManager - > GetSystemPrincipal ( getter_AddRefs ( systemPrincipal ) ) ;
if ( principal . get ( ) ! = systemPrincipal . get ( ) ) {
// and the script to be run does not have the system principal
nsCOMPtr < nsICodebasePrincipal >
objectCodebase ( do_QueryInterface ( objectPrincipal ) ) ;
nsXPIDLCString objectOrigin ;
rv = objectCodebase - > GetOrigin ( getter_Copies ( objectOrigin ) ) ;
if ( PL_strcmp ( " about:blank " , objectOrigin ) ! = 0 ) {
// and the target window is not about:blank, then
// don't run the script. Print a message to the console and
// return undefined.
nsCOMPtr < nsIConsoleService >
console ( do_GetService ( " @mozilla.org/consoleservice;1 " ) ) ;
if ( console ) {
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 ( ) ) ;
}
return NS_ERROR_DOM_RETVAL_UNDEFINED ;
}
}
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 ;
2000-04-02 08:22:56 +00:00
{
2001-08-31 22:56:50 +00:00
NS_ConvertUTF8toUCS2 scriptString ( script ) ;
2000-06-14 04:57:49 +00:00
rv = scriptContext - > EvaluateString ( scriptString ,
nsnull , // obj
principal ,
2002-03-06 07:48:55 +00:00
url . get ( ) , // url
2002-02-08 01:06:25 +00:00
1 , // line no
2000-06-14 04:57:49 +00:00
nsnull ,
result ,
2001-06-29 00:40:45 +00:00
& bIsUndefined ) ;
2000-04-02 08:22:56 +00:00
}
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 {
// XXXbe this should not decimate! pass back UCS-2 to necko
2001-09-29 08:28:41 +00:00
mResult = ToNewCString ( result ) ;
2001-06-29 00:40:45 +00:00
mLength = result . Length ( ) ;
}
1999-07-12 23:46:40 +00:00
return rv ;
}
2000-06-14 04:57:49 +00:00
// Gasp. This is so much easier to write in JS....
2001-06-29 00:40:45 +00:00
nsresult nsJSThunk : : BringUpConsole ( )
2000-06-14 04:57:49 +00:00
{
nsresult rv ;
// First, get the Window Mediator service.
2001-06-29 00:40:45 +00:00
nsCOMPtr < nsIWindowMediator > windowMediator ;
windowMediator = do_GetService ( kWindowMediatorCID , & rv ) ;
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 {
// Get an interface requestor from the channel callbacks.
nsCOMPtr < nsIInterfaceRequestor > callbacks ;
rv = mChannel - > GetNotificationCallbacks ( getter_AddRefs ( callbacks ) ) ;
if ( NS_FAILED ( rv ) ) return rv ;
NS_ENSURE_TRUE ( callbacks , NS_ERROR_FAILURE ) ;
// The requestor must be able to get a script global object owner.
nsCOMPtr < nsIScriptGlobalObjectOwner > globalOwner ;
callbacks - > GetInterface ( NS_GET_IID ( nsIScriptGlobalObjectOwner ) ,
getter_AddRefs ( globalOwner ) ) ;
NS_ENSURE_TRUE ( globalOwner , NS_ERROR_FAILURE ) ;
// So far so good: get the script global and its context.
nsCOMPtr < nsIScriptGlobalObject > global ;
globalOwner - > GetScriptGlobalObject ( getter_AddRefs ( global ) ) ;
NS_ENSURE_TRUE ( global , NS_ERROR_FAILURE ) ;
// Finally, QI global to nsIDOMWindow and open the console.
2001-05-11 01:52:11 +00:00
nsCOMPtr < nsIDOMWindow > window = do_QueryInterface ( global , & rv ) ;
2000-06-14 04:57:49 +00:00
NS_ENSURE_SUCCESS ( rv , NS_ERROR_FAILURE ) ;
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 ;
2001-06-29 00:40:45 +00:00
jsconsole - > Open ( window ) ;
}
return rv ;
}
//
// nsIStreamIO implementation...
//
NS_IMETHODIMP
2002-03-13 00:34:54 +00:00
nsJSThunk : : Open ( PRInt32 * contentLength )
2001-06-29 00:40:45 +00:00
{
//
// At this point the script has already been evaluated...
// The resulting string (if any) is stored in mResult.
//
// If the resultant script evaluation actually does return a value, we
// treat it as html.
* contentLength = mLength ;
return NS_OK ;
}
2002-03-13 00:34:54 +00:00
NS_IMETHODIMP
nsJSThunk : : GetContentType ( char * * aContentType )
{
* aContentType = nsCRT : : strdup ( " text/html " ) ;
if ( * aContentType = = nsnull )
return NS_ERROR_OUT_OF_MEMORY ;
return NS_OK ;
}
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSThunk : : Close ( nsresult status )
{
if ( mResult ) {
nsCRT : : free ( mResult ) ;
mResult = nsnull ;
}
mLength = 0 ;
mChannel = nsnull ;
return NS_OK ;
}
NS_IMETHODIMP
nsJSThunk : : GetInputStream ( nsIInputStream * * aInputStream )
{
nsresult rv ;
nsIByteArrayInputStream * str ;
rv = NS_NewByteArrayInputStream ( & str , mResult , mLength ) ;
if ( NS_SUCCEEDED ( rv ) ) {
mResult = nsnull ; // XXX Whackiness. The input stream takes ownership
* aInputStream = str ;
}
else {
* aInputStream = nsnull ;
2000-06-14 04:57:49 +00:00
}
return rv ;
}
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSThunk : : GetOutputStream ( nsIOutputStream * * aOutputStream )
{
// should never be called
NS_NOTREACHED ( " nsJSThunk::GetOutputStream " ) ;
return NS_ERROR_FAILURE ;
}
NS_IMETHODIMP
nsJSThunk : : GetName ( char * * aName )
{
2002-03-06 07:48:55 +00:00
nsCAutoString buf ;
nsresult rv = mURI - > GetSpec ( buf ) ;
if ( NS_FAILED ( rv ) ) return rv ;
* aName = ToNewCString ( buf ) ;
return * aName ? NS_OK : NS_ERROR_OUT_OF_MEMORY ;
2001-06-29 00:40:45 +00:00
}
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 ( ) ;
protected :
nsCOMPtr < nsIChannel > mStreamChannel ;
2001-07-06 19:40:23 +00:00
nsLoadFlags mLoadFlags ;
2001-06-29 00:40:45 +00:00
nsJSThunk * mIOThunk ;
PRBool mIsActive ;
} ;
nsJSChannel : : nsJSChannel ( ) :
2001-07-06 19:40:23 +00:00
mLoadFlags ( LOAD_NORMAL ) ,
2001-08-21 08:13:04 +00:00
mIOThunk ( nsnull ) ,
mIsActive ( PR_FALSE )
2001-06-29 00:40:45 +00:00
{
NS_INIT_ISUPPORTS ( ) ;
}
nsJSChannel : : ~ nsJSChannel ( )
{
NS_IF_RELEASE ( mIOThunk ) ;
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
nsresult nsJSChannel : : Init ( nsIURI * aURI )
{
nsresult rv ;
// Create the nsIStreamIO layer used by the nsIStreamIOChannel.
mIOThunk = new nsJSThunk ( ) ;
if ( mIOThunk = = nsnull )
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF ( mIOThunk ) ;
// Create a stock nsIStreamIOChannel...
// Remember, until AsyncOpen is called, the script will not be evaluated
// and the underlying Input Stream will not be created...
nsCOMPtr < nsIStreamIOChannel > channel ;
rv = NS_NewStreamIOChannel ( getter_AddRefs ( channel ) , aURI , mIOThunk ) ;
if ( NS_FAILED ( rv ) ) return rv ;
rv = mIOThunk - > Init ( aURI , channel ) ;
if ( NS_SUCCEEDED ( rv ) ) {
mStreamChannel = do_QueryInterface ( 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
nsJSChannel : : GetName ( PRUnichar * * aResult )
{
return mStreamChannel - > GetName ( aResult ) ;
}
NS_IMETHODIMP
nsJSChannel : : IsPending ( PRBool * aResult )
{
if ( mIsActive ) {
* aResult = mIsActive ;
2000-03-29 03:58:50 +00:00
return NS_OK ;
}
2001-06-29 00:40:45 +00:00
return mStreamChannel - > IsPending ( aResult ) ;
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : GetStatus ( nsresult * aResult )
{
return mStreamChannel - > GetStatus ( aResult ) ;
}
2000-06-24 00:03:10 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : Cancel ( nsresult aStatus )
{
return mStreamChannel - > Cancel ( aStatus ) ;
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : Suspend ( void )
{
return mStreamChannel - > Suspend ( ) ;
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : Resume ( void )
{
return mStreamChannel - > Resume ( ) ;
}
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
{
nsresult rv ;
2000-06-14 04:57:49 +00:00
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 ;
rv = mIOThunk - > EvaluateScript ( ) ;
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
if ( NS_SUCCEEDED ( rv ) ) {
2001-08-21 06:20:53 +00:00
rv = mStreamChannel - > Open ( aResult ) ;
} else {
// Propagate the failure down to the underlying channel...
( void ) mStreamChannel - > Cancel ( rv ) ;
2001-06-29 00:40:45 +00:00
}
mIsActive = PR_FALSE ;
return rv ;
2000-03-29 03:58:50 +00:00
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 )
{
nsresult rv ;
2000-03-29 03:58:50 +00:00
2001-07-06 19:40:23 +00:00
nsCOMPtr < nsILoadGroup > loadGroup ;
// Add the javascript channel to its loadgroup...
mStreamChannel - > GetLoadGroup ( getter_AddRefs ( loadGroup ) ) ;
if ( loadGroup ) {
( void ) 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 ;
rv = mIOThunk - > EvaluateScript ( ) ;
2000-04-21 05:18:15 +00:00
2001-06-29 00:40:45 +00:00
if ( NS_SUCCEEDED ( rv ) ) {
rv = mStreamChannel - > AsyncOpen ( aListener , aContext ) ;
2001-08-21 06:20:53 +00:00
} else {
// Propagate the failure down to the underlying channel...
( void ) mStreamChannel - > Cancel ( rv ) ;
2000-03-29 03:58:50 +00:00
}
2001-07-06 19:40:23 +00:00
// Remove the javascript channel from its loadgroup...
if ( loadGroup ) {
( void ) loadGroup - > RemoveRequest ( this , aContext , rv ) ;
}
2001-06-29 00:40:45 +00:00
mIsActive = PR_FALSE ;
return rv ;
}
2000-03-29 03:58:50 +00:00
2001-06-29 00:40:45 +00:00
NS_IMETHODIMP
nsJSChannel : : GetLoadFlags ( nsLoadFlags * aLoadFlags )
{
2001-07-06 19:40:23 +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 )
{
2001-07-06 19:40:23 +00:00
mLoadFlags = aLoadFlags ;
//
// Since the javascript channel is considered the 'document channel'
// clear this bit before passing it down... Otherwise, there will be
// two document channels!!
//
return mStreamChannel - > SetLoadFlags ( aLoadFlags & ~ ( LOAD_DOCUMENT_URI ) ) ;
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
nsJSChannel : : GetContentType ( char * * aContentType )
{
return mStreamChannel - > GetContentType ( aContentType ) ;
}
NS_IMETHODIMP
nsJSChannel : : SetContentType ( const char * aContentType )
{
return mStreamChannel - > SetContentType ( aContentType ) ;
}
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 ( )
{
NS_INIT_REFCNT ( ) ;
}
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 ;
}
////////////////////////////////////////////////////////////////////////////////
// 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 ;
if ( aBaseURI ) {
rv = aBaseURI - > Clone ( & url ) ;
1999-08-26 22:45:55 +00:00
} else {
1999-07-12 23:46:40 +00:00
rv = nsComponentManager : : CreateInstance ( kSimpleURICID , nsnull ,
1999-09-06 23:01:40 +00:00
NS_GET_IID ( nsIURI ) ,
1999-07-12 23:46:40 +00:00
( 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-03-06 07:48:55 +00:00
if ( IsASCII ( aSpec ) )
rv = url - > SetSpec ( aSpec ) ;
else {
// need special encoding for unicode characters...
// XXXdarin iterate over the UTF-8 chars instead
NS_ConvertUTF8toUCS2 ucsSpec ( aSpec ) ;
nsCAutoString encSpec ;
char buf [ 6 + 1 ] ; // space for \uXXXX plus a NUL at the end
for ( const PRUnichar * uch = ucsSpec . get ( ) ; * uch ; + + uch ) {
if ( * uch > 0x7F ) {
PR_snprintf ( buf , sizeof ( buf ) , " \\ u%.4x " , * uch ) ;
encSpec . Append ( buf ) ;
}
else {
// it's ASCII so we're safe...
encSpec . Append ( char ( * uch ) ) ;
}
}
rv = url - > SetSpec ( encSpec ) ;
}
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 ;
}
2001-06-29 00:40:45 +00:00
1999-08-26 22:45:55 +00:00
////////////////////////////////////////////////////////////////////////////////
2002-01-30 21:14:20 +00:00
static const nsModuleComponentInfo gJSModuleInfo [ ] = {
2000-06-14 04:57:49 +00:00
{ " JavaScript Protocol Handler " ,
2000-01-28 02:42:07 +00:00
NS_JSPROTOCOLHANDLER_CID ,
2000-09-13 23:57:52 +00:00
NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX " javascript " ,
2000-01-28 02:42:07 +00:00
nsJSProtocolHandler : : Create }
} ;
1999-08-26 22:45:55 +00:00
2001-05-05 05:33:37 +00:00
NS_IMPL_NSGETMODULE ( javascript__protocol , gJSModuleInfo )
1999-08-26 22:45:55 +00:00
1999-07-12 23:46:40 +00:00
////////////////////////////////////////////////////////////////////////////////