2001-09-25 22:43:09 +00:00
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2005-10-03 16:59:38 +00:00
/* vim: set ts=2 sw=4 et tw=80: */
2001-09-25 22:43:09 +00:00
/* ***** BEGIN LICENSE BLOCK *****
2004-04-17 21:52:36 +00:00
* Version : MPL 1.1 / GPL 2.0 / LGPL 2.1
1999-07-12 23:46:40 +00:00
*
2004-04-17 21:52:36 +00:00
* The contents of this file are subject to the Mozilla 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/MPL/
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 .
*
2004-04-17 21:52:36 +00:00
* The Initial Developer of the Original Code is
2001-09-25 22:43:09 +00:00
* 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
2004-04-17 21:52:36 +00:00
* either of 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 " ) ,
2001-09-25 22:43:09 +00:00
* 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
2004-04-17 21:52:36 +00:00
* use your version of this file under the terms of the MPL , indicate your
2001-09-25 22:43:09 +00:00
* 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
2004-04-17 21:52:36 +00:00
* the terms of any one of the MPL , the GPL or the LGPL .
2001-09-25 22:43:09 +00:00
*
* * * * * * 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"
2006-01-02 03:31:39 +00:00
# include "nsStringStream.h"
2001-06-29 00:40:45 +00:00
# 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"
2000-06-14 04:57:49 +00:00
# include "nsIWindowMediator.h"
2005-08-12 04:11:00 +00:00
# include "nsPIDOMWindow.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"
2004-02-11 06:09:51 +00:00
# include "nsIDocShell.h"
# include "nsIContentViewer.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 ;
2004-03-10 01:18:26 +00:00
// The the global object owner from the channel
2000-03-29 03:58:50 +00:00
nsCOMPtr < nsIScriptGlobalObjectOwner > globalOwner ;
2004-11-15 20:16:52 +00:00
NS_QueryNotificationCallbacks ( aChannel , globalOwner ) ;
2004-03-10 01:18:26 +00:00
NS_ASSERTION ( globalOwner ,
2001-06-29 00:40:45 +00:00
" Unable to get an nsIScriptGlobalObjectOwner from the "
2004-03-10 01:18:26 +00:00
" channel! " ) ;
if ( ! globalOwner ) {
2001-06-29 00:40:45 +00:00
return NS_ERROR_FAILURE ;
}
2000-03-29 03:58:50 +00:00
// So far so good: get the script context from its owner.
2004-07-16 17:03:10 +00:00
nsIScriptGlobalObject * global = globalOwner - > GetScriptGlobalObject ( ) ;
2001-06-29 00:40:45 +00:00
2004-07-16 17:03:10 +00:00
NS_ASSERTION ( global ,
2001-06-29 00:40:45 +00:00
" Unable to get an nsIScriptGlobalObject from the "
" ScriptGlobalObjectOwner! " ) ;
2004-07-16 17:03:10 +00:00
if ( ! global ) {
2001-06-29 00:40:45 +00:00
return NS_ERROR_FAILURE ;
}
2005-08-12 04:11:00 +00:00
nsCOMPtr < nsPIDOMWindow > win ( do_QueryInterface ( global ) ) ;
2005-08-31 23:55:23 +00:00
2005-12-11 20:38:29 +00:00
// Make sure we create a new inner window if one doesn't already exist (see
// bug 306630).
nsPIDOMWindow * innerWin = win - > EnsureInnerWindow ( ) ;
2005-08-12 04:11:00 +00:00
if ( ! innerWin ) {
return NS_ERROR_UNEXPECTED ;
}
nsCOMPtr < nsIScriptGlobalObject > innerGlobal = do_QueryInterface ( innerWin ) ;
JSObject * globalJSObject = innerGlobal - > GetGlobalJSObject ( ) ;
2003-05-12 22:23:52 +00:00
2002-08-21 23:01:23 +00:00
nsCOMPtr < nsIDOMWindow > domWindow ( do_QueryInterface ( global , & rv ) ) ;
if ( NS_FAILED ( rv ) ) {
return NS_ERROR_FAILURE ;
}
2006-05-25 21:22:32 +00:00
// If mURI is just "javascript:", we bring up the Error console
2002-08-21 23:01:23 +00:00
// 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 ;
}
2004-05-18 04:00:47 +00:00
nsCOMPtr < nsIScriptContext > scriptContext = global - > GetContext ( ) ;
2004-02-09 22:48:53 +00:00
if ( ! scriptContext )
return NS_ERROR_FAILURE ;
2001-07-19 05:48:49 +00:00
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 {
2005-10-03 16:59:38 +00:00
// No owner from channel, use the object principals.
rv = securityManager - > GetObjectPrincipal (
( JSContext * ) scriptContext - > GetNativeContext ( ) ,
globalJSObject ,
getter_AddRefs ( principal ) ) ;
// Paranoia check: If we don't have an owner, make sure that we're
// not giving this javascript URL the principals of some other
// random page, so if the principals aren't for about:blank, don't use
// them.
// XXX We can't just create new about:blank principals since caps
// refuses to treat two about:blank principals as equal.
if ( principal ) {
nsCOMPtr < nsIURI > uri ;
rv = principal - > GetURI ( getter_AddRefs ( uri ) ) ;
2006-04-08 01:46:29 +00:00
if ( ! uri ) {
rv = NS_ERROR_NOT_AVAILABLE ;
}
2005-10-03 16:59:38 +00:00
if ( NS_SUCCEEDED ( rv ) ) {
nsCAutoString spec ;
uri - > GetSpec ( spec ) ;
if ( ! spec . EqualsLiteral ( " about:blank " ) ) {
rv = NS_ERROR_FAILURE ;
}
}
}
if ( NS_FAILED ( rv ) | | ! principal ) {
2006-04-02 20:58:26 +00:00
// If all else fails, use a null principal
principal = do_CreateInstance ( " @mozilla.org/nullprincipal;1 " , & rv ) ;
2005-10-03 16:59:38 +00:00
}
2001-06-29 00:40:45 +00:00
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
2006-02-03 14:18:39 +00:00
rv = scriptContext - > EvaluateString ( NS_ConvertUTF8toUTF16 ( script ) ,
2003-05-21 23:51:03 +00:00
globalJSObject , // obj
principal ,
url . get ( ) , // url
1 , // line no
nsnull ,
2004-06-11 00:48:00 +00:00
& result ,
2003-05-21 23:51:03 +00:00
& 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 {
2006-05-04 19:12:26 +00:00
PRUint32 resultUTF8len ;
char * resultUTF8 = ToNewUTF8String ( result , & resultUTF8len ) ;
if ( resultUTF8 )
rv = NS_NewByteInputStream ( getter_AddRefs ( mInnerStream ) ,
resultUTF8 , resultUTF8len ,
NS_ASSIGNMENT_ADOPT ) ;
else
rv = NS_ERROR_OUT_OF_MEMORY ;
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 ( )
{
nsresult rv = NS_ERROR_UNEXPECTED ;
2004-03-10 01:18:26 +00:00
nsCOMPtr < nsIWebNavigation > webNav ;
2004-11-15 20:16:52 +00:00
NS_QueryNotificationCallbacks ( mStreamChannel , webNav ) ;
2003-05-15 01:23:26 +00:00
2004-03-10 01:18:26 +00:00
NS_ASSERTION ( webNav , " Can't get nsIWebNavigation from channel! " ) ;
2003-05-15 01:23:26 +00:00
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 ,
2006-05-04 19:12:26 +00:00
NS_LITERAL_CSTRING ( " text/html " ) ,
NS_LITERAL_CSTRING ( " UTF-8 " ) ) ;
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 ;
2004-10-28 02:06:27 +00:00
// Temporarily set the LOAD_BACKGROUND flag to suppress load group observer
// notifications (and hence nsIWebProgressListener notifications) from
// being dispatched. This is required since we suppress LOAD_DOCUMENT_URI,
// which means that the DocLoader would not generate document start and
// stop notifications (see bug 257875).
PRUint32 oldLoadFlags = mLoadFlags ;
mLoadFlags | = LOAD_BACKGROUND ;
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
2004-10-28 02:06:27 +00:00
// Reset load flags to their original value...
mLoadFlags = oldLoadFlags ;
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 ) {
2004-02-11 06:09:51 +00:00
// We're loaded as the document channel. If we go on,
// we'll blow away the current document. Make sure that's
// ok. If so, stop all pending network loads.
2004-03-10 01:18:26 +00:00
nsCOMPtr < nsIDocShell > docShell ;
2004-11-15 20:16:52 +00:00
NS_QueryNotificationCallbacks ( mStreamChannel , docShell ) ;
2004-02-11 06:09:51 +00:00
if ( docShell ) {
nsCOMPtr < nsIContentViewer > cv ;
docShell - > GetContentViewer ( getter_AddRefs ( cv ) ) ;
if ( cv ) {
PRBool okToUnload ;
if ( NS_SUCCEEDED ( cv - > PermitUnload ( & okToUnload ) ) & &
! okToUnload ) {
// The user didn't want to unload the current
// page, translate this into an undefined
// return from the javascript: URL...
rv = NS_ERROR_DOM_RETVAL_UNDEFINED ;
}
}
}
2003-05-15 19:38:35 +00:00
2004-02-11 06:09:51 +00:00
if ( NS_SUCCEEDED ( rv ) ) {
rv = StopAll ( ) ;
}
2003-05-15 19:38:35 +00:00
}
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
}
2004-02-11 06:09:51 +00:00
}
if ( NS_FAILED ( rv ) ) {
2001-08-21 06:20:53 +00:00
// 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 ) )
2006-02-03 14:18:39 +00:00
NS_EscapeURL ( NS_ConvertUTF16toUTF8 ( 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
{
2006-05-02 18:54:19 +00:00
* result = URI_NORELATIVE | URI_NOAUTH | URI_HAS_NO_SECURITY_CONTEXT ;
2001-08-07 20:42:57 +00:00
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 ;
2004-11-01 18:50:36 +00:00
rv = CallCreateInstance ( kSimpleURICID , & url ) ;
2002-09-02 22:15:07 +00:00
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 ;
}