2007-03-22 10:30:00 -07:00
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim : set ts = 2 sw = 4 et tw = 80 :
*
* * * * * * BEGIN LICENSE BLOCK * * * * *
* Version : MPL 1.1 / GPL 2.0 / LGPL 2.1
*
* 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/
*
* 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 .
*
* The Original Code is Mozilla Communicator client code , released
* March 31 , 1998.
*
* 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 .
*
* Contributor ( s ) :
* John Bandhauer < jband @ netscape . com >
* Pierre Phaneuf < pp @ ludusdesign . com >
* IBM Corp .
* Dan Mosedale < dan . mosedale @ oracle . com >
*
* Alternatively , the contents of this file may be used under the terms of
* 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 " ) ,
* 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 MPL , 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 MPL , the GPL or the LGPL .
*
* * * * * * END LICENSE BLOCK * * * * * */
/* XPConnect JavaScript interactive shell. */
# include <stdio.h>
2009-01-20 11:56:44 -08:00
# include "nsXULAppAPI.h"
2007-03-22 10:30:00 -07:00
# include "nsServiceManagerUtils.h"
# include "nsComponentManagerUtils.h"
2009-01-20 11:56:44 -08:00
# include "nsStringAPI.h"
2007-03-22 10:30:00 -07:00
# include "nsIXPConnect.h"
# include "nsIXPCScriptable.h"
# include "nsIInterfaceInfo.h"
# include "nsIInterfaceInfoManager.h"
# include "nsIXPCScriptable.h"
# include "nsIServiceManager.h"
# include "nsIComponentManager.h"
# include "nsIComponentRegistrar.h"
2009-01-18 09:01:15 -08:00
# include "nsILocalFile.h"
# include "nsStringAPI.h"
2009-01-20 11:56:44 -08:00
# include "nsIDirectoryService.h"
# include "nsILocalFile.h"
# include "nsDirectoryServiceDefs.h"
2007-03-22 10:30:00 -07:00
# include "jsapi.h"
2008-10-12 12:03:40 -07:00
# include "jsdbgapi.h"
2007-03-22 10:30:00 -07:00
# include "jsprf.h"
# include "nscore.h"
# include "nsMemory.h"
# include "nsIGenericFactory.h"
2009-01-20 11:56:44 -08:00
# include "nsISupportsImpl.h"
2007-03-22 10:30:00 -07:00
# include "nsIJSRuntimeService.h"
# include "nsCOMPtr.h"
2007-06-20 17:10:48 -07:00
# include "nsAutoPtr.h"
2007-03-22 10:30:00 -07:00
# include "nsIXPCSecurityManager.h"
2008-06-03 03:56:09 -07:00
# ifdef XP_MACOSX
# include "xpcshellMacUtils.h"
# endif
2009-01-18 09:01:15 -08:00
# ifdef XP_WIN
# include <windows.h>
# endif
2007-03-22 10:30:00 -07:00
# ifndef XPCONNECT_STANDALONE
# include "nsIScriptSecurityManager.h"
# include "nsIPrincipal.h"
# endif
// all this crap is needed to do the interactive shell stuff
# include <stdlib.h>
# include <errno.h>
2009-01-16 14:10:48 -08:00
# ifdef HAVE_IO_H
2007-03-22 10:30:00 -07:00
# include <io.h> /* for isatty() */
2009-01-16 14:10:48 -08:00
# endif
# ifdef HAVE_UNISTD_H
2007-03-22 10:30:00 -07:00
# include <unistd.h> /* for isatty() */
# endif
# include "nsIJSContextStack.h"
2009-01-20 11:56:44 -08:00
class XPCShellDirProvider : public nsIDirectoryServiceProvider
{
public :
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDIRECTORYSERVICEPROVIDER
XPCShellDirProvider ( ) { }
~ XPCShellDirProvider ( ) { }
PRBool SetGREDir ( const char * dir ) ;
void ClearGREDir ( ) { mGREDir = nsnull ; }
private :
nsCOMPtr < nsILocalFile > mGREDir ;
} ;
2007-03-22 10:30:00 -07:00
/***************************************************************************/
# ifdef JS_THREADSAFE
# define DoBeginRequest(cx) JS_BeginRequest((cx))
# define DoEndRequest(cx) JS_EndRequest((cx))
# else
# define DoBeginRequest(cx) ((void)0)
# define DoEndRequest(cx) ((void)0)
# endif
/***************************************************************************/
2009-01-18 09:01:15 -08:00
static const char kXPConnectServiceContractID [ ] = " @mozilla.org/js/xpc/XPConnect;1 " ;
2007-03-22 10:30:00 -07:00
# define EXITCODE_RUNTIME_ERROR 3
# define EXITCODE_FILE_NOT_FOUND 4
FILE * gOutFile = NULL ;
FILE * gErrFile = NULL ;
2008-11-27 18:25:35 -08:00
FILE * gInFile = NULL ;
2007-03-22 10:30:00 -07:00
int gExitCode = 0 ;
JSBool gQuitting = JS_FALSE ;
static JSBool reportWarnings = JS_TRUE ;
static JSBool compileOnly = JS_FALSE ;
JSPrincipals * gJSPrincipals = nsnull ;
2009-01-18 09:01:15 -08:00
nsAutoString * gWorkingDirectory = nsnull ;
static JSBool
GetLocationProperty ( JSContext * cx , JSObject * obj , jsval id , jsval * vp )
{
2009-02-01 01:03:41 -08:00
# if (!defined(XP_WIN) && !defined(XP_UNIX)) || defined(WINCE)
2009-01-18 09:01:15 -08:00
//XXX: your platform should really implement this
2009-01-30 01:19:43 -08:00
return JS_FALSE ;
# else
2009-01-18 09:01:15 -08:00
JSStackFrame * fp = JS_GetScriptedCaller ( cx , NULL ) ;
JSScript * script = JS_GetFrameScript ( cx , fp ) ;
const char * filename = JS_GetScriptFilename ( cx , script ) ;
if ( filename ) {
nsresult rv ;
nsCOMPtr < nsIXPConnect > xpc =
do_GetService ( kXPConnectServiceContractID , & rv ) ;
# if defined(XP_WIN)
// convert from the system codepage to UTF-16
int bufferSize = MultiByteToWideChar ( CP_ACP , 0 , filename ,
- 1 , NULL , 0 ) ;
nsAutoString filenameString ;
filenameString . SetLength ( bufferSize ) ;
MultiByteToWideChar ( CP_ACP , 0 , filename ,
- 1 , ( LPWSTR ) filenameString . BeginWriting ( ) ,
filenameString . Length ( ) ) ;
// remove the null terminator
filenameString . SetLength ( bufferSize - 1 ) ;
// replace forward slashes with backslashes,
// since nsLocalFileWin chokes on them
PRUnichar * start , * end ;
filenameString . BeginWriting ( & start , & end ) ;
while ( start ! = end ) {
if ( * start = = L ' / ' )
* start = L ' \\ ' ;
start + + ;
}
# elif defined(XP_UNIX)
NS_ConvertUTF8toUTF16 filenameString ( filename ) ;
# endif
nsCOMPtr < nsILocalFile > location ;
if ( NS_SUCCEEDED ( rv ) ) {
rv = NS_NewLocalFile ( filenameString ,
PR_FALSE , getter_AddRefs ( location ) ) ;
}
if ( ! location & & gWorkingDirectory ) {
// could be a relative path, try appending it to the cwd
// and then normalize
nsAutoString absolutePath ( * gWorkingDirectory ) ;
absolutePath . Append ( filenameString ) ;
rv = NS_NewLocalFile ( absolutePath ,
PR_FALSE , getter_AddRefs ( location ) ) ;
}
if ( location ) {
nsCOMPtr < nsIXPConnectJSObjectHolder > locationHolder ;
JSObject * locationObj = NULL ;
2009-02-02 05:53:23 -08:00
PRBool symlink ;
// don't normalize symlinks, because that's kind of confusing
if ( NS_SUCCEEDED ( location - > IsSymlink ( & symlink ) ) & &
! symlink )
location - > Normalize ( ) ;
2009-01-18 09:01:15 -08:00
rv = xpc - > WrapNative ( cx , obj , location ,
NS_GET_IID ( nsILocalFile ) ,
getter_AddRefs ( locationHolder ) ) ;
if ( NS_SUCCEEDED ( rv ) & &
NS_SUCCEEDED ( locationHolder - > GetJSObject ( & locationObj ) ) ) {
* vp = OBJECT_TO_JSVAL ( locationObj ) ;
}
}
}
return JS_TRUE ;
2009-01-30 01:19:43 -08:00
# endif
2009-01-18 09:01:15 -08:00
}
2007-03-22 10:30:00 -07:00
2008-11-27 18:25:35 -08:00
static JSBool
GetLine ( JSContext * cx , char * bufp , FILE * file , const char * prompt ) {
# ifdef EDITLINE
/*
* Use readline only if file is stdin , because there ' s no way to specify
* another handle . Are other filehandles interactive ?
*/
if ( file = = stdin ) {
char * linep = readline ( prompt ) ;
if ( ! linep )
return JS_FALSE ;
if ( * linep )
add_history ( linep ) ;
strcpy ( bufp , linep ) ;
JS_free ( cx , linep ) ;
bufp + = strlen ( bufp ) ;
* bufp + + = ' \n ' ;
* bufp = ' \0 ' ;
} else
# endif
{
char line [ 256 ] ;
fprintf ( gOutFile , prompt ) ;
fflush ( gOutFile ) ;
if ( ! fgets ( line , sizeof line , file ) )
return JS_FALSE ;
strcpy ( bufp , line ) ;
}
return JS_TRUE ;
}
2008-09-06 15:21:43 -07:00
static void
2007-03-22 10:30:00 -07:00
my_ErrorReporter ( JSContext * cx , const char * message , JSErrorReport * report )
{
int i , j , k , n ;
char * prefix = NULL , * tmp ;
const char * ctmp ;
2008-10-12 11:32:34 -07:00
JSStackFrame * fp = nsnull ;
nsCOMPtr < nsIXPConnect > xpc ;
// Don't report an exception from inner JS frames as the callers may intend
// to handle it.
while ( ( fp = JS_FrameIterator ( cx , & fp ) ) ) {
if ( ! JS_IsNativeFrame ( cx , fp ) ) {
return ;
}
}
// In some cases cx->fp is null here so use XPConnect to tell us about inner
// frames.
if ( ( xpc = do_GetService ( nsIXPConnect : : GetCID ( ) ) ) ) {
nsAXPCNativeCallContext * cc = nsnull ;
xpc - > GetCurrentNativeCallContext ( & cc ) ;
if ( cc ) {
nsAXPCNativeCallContext * prev = cc ;
while ( NS_SUCCEEDED ( prev - > GetPreviousCallContext ( & prev ) ) & & prev ) {
PRUint16 lang ;
if ( NS_SUCCEEDED ( prev - > GetLanguage ( & lang ) ) & &
lang = = nsAXPCNativeCallContext : : LANG_JS ) {
return ;
}
}
}
}
2007-03-22 10:30:00 -07:00
if ( ! report ) {
fprintf ( gErrFile , " %s \n " , message ) ;
return ;
}
/* Conditionally ignore reported warnings. */
if ( JSREPORT_IS_WARNING ( report - > flags ) & & ! reportWarnings )
return ;
if ( report - > filename )
prefix = JS_smprintf ( " %s: " , report - > filename ) ;
if ( report - > lineno ) {
tmp = prefix ;
prefix = JS_smprintf ( " %s%u: " , tmp ? tmp : " " , report - > lineno ) ;
JS_free ( cx , tmp ) ;
}
if ( JSREPORT_IS_WARNING ( report - > flags ) ) {
tmp = prefix ;
prefix = JS_smprintf ( " %s%swarning: " ,
tmp ? tmp : " " ,
JSREPORT_IS_STRICT ( report - > flags ) ? " strict " : " " ) ;
JS_free ( cx , tmp ) ;
}
/* embedded newlines -- argh! */
while ( ( ctmp = strchr ( message , ' \n ' ) ) ! = 0 ) {
ctmp + + ;
if ( prefix ) fputs ( prefix , gErrFile ) ;
fwrite ( message , 1 , ctmp - message , gErrFile ) ;
message = ctmp ;
}
/* If there were no filename or lineno, the prefix might be empty */
if ( prefix )
fputs ( prefix , gErrFile ) ;
fputs ( message , gErrFile ) ;
if ( ! report - > linebuf ) {
fputc ( ' \n ' , gErrFile ) ;
goto out ;
}
fprintf ( gErrFile , " : \n %s%s \n %s " , prefix , report - > linebuf , prefix ) ;
n = report - > tokenptr - report - > linebuf ;
for ( i = j = 0 ; i < n ; i + + ) {
if ( report - > linebuf [ i ] = = ' \t ' ) {
for ( k = ( j + 8 ) & ~ 7 ; j < k ; j + + ) {
fputc ( ' . ' , gErrFile ) ;
}
continue ;
}
fputc ( ' . ' , gErrFile ) ;
j + + ;
}
fputs ( " ^ \n " , gErrFile ) ;
out :
if ( ! JSREPORT_IS_WARNING ( report - > flags ) )
gExitCode = EXITCODE_RUNTIME_ERROR ;
JS_free ( cx , prefix ) ;
}
2008-11-27 18:25:35 -08:00
static JSBool
ReadLine ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
// While 4096 might be quite arbitrary, this is something to be fixed in
// bug 105707. It is also the same limit as in ProcessFile.
char buf [ 4096 ] ;
JSString * str ;
/* If a prompt was specified, construct the string */
if ( argc > 0 ) {
str = JS_ValueToString ( cx , argv [ 0 ] ) ;
if ( ! str )
return JS_FALSE ;
argv [ 0 ] = STRING_TO_JSVAL ( str ) ;
} else {
str = JSVAL_TO_STRING ( JS_GetEmptyStringValue ( cx ) ) ;
}
/* Get a line from the infile */
if ( ! GetLine ( cx , buf , gInFile , JS_GetStringBytes ( str ) ) )
return JS_FALSE ;
/* Strip newline character added by GetLine() */
unsigned int buflen = strlen ( buf ) ;
if ( buflen = = 0 ) {
if ( feof ( gInFile ) ) {
* rval = JSVAL_NULL ;
return JS_TRUE ;
}
} else if ( buf [ buflen - 1 ] = = ' \n ' ) {
- - buflen ;
}
/* Turn buf into a JSString */
str = JS_NewStringCopyN ( cx , buf , buflen ) ;
if ( ! str )
return JS_FALSE ;
* rval = STRING_TO_JSVAL ( str ) ;
return JS_TRUE ;
}
2008-09-06 15:21:43 -07:00
static JSBool
2007-03-22 10:30:00 -07:00
Print ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
uintN i , n ;
JSString * str ;
for ( i = n = 0 ; i < argc ; i + + ) {
str = JS_ValueToString ( cx , argv [ i ] ) ;
if ( ! str )
return JS_FALSE ;
fprintf ( gOutFile , " %s%s " , i ? " " : " " , JS_GetStringBytes ( str ) ) ;
}
n + + ;
if ( n )
fputc ( ' \n ' , gOutFile ) ;
return JS_TRUE ;
}
2008-09-06 15:21:43 -07:00
static JSBool
2007-03-22 10:30:00 -07:00
Dump ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
JSString * str ;
if ( ! argc )
return JS_TRUE ;
str = JS_ValueToString ( cx , argv [ 0 ] ) ;
if ( ! str )
return JS_FALSE ;
char * bytes = JS_GetStringBytes ( str ) ;
bytes = strdup ( bytes ) ;
fputs ( bytes , gOutFile ) ;
free ( bytes ) ;
return JS_TRUE ;
}
2008-09-06 15:21:43 -07:00
static JSBool
2007-03-22 10:30:00 -07:00
Load ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
uintN i ;
JSString * str ;
const char * filename ;
JSScript * script ;
JSBool ok ;
jsval result ;
2008-06-18 15:49:51 -07:00
FILE * file ;
2007-03-22 10:30:00 -07:00
for ( i = 0 ; i < argc ; i + + ) {
str = JS_ValueToString ( cx , argv [ i ] ) ;
if ( ! str )
return JS_FALSE ;
argv [ i ] = STRING_TO_JSVAL ( str ) ;
filename = JS_GetStringBytes ( str ) ;
2008-06-18 15:49:51 -07:00
file = fopen ( filename , " r " ) ;
script = JS_CompileFileHandleForPrincipals ( cx , obj , filename , file ,
gJSPrincipals ) ;
2009-02-15 08:23:50 -08:00
if ( file )
fclose ( file ) ;
2008-06-18 15:49:51 -07:00
if ( ! script )
2007-03-22 10:30:00 -07:00
ok = JS_FALSE ;
2008-06-18 15:49:51 -07:00
else {
2007-03-22 10:30:00 -07:00
ok = ! compileOnly
? JS_ExecuteScript ( cx , obj , script , & result )
: JS_TRUE ;
JS_DestroyScript ( cx , script ) ;
}
if ( ! ok )
return JS_FALSE ;
}
return JS_TRUE ;
}
2008-09-06 15:21:43 -07:00
static JSBool
2007-03-22 10:30:00 -07:00
Version ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
if ( argc > 0 & & JSVAL_IS_INT ( argv [ 0 ] ) )
* rval = INT_TO_JSVAL ( JS_SetVersion ( cx , JSVersion ( JSVAL_TO_INT ( argv [ 0 ] ) ) ) ) ;
else
* rval = INT_TO_JSVAL ( JS_GetVersion ( cx ) ) ;
return JS_TRUE ;
}
2008-09-06 15:21:43 -07:00
static JSBool
2007-03-22 10:30:00 -07:00
BuildDate ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
fprintf ( gOutFile , " built on %s at %s \n " , __DATE__ , __TIME__ ) ;
return JS_TRUE ;
}
2008-09-06 15:21:43 -07:00
static JSBool
2007-03-22 10:30:00 -07:00
Quit ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
# ifdef LIVECONNECT
JSJ_SimpleShutdown ( ) ;
# endif
gExitCode = 0 ;
JS_ConvertArguments ( cx , argc , argv , " / i " , & gExitCode ) ;
gQuitting = JS_TRUE ;
// exit(0);
return JS_FALSE ;
}
2008-09-06 15:21:43 -07:00
static JSBool
2007-03-22 10:30:00 -07:00
DumpXPC ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
int32 depth = 2 ;
if ( argc > 0 ) {
if ( ! JS_ValueToInt32 ( cx , argv [ 0 ] , & depth ) )
return JS_FALSE ;
}
nsCOMPtr < nsIXPConnect > xpc = do_GetService ( nsIXPConnect : : GetCID ( ) ) ;
if ( xpc )
xpc - > DebugDump ( ( int16 ) depth ) ;
return JS_TRUE ;
}
/* XXX needed only by GC() */
# include "jscntxt.h"
2008-09-06 15:21:43 -07:00
static JSBool
2007-03-22 10:30:00 -07:00
GC ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
JSRuntime * rt ;
uint32 preBytes ;
rt = cx - > runtime ;
preBytes = rt - > gcBytes ;
JS_GC ( cx ) ;
fprintf ( gOutFile , " before %lu, after %lu, break %08lx \n " ,
( unsigned long ) preBytes , ( unsigned long ) rt - > gcBytes ,
# ifdef XP_UNIX
( unsigned long ) sbrk ( 0 )
# else
0
# endif
) ;
# ifdef JS_GCMETER
js_DumpGCStats ( rt , stdout ) ;
# endif
return JS_TRUE ;
}
2007-04-25 06:43:18 -07:00
# ifdef DEBUG
static JSBool
DumpHeap ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
char * fileName = NULL ;
void * startThing = NULL ;
uint32 startTraceKind = 0 ;
void * thingToFind = NULL ;
size_t maxDepth = ( size_t ) - 1 ;
void * thingToIgnore = NULL ;
jsval * vp ;
FILE * dumpFile ;
JSBool ok ;
vp = & argv [ 0 ] ;
if ( * vp ! = JSVAL_NULL & & * vp ! = JSVAL_VOID ) {
JSString * str ;
str = JS_ValueToString ( cx , * vp ) ;
if ( ! str )
return JS_FALSE ;
* vp = STRING_TO_JSVAL ( str ) ;
fileName = JS_GetStringBytes ( str ) ;
}
vp = & argv [ 1 ] ;
if ( * vp ! = JSVAL_NULL & & * vp ! = JSVAL_VOID ) {
if ( ! JSVAL_IS_TRACEABLE ( * vp ) )
goto not_traceable_arg ;
startThing = JSVAL_TO_TRACEABLE ( * vp ) ;
startTraceKind = JSVAL_TRACE_KIND ( * vp ) ;
}
vp = & argv [ 2 ] ;
if ( * vp ! = JSVAL_NULL & & * vp ! = JSVAL_VOID ) {
if ( ! JSVAL_IS_TRACEABLE ( * vp ) )
goto not_traceable_arg ;
thingToFind = JSVAL_TO_TRACEABLE ( * vp ) ;
}
vp = & argv [ 3 ] ;
if ( * vp ! = JSVAL_NULL & & * vp ! = JSVAL_VOID ) {
uint32 depth ;
if ( ! JS_ValueToECMAUint32 ( cx , * vp , & depth ) )
return JS_FALSE ;
maxDepth = depth ;
}
vp = & argv [ 4 ] ;
if ( * vp ! = JSVAL_NULL & & * vp ! = JSVAL_VOID ) {
if ( ! JSVAL_IS_TRACEABLE ( * vp ) )
goto not_traceable_arg ;
thingToIgnore = JSVAL_TO_TRACEABLE ( * vp ) ;
}
if ( ! fileName ) {
dumpFile = gOutFile ;
} else {
dumpFile = fopen ( fileName , " w " ) ;
if ( ! dumpFile ) {
fprintf ( gErrFile , " dumpHeap: can't open %s: %s \n " ,
fileName , strerror ( errno ) ) ;
return JS_FALSE ;
}
}
2007-04-29 14:49:00 -07:00
ok = JS_DumpHeap ( cx , dumpFile , startThing , startTraceKind , thingToFind ,
maxDepth , thingToIgnore ) ;
2007-04-25 06:43:18 -07:00
if ( dumpFile ! = gOutFile )
fclose ( dumpFile ) ;
return ok ;
not_traceable_arg :
fprintf ( gErrFile ,
" dumpHeap: argument %u is not null or a heap-allocated thing \n " ,
( unsigned ) ( vp - argv ) ) ;
return JS_FALSE ;
}
# endif /* DEBUG */
2008-09-06 15:21:43 -07:00
static JSBool
2007-03-22 10:30:00 -07:00
Clear ( JSContext * cx , JSObject * obj , uintN argc , jsval * argv , jsval * rval )
{
if ( argc > 0 & & ! JSVAL_IS_PRIMITIVE ( argv [ 0 ] ) ) {
JS_ClearScope ( cx , JSVAL_TO_OBJECT ( argv [ 0 ] ) ) ;
} else {
JS_ReportError ( cx , " 'clear' requires an object " ) ;
return JS_FALSE ;
}
return JS_TRUE ;
}
static JSFunctionSpec glob_functions [ ] = {
{ " print " , Print , 0 , 0 , 0 } ,
2008-11-27 18:25:35 -08:00
{ " readline " , ReadLine , 1 , 0 , 0 } ,
2007-03-22 10:30:00 -07:00
{ " load " , Load , 1 , 0 , 0 } ,
{ " quit " , Quit , 0 , 0 , 0 } ,
{ " version " , Version , 1 , 0 , 0 } ,
{ " build " , BuildDate , 0 , 0 , 0 } ,
{ " dumpXPC " , DumpXPC , 1 , 0 , 0 } ,
{ " dump " , Dump , 1 , 0 , 0 } ,
{ " gc " , GC , 0 , 0 , 0 } ,
{ " clear " , Clear , 1 , 0 , 0 } ,
2007-04-25 06:43:18 -07:00
# ifdef DEBUG
{ " dumpHeap " , DumpHeap , 5 , 0 , 0 } ,
2008-01-16 12:42:50 -08:00
# endif
# ifdef MOZ_SHARK
2008-01-21 22:37:53 -08:00
{ " startShark " , js_StartShark , 0 , 0 , 0 } ,
{ " stopShark " , js_StopShark , 0 , 0 , 0 } ,
{ " connectShark " , js_ConnectShark , 0 , 0 , 0 } ,
{ " disconnectShark " , js_DisconnectShark , 0 , 0 , 0 } ,
2008-07-08 15:58:08 -07:00
# endif
# ifdef MOZ_CALLGRIND
{ " startCallgrind " , js_StartCallgrind , 0 , 0 , 0 } ,
{ " stopCallgrind " , js_StopCallgrind , 0 , 0 , 0 } ,
{ " dumpCallgrind " , js_DumpCallgrind , 1 , 0 , 0 } ,
2007-04-25 06:43:18 -07:00
# endif
2007-03-22 10:30:00 -07:00
{ nsnull , nsnull , 0 , 0 , 0 }
} ;
JSClass global_class = {
" global " , 0 ,
JS_PropertyStub , JS_PropertyStub , JS_PropertyStub , JS_PropertyStub ,
JS_EnumerateStub , JS_ResolveStub , JS_ConvertStub , JS_FinalizeStub
} ;
static JSBool
env_setProperty ( JSContext * cx , JSObject * obj , jsval id , jsval * vp )
{
/* XXX porting may be easy, but these don't seem to supply setenv by default */
# if !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS
JSString * idstr , * valstr ;
const char * name , * value ;
int rv ;
idstr = JS_ValueToString ( cx , id ) ;
valstr = JS_ValueToString ( cx , * vp ) ;
if ( ! idstr | | ! valstr )
return JS_FALSE ;
name = JS_GetStringBytes ( idstr ) ;
value = JS_GetStringBytes ( valstr ) ;
# if defined XP_WIN || defined HPUX || defined OSF1 || defined IRIX \
| | defined SCO
{
char * waste = JS_smprintf ( " %s=%s " , name , value ) ;
if ( ! waste ) {
JS_ReportOutOfMemory ( cx ) ;
return JS_FALSE ;
}
rv = putenv ( waste ) ;
# ifdef XP_WIN
/*
* HPUX9 at least still has the bad old non - copying putenv .
*
* Per mail from < s . shanmuganathan @ digital . com > , OSF1 also has a putenv
* that will crash if you pass it an auto char array ( so it must place
* its argument directly in the char * environ [ ] array ) .
*/
free ( waste ) ;
# endif
}
# else
rv = setenv ( name , value , 1 ) ;
# endif
if ( rv < 0 ) {
JS_ReportError ( cx , " can't set envariable %s to %s " , name , value ) ;
return JS_FALSE ;
}
* vp = STRING_TO_JSVAL ( valstr ) ;
# endif /* !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS */
return JS_TRUE ;
}
static JSBool
env_enumerate ( JSContext * cx , JSObject * obj )
{
static JSBool reflected ;
char * * evp , * name , * value ;
JSString * valstr ;
JSBool ok ;
if ( reflected )
return JS_TRUE ;
for ( evp = ( char * * ) JS_GetPrivate ( cx , obj ) ; ( name = * evp ) ! = NULL ; evp + + ) {
value = strchr ( name , ' = ' ) ;
if ( ! value )
continue ;
* value + + = ' \0 ' ;
valstr = JS_NewStringCopyZ ( cx , value ) ;
if ( ! valstr ) {
ok = JS_FALSE ;
} else {
ok = JS_DefineProperty ( cx , obj , name , STRING_TO_JSVAL ( valstr ) ,
NULL , NULL , JSPROP_ENUMERATE ) ;
}
value [ - 1 ] = ' = ' ;
if ( ! ok )
return JS_FALSE ;
}
reflected = JS_TRUE ;
return JS_TRUE ;
}
static JSBool
env_resolve ( JSContext * cx , JSObject * obj , jsval id , uintN flags ,
JSObject * * objp )
{
JSString * idstr , * valstr ;
const char * name , * value ;
if ( flags & JSRESOLVE_ASSIGNING )
return JS_TRUE ;
idstr = JS_ValueToString ( cx , id ) ;
if ( ! idstr )
return JS_FALSE ;
name = JS_GetStringBytes ( idstr ) ;
value = getenv ( name ) ;
if ( value ) {
valstr = JS_NewStringCopyZ ( cx , value ) ;
if ( ! valstr )
return JS_FALSE ;
if ( ! JS_DefineProperty ( cx , obj , name , STRING_TO_JSVAL ( valstr ) ,
NULL , NULL , JSPROP_ENUMERATE ) ) {
return JS_FALSE ;
}
* objp = obj ;
}
return JS_TRUE ;
}
static JSClass env_class = {
" environment " , JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE ,
JS_PropertyStub , JS_PropertyStub ,
JS_PropertyStub , env_setProperty ,
env_enumerate , ( JSResolveOp ) env_resolve ,
JS_ConvertStub , JS_FinalizeStub
} ;
/***************************************************************************/
typedef enum JSShellErrNum {
# define MSG_DEF(name, number, count, exception, format) \
name = number ,
# include "jsshell.msg"
# undef MSG_DEF
JSShellErr_Limit
# undef MSGDEF
} JSShellErrNum ;
JSErrorFormatString jsShell_ErrorFormatString [ JSErr_Limit ] = {
# define MSG_DEF(name, number, count, exception, format) \
{ format , count } ,
# include "jsshell.msg"
# undef MSG_DEF
} ;
2008-09-06 15:21:43 -07:00
static const JSErrorFormatString *
2007-03-22 10:30:00 -07:00
my_GetErrorMessage ( void * userRef , const char * locale , const uintN errorNumber )
{
if ( ( errorNumber > 0 ) & & ( errorNumber < JSShellErr_Limit ) )
return & jsShell_ErrorFormatString [ errorNumber ] ;
else
return NULL ;
}
# ifdef EDITLINE
extern " C " {
extern char * readline ( const char * prompt ) ;
extern void add_history ( char * line ) ;
}
# endif
static void
ProcessFile ( JSContext * cx , JSObject * obj , const char * filename , FILE * file ,
JSBool forceTTY )
{
JSScript * script ;
jsval result ;
int lineno , startline ;
JSBool ok , hitEOF ;
char * bufp , buffer [ 4096 ] ;
JSString * str ;
if ( forceTTY ) {
file = stdin ;
2009-01-16 14:10:48 -08:00
}
# ifdef HAVE_ISATTY
else if ( ! isatty ( fileno ( file ) ) ) {
2007-03-22 10:30:00 -07:00
/*
* It ' s not interactive - just execute it .
*
* Support the UNIX # ! shell hack ; gobble the first line if it starts
* with ' # ' . TODO - this isn ' t quite compatible with sharp variables ,
* as a legal js program ( using sharp variables ) might start with ' # ' .
* But that would require multi - character lookahead .
*/
int ch = fgetc ( file ) ;
if ( ch = = ' # ' ) {
while ( ( ch = fgetc ( file ) ) ! = EOF ) {
if ( ch = = ' \n ' | | ch = = ' \r ' )
break ;
}
}
ungetc ( ch , file ) ;
DoBeginRequest ( cx ) ;
script = JS_CompileFileHandleForPrincipals ( cx , obj , filename , file ,
gJSPrincipals ) ;
if ( script ) {
if ( ! compileOnly )
( void ) JS_ExecuteScript ( cx , obj , script , & result ) ;
JS_DestroyScript ( cx , script ) ;
}
DoEndRequest ( cx ) ;
return ;
}
2009-01-16 14:10:48 -08:00
# endif
2007-03-22 10:30:00 -07:00
/* It's an interactive filehandle; drop into read-eval-print loop. */
lineno = 1 ;
hitEOF = JS_FALSE ;
do {
bufp = buffer ;
* bufp = ' \0 ' ;
/*
* Accumulate lines until we get a ' compilable unit ' - one that either
* generates an error ( before running out of source ) or that compiles
* cleanly . This should be whenever we get a complete statement that
* coincides with the end of a line .
*/
startline = lineno ;
do {
if ( ! GetLine ( cx , bufp , file , startline = = lineno ? " js> " : " " ) ) {
hitEOF = JS_TRUE ;
break ;
}
bufp + = strlen ( bufp ) ;
lineno + + ;
} while ( ! JS_BufferIsCompilableUnit ( cx , obj , buffer , strlen ( buffer ) ) ) ;
DoBeginRequest ( cx ) ;
/* Clear any pending exception from previous failed compiles. */
JS_ClearPendingException ( cx ) ;
script = JS_CompileScriptForPrincipals ( cx , obj , gJSPrincipals , buffer ,
strlen ( buffer ) , " typein " , startline ) ;
if ( script ) {
JSErrorReporter older ;
if ( ! compileOnly ) {
ok = JS_ExecuteScript ( cx , obj , script , & result ) ;
if ( ok & & result ! = JSVAL_VOID ) {
/* Suppress error reports from JS_ValueToString(). */
older = JS_SetErrorReporter ( cx , NULL ) ;
str = JS_ValueToString ( cx , result ) ;
JS_SetErrorReporter ( cx , older ) ;
if ( str )
fprintf ( gOutFile , " %s \n " , JS_GetStringBytes ( str ) ) ;
else
ok = JS_FALSE ;
}
}
JS_DestroyScript ( cx , script ) ;
}
DoEndRequest ( cx ) ;
} while ( ! hitEOF & & ! gQuitting ) ;
fprintf ( gOutFile , " \n " ) ;
}
static void
Process ( JSContext * cx , JSObject * obj , const char * filename , JSBool forceTTY )
{
FILE * file ;
if ( forceTTY | | ! filename | | strcmp ( filename , " - " ) = = 0 ) {
file = stdin ;
} else {
file = fopen ( filename , " r " ) ;
if ( ! file ) {
JS_ReportErrorNumber ( cx , my_GetErrorMessage , NULL ,
JSSMSG_CANT_OPEN ,
filename , strerror ( errno ) ) ;
gExitCode = EXITCODE_FILE_NOT_FOUND ;
return ;
}
}
ProcessFile ( cx , obj , filename , file , forceTTY ) ;
2009-02-15 08:23:50 -08:00
if ( file ! = stdin )
fclose ( file ) ;
2007-03-22 10:30:00 -07:00
}
static int
usage ( void )
{
fprintf ( gErrFile , " %s \n " , JS_GetImplementationVersion ( ) ) ;
2009-01-20 11:56:44 -08:00
fprintf ( gErrFile , " usage: xpcshell [-g gredir] [-PswWxCij] [-v version] [-f scriptfile] [-e script] [scriptfile] [scriptarg...] \n " ) ;
2007-03-22 10:30:00 -07:00
return 2 ;
}
extern JSClass global_class ;
static int
ProcessArgs ( JSContext * cx , JSObject * obj , char * * argv , int argc )
{
const char rcfilename [ ] = " xpcshell.js " ;
FILE * rcfile ;
int i , j , length ;
JSObject * argsObj ;
char * filename = NULL ;
JSBool isInteractive = JS_TRUE ;
JSBool forceTTY = JS_FALSE ;
rcfile = fopen ( rcfilename , " r " ) ;
if ( rcfile ) {
printf ( " [loading '%s'...] \n " , rcfilename ) ;
ProcessFile ( cx , obj , rcfilename , rcfile , JS_FALSE ) ;
2009-02-15 08:23:50 -08:00
fclose ( rcfile ) ;
2007-03-22 10:30:00 -07:00
}
/*
* Scan past all optional arguments so we can create the arguments object
* before processing any - f options , which must interleave properly with
* - v and - w options . This requires two passes , and without getopt , we ' ll
* have to keep the option logic here and in the second for loop in sync .
*/
for ( i = 0 ; i < argc ; i + + ) {
if ( argv [ i ] [ 0 ] ! = ' - ' | | argv [ i ] [ 1 ] = = ' \0 ' ) {
+ + i ;
break ;
}
switch ( argv [ i ] [ 1 ] ) {
case ' v ' :
case ' f ' :
case ' e ' :
+ + i ;
break ;
default : ;
}
}
/*
* Create arguments early and define it to root it , so it ' s safe from any
* GC calls nested below , and so it is available to - f < file > arguments .
*/
argsObj = JS_NewArrayObject ( cx , 0 , NULL ) ;
if ( ! argsObj )
return 1 ;
if ( ! JS_DefineProperty ( cx , obj , " arguments " , OBJECT_TO_JSVAL ( argsObj ) ,
NULL , NULL , 0 ) ) {
return 1 ;
}
length = argc - i ;
for ( j = 0 ; j < length ; j + + ) {
JSString * str = JS_NewStringCopyZ ( cx , argv [ i + + ] ) ;
if ( ! str )
return 1 ;
if ( ! JS_DefineElement ( cx , argsObj , j , STRING_TO_JSVAL ( str ) ,
NULL , NULL , JSPROP_ENUMERATE ) ) {
return 1 ;
}
}
for ( i = 0 ; i < argc ; i + + ) {
if ( argv [ i ] [ 0 ] ! = ' - ' | | argv [ i ] [ 1 ] = = ' \0 ' ) {
filename = argv [ i + + ] ;
isInteractive = JS_FALSE ;
break ;
}
switch ( argv [ i ] [ 1 ] ) {
case ' v ' :
if ( + + i = = argc ) {
return usage ( ) ;
}
JS_SetVersion ( cx , JSVersion ( atoi ( argv [ i ] ) ) ) ;
break ;
case ' W ' :
reportWarnings = JS_FALSE ;
break ;
case ' w ' :
reportWarnings = JS_TRUE ;
break ;
case ' s ' :
JS_ToggleOptions ( cx , JSOPTION_STRICT ) ;
break ;
case ' x ' :
JS_ToggleOptions ( cx , JSOPTION_XML ) ;
break ;
case ' P ' :
if ( JS_GET_CLASS ( cx , JS_GetPrototype ( cx , obj ) ) ! = & global_class ) {
JSObject * gobj ;
if ( ! JS_SealObject ( cx , obj , JS_TRUE ) )
return JS_FALSE ;
gobj = JS_NewObject ( cx , & global_class , NULL , NULL ) ;
if ( ! gobj )
return JS_FALSE ;
if ( ! JS_SetPrototype ( cx , gobj , obj ) )
return JS_FALSE ;
JS_SetParent ( cx , gobj , NULL ) ;
JS_SetGlobalObject ( cx , gobj ) ;
obj = gobj ;
}
break ;
case ' f ' :
if ( + + i = = argc ) {
return usage ( ) ;
}
Process ( cx , obj , argv [ i ] , JS_FALSE ) ;
/*
* XXX : js - f foo . js should interpret foo . js and then
* drop into interactive mode , but that breaks test
* harness . Just execute foo . js for now .
*/
isInteractive = JS_FALSE ;
break ;
case ' i ' :
isInteractive = forceTTY = JS_TRUE ;
break ;
case ' e ' :
{
jsval rval ;
if ( + + i = = argc ) {
return usage ( ) ;
}
JS_EvaluateScript ( cx , obj , argv [ i ] , strlen ( argv [ i ] ) ,
" -e " , 1 , & rval ) ;
isInteractive = JS_FALSE ;
break ;
}
case ' C ' :
compileOnly = JS_TRUE ;
isInteractive = JS_FALSE ;
break ;
2008-08-09 15:36:17 -07:00
case ' j ' :
JS_ToggleOptions ( cx , JSOPTION_JIT ) ;
break ;
2008-01-16 12:42:50 -08:00
# ifdef MOZ_SHARK
case ' k ' :
2008-01-19 15:33:08 -08:00
JS_ConnectShark ( ) ;
2008-01-16 12:42:50 -08:00
break ;
# endif
2007-03-22 10:30:00 -07:00
default :
return usage ( ) ;
}
}
if ( filename | | isInteractive )
Process ( cx , obj , filename , forceTTY ) ;
return gExitCode ;
}
/***************************************************************************/
2007-06-20 17:10:48 -07:00
class FullTrustSecMan
# ifndef XPCONNECT_STANDALONE
: public nsIScriptSecurityManager
# else
: public nsIXPCSecurityManager
# endif
2007-03-22 10:30:00 -07:00
{
public :
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCSECURITYMANAGER
2007-06-20 17:10:48 -07:00
# ifndef XPCONNECT_STANDALONE
NS_DECL_NSISCRIPTSECURITYMANAGER
# endif
2007-03-22 10:30:00 -07:00
FullTrustSecMan ( ) ;
2007-06-20 17:10:48 -07:00
virtual ~ FullTrustSecMan ( ) ;
# ifndef XPCONNECT_STANDALONE
void SetSystemPrincipal ( nsIPrincipal * aPrincipal ) {
mSystemPrincipal = aPrincipal ;
}
private :
nsCOMPtr < nsIPrincipal > mSystemPrincipal ;
# endif
2007-03-22 10:30:00 -07:00
} ;
2007-06-20 17:10:48 -07:00
NS_INTERFACE_MAP_BEGIN ( FullTrustSecMan )
NS_INTERFACE_MAP_ENTRY ( nsIXPCSecurityManager )
# ifndef XPCONNECT_STANDALONE
NS_INTERFACE_MAP_ENTRY ( nsIScriptSecurityManager )
# endif
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS ( nsISupports , nsIXPCSecurityManager )
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF ( FullTrustSecMan )
NS_IMPL_RELEASE ( FullTrustSecMan )
2007-03-22 10:30:00 -07:00
FullTrustSecMan : : FullTrustSecMan ( )
{
2007-06-20 17:10:48 -07:00
# ifndef XPCONNECT_STANDALONE
mSystemPrincipal = nsnull ;
# endif
}
FullTrustSecMan : : ~ FullTrustSecMan ( )
{
2007-03-22 10:30:00 -07:00
}
NS_IMETHODIMP
2007-06-20 17:10:48 -07:00
FullTrustSecMan : : CanCreateWrapper ( JSContext * aJSContext , const nsIID & aIID ,
nsISupports * aObj , nsIClassInfo * aClassInfo ,
void * * aPolicy )
2007-03-22 10:30:00 -07:00
{
return NS_OK ;
}
NS_IMETHODIMP
FullTrustSecMan : : CanCreateInstance ( JSContext * aJSContext , const nsCID & aCID )
{
return NS_OK ;
}
NS_IMETHODIMP
FullTrustSecMan : : CanGetService ( JSContext * aJSContext , const nsCID & aCID )
{
return NS_OK ;
}
2007-06-20 17:10:48 -07:00
# ifndef XPCONNECT_STANDALONE
2007-03-22 10:30:00 -07:00
/* void CanAccess (in PRUint32 aAction, in nsIXPCNativeCallContext aCallContext, in JSContextPtr aJSContext, in JSObjectPtr aJSObject, in nsISupports aObj, in nsIClassInfo aClassInfo, in JSVal aName, inout voidPtr aPolicy); */
2007-06-20 17:10:48 -07:00
NS_IMETHODIMP
FullTrustSecMan : : CanAccess ( PRUint32 aAction ,
2008-01-15 07:50:57 -08:00
nsAXPCNativeCallContext * aCallContext ,
2007-06-20 17:10:48 -07:00
JSContext * aJSContext , JSObject * aJSObject ,
nsISupports * aObj , nsIClassInfo * aClassInfo ,
jsval aName , void * * aPolicy )
{
return NS_OK ;
}
/* [noscript] void checkPropertyAccess (in JSContextPtr aJSContext, in JSObjectPtr aJSObject, in string aClassName, in JSVal aProperty, in PRUint32 aAction); */
NS_IMETHODIMP
FullTrustSecMan : : CheckPropertyAccess ( JSContext * aJSContext ,
JSObject * aJSObject ,
const char * aClassName ,
jsval aProperty , PRUint32 aAction )
2007-03-22 10:30:00 -07:00
{
return NS_OK ;
}
2008-04-18 10:51:10 -07:00
/* [noscript] void checkConnect (in JSContextPtr aJSContext, in nsIURI aTargetURI, in string aClassName, in string aProperty); */
NS_IMETHODIMP
FullTrustSecMan : : CheckConnect ( JSContext * aJSContext , nsIURI * aTargetURI ,
const char * aClassName , const char * aProperty )
{
return NS_OK ;
}
2007-06-20 17:10:48 -07:00
/* [noscript] void checkLoadURIFromScript (in JSContextPtr cx, in nsIURI uri); */
NS_IMETHODIMP
FullTrustSecMan : : CheckLoadURIFromScript ( JSContext * cx , nsIURI * uri )
{
return NS_OK ;
}
/* void checkLoadURIWithPrincipal (in nsIPrincipal aPrincipal, in nsIURI uri, in unsigned long flags); */
NS_IMETHODIMP
FullTrustSecMan : : CheckLoadURIWithPrincipal ( nsIPrincipal * aPrincipal ,
nsIURI * uri , PRUint32 flags )
{
return NS_OK ;
}
/* void checkLoadURI (in nsIURI from, in nsIURI uri, in unsigned long flags); */
NS_IMETHODIMP
FullTrustSecMan : : CheckLoadURI ( nsIURI * from , nsIURI * uri , PRUint32 flags )
{
return NS_OK ;
}
/* void checkLoadURIStrWithPrincipal (in nsIPrincipal aPrincipal, in AUTF8String uri, in unsigned long flags); */
NS_IMETHODIMP
FullTrustSecMan : : CheckLoadURIStrWithPrincipal ( nsIPrincipal * aPrincipal ,
const nsACString & uri ,
PRUint32 flags )
{
return NS_OK ;
}
/* void checkLoadURIStr (in AUTF8String from, in AUTF8String uri, in unsigned long flags); */
NS_IMETHODIMP
FullTrustSecMan : : CheckLoadURIStr ( const nsACString & from ,
const nsACString & uri , PRUint32 flags )
{
return NS_OK ;
}
/* [noscript] void checkFunctionAccess (in JSContextPtr cx, in voidPtr funObj, in voidPtr targetObj); */
NS_IMETHODIMP
FullTrustSecMan : : CheckFunctionAccess ( JSContext * cx , void * funObj ,
void * targetObj )
{
return NS_OK ;
}
/* [noscript] boolean canExecuteScripts (in JSContextPtr cx, in nsIPrincipal principal); */
NS_IMETHODIMP
FullTrustSecMan : : CanExecuteScripts ( JSContext * cx , nsIPrincipal * principal ,
PRBool * _retval )
{
* _retval = PR_TRUE ;
return NS_OK ;
}
/* [noscript] nsIPrincipal getSubjectPrincipal (); */
NS_IMETHODIMP
FullTrustSecMan : : GetSubjectPrincipal ( nsIPrincipal * * _retval )
{
NS_IF_ADDREF ( * _retval = mSystemPrincipal ) ;
return * _retval ? NS_OK : NS_ERROR_FAILURE ;
}
/* [noscript] nsIPrincipal getSystemPrincipal (); */
NS_IMETHODIMP
FullTrustSecMan : : GetSystemPrincipal ( nsIPrincipal * * _retval )
{
NS_IF_ADDREF ( * _retval = mSystemPrincipal ) ;
return * _retval ? NS_OK : NS_ERROR_FAILURE ;
}
/* [noscript] nsIPrincipal getCertificatePrincipal (in AUTF8String aCertFingerprint, in AUTF8String aSubjectName, in AUTF8String aPrettyName, in nsISupports aCert, in nsIURI aURI); */
NS_IMETHODIMP
FullTrustSecMan : : GetCertificatePrincipal ( const nsACString & aCertFingerprint ,
const nsACString & aSubjectName ,
const nsACString & aPrettyName ,
nsISupports * aCert , nsIURI * aURI ,
nsIPrincipal * * _retval )
{
NS_IF_ADDREF ( * _retval = mSystemPrincipal ) ;
return * _retval ? NS_OK : NS_ERROR_FAILURE ;
}
/* [noscript] nsIPrincipal getCodebasePrincipal (in nsIURI aURI); */
NS_IMETHODIMP
FullTrustSecMan : : GetCodebasePrincipal ( nsIURI * aURI , nsIPrincipal * * _retval )
{
NS_IF_ADDREF ( * _retval = mSystemPrincipal ) ;
return * _retval ? NS_OK : NS_ERROR_FAILURE ;
}
/* [noscript] short requestCapability (in nsIPrincipal principal, in string capability); */
NS_IMETHODIMP
FullTrustSecMan : : RequestCapability ( nsIPrincipal * principal ,
const char * capability , PRInt16 * _retval )
{
* _retval = nsIPrincipal : : ENABLE_GRANTED ;
return NS_OK ;
}
/* boolean isCapabilityEnabled (in string capability); */
NS_IMETHODIMP
FullTrustSecMan : : IsCapabilityEnabled ( const char * capability , PRBool * _retval )
{
* _retval = PR_TRUE ;
return NS_OK ;
}
/* void enableCapability (in string capability); */
NS_IMETHODIMP
FullTrustSecMan : : EnableCapability ( const char * capability )
{
return NS_OK ; ;
}
/* void revertCapability (in string capability); */
NS_IMETHODIMP
FullTrustSecMan : : RevertCapability ( const char * capability )
{
return NS_OK ;
}
/* void disableCapability (in string capability); */
NS_IMETHODIMP
FullTrustSecMan : : DisableCapability ( const char * capability )
{
return NS_OK ;
}
/* void setCanEnableCapability (in AUTF8String certificateFingerprint, in string capability, in short canEnable); */
NS_IMETHODIMP
FullTrustSecMan : : SetCanEnableCapability ( const nsACString & certificateFingerprint ,
const char * capability ,
PRInt16 canEnable )
{
return NS_OK ;
}
/* [noscript] nsIPrincipal getObjectPrincipal (in JSContextPtr cx, in JSObjectPtr obj); */
NS_IMETHODIMP
FullTrustSecMan : : GetObjectPrincipal ( JSContext * cx , JSObject * obj ,
nsIPrincipal * * _retval )
{
NS_IF_ADDREF ( * _retval = mSystemPrincipal ) ;
return * _retval ? NS_OK : NS_ERROR_FAILURE ;
}
/* [noscript] boolean subjectPrincipalIsSystem (); */
NS_IMETHODIMP
FullTrustSecMan : : SubjectPrincipalIsSystem ( PRBool * _retval )
{
* _retval = PR_TRUE ;
return NS_OK ;
}
/* [noscript] void checkSameOrigin (in JSContextPtr aJSContext, in nsIURI aTargetURI); */
NS_IMETHODIMP
FullTrustSecMan : : CheckSameOrigin ( JSContext * aJSContext , nsIURI * aTargetURI )
{
return NS_OK ;
}
/* void checkSameOriginURI (in nsIURI aSourceURI, in nsIURI aTargetURI); */
NS_IMETHODIMP
2007-10-26 18:46:09 -07:00
FullTrustSecMan : : CheckSameOriginURI ( nsIURI * aSourceURI , nsIURI * aTargetURI ,
PRBool reportError )
2007-06-20 17:10:48 -07:00
{
return NS_OK ;
}
/* [noscript] nsIPrincipal getPrincipalFromContext (in JSContextPtr cx); */
NS_IMETHODIMP
FullTrustSecMan : : GetPrincipalFromContext ( JSContext * cx , nsIPrincipal * * _retval )
{
NS_IF_ADDREF ( * _retval = mSystemPrincipal ) ;
return * _retval ? NS_OK : NS_ERROR_FAILURE ;
}
/* [noscript] nsIPrincipal getChannelPrincipal (in nsIChannel aChannel); */
NS_IMETHODIMP
FullTrustSecMan : : GetChannelPrincipal ( nsIChannel * aChannel , nsIPrincipal * * _retval )
{
NS_IF_ADDREF ( * _retval = mSystemPrincipal ) ;
return * _retval ? NS_OK : NS_ERROR_FAILURE ;
}
/* boolean isSystemPrincipal (in nsIPrincipal aPrincipal); */
NS_IMETHODIMP
FullTrustSecMan : : IsSystemPrincipal ( nsIPrincipal * aPrincipal , PRBool * _retval )
{
* _retval = aPrincipal = = mSystemPrincipal ;
return NS_OK ;
}
2008-01-04 15:59:12 -08:00
NS_IMETHODIMP_ ( nsIPrincipal * )
FullTrustSecMan : : GetCxSubjectPrincipal ( JSContext * cx )
{
return mSystemPrincipal ;
}
2008-10-22 13:15:22 -07:00
NS_IMETHODIMP_ ( nsIPrincipal * )
FullTrustSecMan : : GetCxSubjectPrincipalAndFrame ( JSContext * cx , JSStackFrame * * fp )
{
* fp = nsnull ;
return mSystemPrincipal ;
}
2007-06-20 17:10:48 -07:00
# endif
2007-03-22 10:30:00 -07:00
/***************************************************************************/
// #define TEST_InitClassesWithNewWrappedGlobal
# ifdef TEST_InitClassesWithNewWrappedGlobal
// XXX hacky test code...
# include "xpctest.h"
class TestGlobal : public nsIXPCTestNoisy , public nsIXPCScriptable
{
public :
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCTESTNOISY
NS_DECL_NSIXPCSCRIPTABLE
TestGlobal ( ) { }
} ;
NS_IMPL_ISUPPORTS2 ( TestGlobal , nsIXPCTestNoisy , nsIXPCScriptable )
// The nsIXPCScriptable map declaration that will generate stubs for us...
# define XPC_MAP_CLASSNAME TestGlobal
# define XPC_MAP_QUOTED_CLASSNAME "TestGlobal"
# define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY |\
nsIXPCScriptable : : USE_JSSTUB_FOR_DELPROPERTY | \
nsIXPCScriptable : : USE_JSSTUB_FOR_SETPROPERTY
# include "xpc_map_end.h" /* This will #undef the above */
NS_IMETHODIMP TestGlobal : : Squawk ( ) { return NS_OK ; }
# endif
// uncomment to install the test 'this' translator
// #define TEST_TranslateThis
# ifdef TEST_TranslateThis
# include "xpctest.h"
class nsXPCFunctionThisTranslator : public nsIXPCFunctionThisTranslator
{
public :
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCFUNCTIONTHISTRANSLATOR
nsXPCFunctionThisTranslator ( ) ;
virtual ~ nsXPCFunctionThisTranslator ( ) ;
/* additional members */
} ;
/* Implementation file */
NS_IMPL_ISUPPORTS1 ( nsXPCFunctionThisTranslator , nsIXPCFunctionThisTranslator )
nsXPCFunctionThisTranslator : : nsXPCFunctionThisTranslator ( )
{
/* member initializers and constructor code */
}
nsXPCFunctionThisTranslator : : ~ nsXPCFunctionThisTranslator ( )
{
/* destructor code */
# ifdef DEBUG_jband
printf ( " destroying nsXPCFunctionThisTranslator \n " ) ;
# endif
}
/* nsISupports TranslateThis (in nsISupports aInitialThis, in nsIInterfaceInfo aInterfaceInfo, in PRUint16 aMethodIndex, out PRBool aHideFirstParamFromJS, out nsIIDPtr aIIDOfResult); */
NS_IMETHODIMP
nsXPCFunctionThisTranslator : : TranslateThis ( nsISupports * aInitialThis ,
nsIInterfaceInfo * aInterfaceInfo ,
PRUint16 aMethodIndex ,
PRBool * aHideFirstParamFromJS ,
nsIID * * aIIDOfResult ,
nsISupports * * _retval )
{
NS_IF_ADDREF ( aInitialThis ) ;
* _retval = aInitialThis ;
* aHideFirstParamFromJS = JS_FALSE ;
* aIIDOfResult = nsnull ;
return NS_OK ;
}
# endif
2008-10-11 10:35:39 -07:00
// ContextCallback calls are chained
static JSContextCallback gOldJSContextCallback ;
2008-09-06 15:21:43 -07:00
static JSBool
2008-04-09 00:27:16 -07:00
ContextCallback ( JSContext * cx , uintN contextOp )
{
2008-10-11 10:35:39 -07:00
if ( gOldJSContextCallback & & ! gOldJSContextCallback ( cx , contextOp ) )
return JS_FALSE ;
2008-04-09 00:27:16 -07:00
if ( contextOp = = JSCONTEXT_NEW ) {
JS_SetErrorReporter ( cx , my_ErrorReporter ) ;
JS_SetVersion ( cx , JSVERSION_LATEST ) ;
}
return JS_TRUE ;
}
2009-01-18 09:01:15 -08:00
static bool
GetCurrentWorkingDirectory ( nsAString & workingDirectory )
{
2009-01-22 07:17:22 -08:00
# if (!defined(XP_WIN) && !defined(XP_UNIX)) || defined(WINCE)
2009-01-18 09:01:15 -08:00
//XXX: your platform should really implement this
return false ;
2009-01-22 07:17:22 -08:00
# elif XP_WIN
2009-01-18 09:01:15 -08:00
DWORD requiredLength = GetCurrentDirectoryW ( 0 , NULL ) ;
workingDirectory . SetLength ( requiredLength ) ;
GetCurrentDirectoryW ( workingDirectory . Length ( ) ,
( LPWSTR ) workingDirectory . BeginWriting ( ) ) ;
// we got a trailing null there
workingDirectory . SetLength ( requiredLength ) ;
workingDirectory . Replace ( workingDirectory . Length ( ) - 1 , 1 , L ' \\ ' ) ;
# elif defined(XP_UNIX)
nsCAutoString cwd ;
// 1024 is just a guess at a sane starting value
size_t bufsize = 1024 ;
char * result = nsnull ;
while ( result = = nsnull ) {
if ( ! cwd . SetLength ( bufsize ) )
return false ;
result = getcwd ( cwd . BeginWriting ( ) , cwd . Length ( ) ) ;
if ( ! result ) {
if ( errno ! = ERANGE )
return false ;
// need to make the buffer bigger
bufsize * = 2 ;
}
}
// size back down to the actual string length
cwd . SetLength ( strlen ( result ) + 1 ) ;
cwd . Replace ( cwd . Length ( ) - 1 , 1 , ' / ' ) ;
workingDirectory = NS_ConvertUTF8toUTF16 ( cwd ) ;
# endif
return true ;
}
2007-03-22 10:30:00 -07:00
int
main ( int argc , char * * argv , char * * envp )
{
2008-06-03 03:56:09 -07:00
# ifdef XP_MACOSX
InitAutoreleasePool ( ) ;
# endif
2007-03-22 10:30:00 -07:00
JSRuntime * rt ;
JSContext * cx ;
JSObject * glob , * envobj ;
int result ;
nsresult rv ;
2009-01-16 14:10:48 -08:00
# ifdef HAVE_SETBUF
2007-03-22 10:30:00 -07:00
// unbuffer stdout so that output is in the correct order; note that stderr
// is unbuffered by default
setbuf ( stdout , 0 ) ;
2009-01-16 14:10:48 -08:00
# endif
2007-03-22 10:30:00 -07:00
gErrFile = stderr ;
gOutFile = stdout ;
2008-11-27 18:25:35 -08:00
gInFile = stdin ;
2009-01-20 11:56:44 -08:00
NS_LogInit ( ) ;
nsCOMPtr < nsILocalFile > appFile ;
rv = XRE_GetBinaryPath ( argv [ 0 ] , getter_AddRefs ( appFile ) ) ;
if ( NS_FAILED ( rv ) ) {
printf ( " Couldn't figure application file. \n " ) ;
return 1 ;
}
nsCOMPtr < nsIFile > appDir ;
rv = appFile - > GetParent ( getter_AddRefs ( appDir ) ) ;
if ( NS_FAILED ( rv ) ) {
printf ( " Couldn't get application directory. \n " ) ;
return 1 ;
}
XPCShellDirProvider dirprovider ;
if ( argc > 1 & & ! strcmp ( argv [ 1 ] , " -g " ) ) {
if ( argc < 3 )
return usage ( ) ;
if ( ! dirprovider . SetGREDir ( argv [ 2 ] ) ) {
printf ( " SetGREDir failed. \n " ) ;
return 1 ;
}
argc - = 2 ;
argv + = 2 ;
}
2007-03-22 10:30:00 -07:00
{
nsCOMPtr < nsIServiceManager > servMan ;
2009-01-20 11:56:44 -08:00
rv = NS_InitXPCOM2 ( getter_AddRefs ( servMan ) , appDir , & dirprovider ) ;
2007-03-22 10:30:00 -07:00
if ( NS_FAILED ( rv ) ) {
printf ( " NS_InitXPCOM failed! \n " ) ;
return 1 ;
}
{
nsCOMPtr < nsIComponentRegistrar > registrar = do_QueryInterface ( servMan ) ;
NS_ASSERTION ( registrar , " Null nsIComponentRegistrar " ) ;
if ( registrar )
registrar - > AutoRegister ( nsnull ) ;
}
nsCOMPtr < nsIJSRuntimeService > rtsvc = do_GetService ( " @mozilla.org/js/xpc/RuntimeService;1 " ) ;
// get the JSRuntime from the runtime svc
if ( ! rtsvc ) {
printf ( " failed to get nsJSRuntimeService! \n " ) ;
return 1 ;
}
if ( NS_FAILED ( rtsvc - > GetRuntime ( & rt ) ) | | ! rt ) {
printf ( " failed to get JSRuntime from nsJSRuntimeService! \n " ) ;
return 1 ;
}
2008-10-11 10:35:39 -07:00
gOldJSContextCallback = JS_SetContextCallback ( rt , ContextCallback ) ;
2008-04-09 00:27:16 -07:00
2007-03-22 10:30:00 -07:00
cx = JS_NewContext ( rt , 8192 ) ;
if ( ! cx ) {
printf ( " JS_NewContext failed! \n " ) ;
return 1 ;
}
nsCOMPtr < nsIXPConnect > xpc = do_GetService ( nsIXPConnect : : GetCID ( ) ) ;
if ( ! xpc ) {
printf ( " failed to get nsXPConnect service! \n " ) ;
return 1 ;
}
// Since the caps security system might set a default security manager
// we will be sure that the secman on this context gives full trust.
2007-06-20 17:10:48 -07:00
nsRefPtr < FullTrustSecMan > secman = new FullTrustSecMan ( ) ;
xpc - > SetSecurityManagerForJSContext ( cx , secman , 0xFFFF ) ;
2007-03-22 10:30:00 -07:00
# ifndef XPCONNECT_STANDALONE
// Fetch the system principal and store it away in a global, to use for
// script compilation in Load() and ProcessFile() (including interactive
// eval loop)
{
nsCOMPtr < nsIPrincipal > princ ;
nsCOMPtr < nsIScriptSecurityManager > securityManager =
do_GetService ( NS_SCRIPTSECURITYMANAGER_CONTRACTID , & rv ) ;
if ( NS_SUCCEEDED ( rv ) & & securityManager ) {
rv = securityManager - > GetSystemPrincipal ( getter_AddRefs ( princ ) ) ;
if ( NS_FAILED ( rv ) ) {
fprintf ( gErrFile , " +++ Failed to obtain SystemPrincipal from ScriptSecurityManager service. \n " ) ;
} else {
// fetch the JS principals and stick in a global
rv = princ - > GetJSPrincipals ( cx , & gJSPrincipals ) ;
if ( NS_FAILED ( rv ) ) {
fprintf ( gErrFile , " +++ Failed to obtain JS principals from SystemPrincipal. \n " ) ;
}
2007-06-20 17:10:48 -07:00
secman - > SetSystemPrincipal ( princ ) ;
2007-03-22 10:30:00 -07:00
}
} else {
fprintf ( gErrFile , " +++ Failed to get ScriptSecurityManager service, running without principals " ) ;
}
}
# endif
# ifdef TEST_TranslateThis
nsCOMPtr < nsIXPCFunctionThisTranslator >
translator ( new nsXPCFunctionThisTranslator ) ;
xpc - > SetFunctionThisTranslator ( NS_GET_IID ( nsITestXPCFunctionCallback ) , translator , nsnull ) ;
# endif
nsCOMPtr < nsIJSContextStack > cxstack = do_GetService ( " @mozilla.org/js/xpc/ContextStack;1 " ) ;
if ( ! cxstack ) {
printf ( " failed to get the nsThreadJSContextStack service! \n " ) ;
return 1 ;
}
if ( NS_FAILED ( cxstack - > Push ( cx ) ) ) {
printf ( " failed to push the current JSContext on the nsThreadJSContextStack! \n " ) ;
return 1 ;
}
nsCOMPtr < nsIXPCScriptable > backstagePass ;
nsresult rv = rtsvc - > GetBackstagePass ( getter_AddRefs ( backstagePass ) ) ;
if ( NS_FAILED ( rv ) ) {
fprintf ( gErrFile , " +++ Failed to get backstage pass from rtsvc: %8x \n " ,
rv ) ;
return 1 ;
}
nsCOMPtr < nsIXPConnectJSObjectHolder > holder ;
rv = xpc - > InitClassesWithNewWrappedGlobal ( cx , backstagePass ,
NS_GET_IID ( nsISupports ) ,
nsIXPConnect : :
FLAG_SYSTEM_GLOBAL_OBJECT ,
getter_AddRefs ( holder ) ) ;
if ( NS_FAILED ( rv ) )
return 1 ;
rv = holder - > GetJSObject ( & glob ) ;
if ( NS_FAILED ( rv ) ) {
NS_ASSERTION ( glob = = nsnull , " bad GetJSObject? " ) ;
return 1 ;
}
JS_BeginRequest ( cx ) ;
if ( ! JS_DefineFunctions ( cx , glob , glob_functions ) ) {
JS_EndRequest ( cx ) ;
return 1 ;
}
envobj = JS_DefineObject ( cx , glob , " environment " , & env_class , NULL , 0 ) ;
if ( ! envobj | | ! JS_SetPrivate ( cx , envobj , envp ) ) {
JS_EndRequest ( cx ) ;
return 1 ;
}
2009-01-18 09:01:15 -08:00
nsAutoString workingDirectory ;
if ( GetCurrentWorkingDirectory ( workingDirectory ) )
gWorkingDirectory = & workingDirectory ;
JS_DefineProperty ( cx , glob , " __LOCATION__ " , JSVAL_VOID ,
GetLocationProperty , NULL , 0 ) ;
2007-03-22 10:30:00 -07:00
argc - - ;
argv + + ;
result = ProcessArgs ( cx , glob , argv , argc ) ;
//#define TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN 1
# ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
// test of late call and release (see below)
nsCOMPtr < nsIJSContextStack > bogus ;
xpc - > WrapJS ( cx , glob , NS_GET_IID ( nsIJSContextStack ) ,
( void * * ) getter_AddRefs ( bogus ) ) ;
# endif
2007-06-20 17:10:48 -07:00
JSPRINCIPALS_DROP ( cx , gJSPrincipals ) ;
2007-03-22 10:30:00 -07:00
JS_ClearScope ( cx , glob ) ;
JS_GC ( cx ) ;
JSContext * oldcx ;
cxstack - > Pop ( & oldcx ) ;
NS_ASSERTION ( oldcx = = cx , " JS thread context push/pop mismatch " ) ;
cxstack = nsnull ;
JS_GC ( cx ) ;
JS_DestroyContext ( cx ) ;
} // this scopes the nsCOMPtrs
// no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
rv = NS_ShutdownXPCOM ( NULL ) ;
NS_ASSERTION ( NS_SUCCEEDED ( rv ) , " NS_ShutdownXPCOM failed " ) ;
# ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
// test of late call and release (see above)
JSContext * bogusCX ;
bogus - > Peek ( & bogusCX ) ;
bogus = nsnull ;
# endif
2009-01-20 11:56:44 -08:00
appDir = nsnull ;
appFile = nsnull ;
dirprovider . ClearGREDir ( ) ;
NS_LogTerm ( ) ;
2008-06-03 03:56:09 -07:00
# ifdef XP_MACOSX
FinishAutoreleasePool ( ) ;
# endif
2007-03-22 10:30:00 -07:00
return result ;
}
2009-01-20 11:56:44 -08:00
PRBool
XPCShellDirProvider : : SetGREDir ( const char * dir )
{
nsresult rv = XRE_GetFileFromPath ( dir , getter_AddRefs ( mGREDir ) ) ;
return NS_SUCCEEDED ( rv ) ;
}
NS_IMETHODIMP_ ( nsrefcnt )
XPCShellDirProvider : : AddRef ( )
{
return 2 ;
}
NS_IMETHODIMP_ ( nsrefcnt )
XPCShellDirProvider : : Release ( )
{
return 1 ;
}
NS_IMPL_QUERY_INTERFACE1 ( XPCShellDirProvider , nsIDirectoryServiceProvider )
NS_IMETHODIMP
XPCShellDirProvider : : GetFile ( const char * prop , PRBool * persistent ,
nsIFile * * result )
{
if ( mGREDir & & ! strcmp ( prop , NS_GRE_DIR ) ) {
* persistent = PR_TRUE ;
NS_ADDREF ( * result = mGREDir ) ;
return NS_OK ;
}
return NS_ERROR_FAILURE ;
}