1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=2 sw=4 et tw=80:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla Communicator client code, released
20 * The Initial Developer of the Original Code is
21 * Netscape Communications Corporation.
22 * Portions created by the Initial Developer are Copyright (C) 1998
23 * the Initial Developer. All Rights Reserved.
26 * John Bandhauer <jband@netscape.com>
27 * Pierre Phaneuf <pp@ludusdesign.com>
29 * Dan Mosedale <dan.mosedale@oracle.com>
31 * Alternatively, the contents of this file may be used under the terms of
32 * either of the GNU General Public License Version 2 or later (the "GPL"),
33 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
34 * in which case the provisions of the GPL or the LGPL are applicable instead
35 * of those above. If you wish to allow use of your version of this file only
36 * under the terms of either the GPL or the LGPL, and not to allow others to
37 * use your version of this file under the terms of the MPL, indicate your
38 * decision by deleting the provisions above and replace them with the notice
39 * and other provisions required by the GPL or the LGPL. If you do not delete
40 * the provisions above, a recipient may use your version of this file under
41 * the terms of any one of the MPL, the GPL or the LGPL.
43 * ***** END LICENSE BLOCK ***** */
45 /* XPConnect JavaScript interactive shell. */
48 #include "nsServiceManagerUtils.h"
49 #include "nsComponentManagerUtils.h"
50 #include "nsIXPConnect.h"
51 #include "nsIXPCScriptable.h"
52 #include "nsIInterfaceInfo.h"
53 #include "nsIInterfaceInfoManager.h"
54 #include "nsIXPCScriptable.h"
55 #include "nsIServiceManager.h"
56 #include "nsIComponentManager.h"
57 #include "nsIComponentRegistrar.h"
62 #include "nsIGenericFactory.h"
63 #include "nsIJSRuntimeService.h"
65 #include "nsAutoPtr.h"
66 #include "nsIXPCSecurityManager.h"
68 #include "xpcshellMacUtils.h"
71 #ifndef XPCONNECT_STANDALONE
72 #include "nsIScriptSecurityManager.h"
73 #include "nsIPrincipal.h"
76 // all this crap is needed to do the interactive shell stuff
79 #if defined(XP_WIN) || defined(XP_OS2)
80 #include <io.h> /* for isatty() */
81 #elif defined(XP_UNIX) || defined(XP_BEOS)
82 #include <unistd.h> /* for isatty() */
85 #include "nsIJSContextStack.h"
91 /***************************************************************************/
94 #define DoBeginRequest(cx) JS_BeginRequest((cx))
95 #define DoEndRequest(cx) JS_EndRequest((cx))
97 #define DoBeginRequest(cx) ((void)0)
98 #define DoEndRequest(cx) ((void)0)
101 /***************************************************************************/
103 #define EXITCODE_RUNTIME_ERROR 3
104 #define EXITCODE_FILE_NOT_FOUND 4
106 FILE *gOutFile
= NULL
;
107 FILE *gErrFile
= NULL
;
110 JSBool gQuitting
= JS_FALSE
;
111 static JSBool reportWarnings
= JS_TRUE
;
112 static JSBool compileOnly
= JS_FALSE
;
114 JSPrincipals
*gJSPrincipals
= nsnull
;
116 JS_STATIC_DLL_CALLBACK(void)
117 my_ErrorReporter(JSContext
*cx
, const char *message
, JSErrorReport
*report
)
120 char *prefix
= NULL
, *tmp
;
124 fprintf(gErrFile
, "%s\n", message
);
128 /* Conditionally ignore reported warnings. */
129 if (JSREPORT_IS_WARNING(report
->flags
) && !reportWarnings
)
132 if (report
->filename
)
133 prefix
= JS_smprintf("%s:", report
->filename
);
134 if (report
->lineno
) {
136 prefix
= JS_smprintf("%s%u: ", tmp
? tmp
: "", report
->lineno
);
139 if (JSREPORT_IS_WARNING(report
->flags
)) {
141 prefix
= JS_smprintf("%s%swarning: ",
143 JSREPORT_IS_STRICT(report
->flags
) ? "strict " : "");
147 /* embedded newlines -- argh! */
148 while ((ctmp
= strchr(message
, '\n')) != 0) {
150 if (prefix
) fputs(prefix
, gErrFile
);
151 fwrite(message
, 1, ctmp
- message
, gErrFile
);
154 /* If there were no filename or lineno, the prefix might be empty */
156 fputs(prefix
, gErrFile
);
157 fputs(message
, gErrFile
);
159 if (!report
->linebuf
) {
160 fputc('\n', gErrFile
);
164 fprintf(gErrFile
, ":\n%s%s\n%s", prefix
, report
->linebuf
, prefix
);
165 n
= report
->tokenptr
- report
->linebuf
;
166 for (i
= j
= 0; i
< n
; i
++) {
167 if (report
->linebuf
[i
] == '\t') {
168 for (k
= (j
+ 8) & ~7; j
< k
; j
++) {
169 fputc('.', gErrFile
);
173 fputc('.', gErrFile
);
176 fputs("^\n", gErrFile
);
178 if (!JSREPORT_IS_WARNING(report
->flags
))
179 gExitCode
= EXITCODE_RUNTIME_ERROR
;
183 JS_STATIC_DLL_CALLBACK(JSBool
)
184 Print(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
189 for (i
= n
= 0; i
< argc
; i
++) {
190 str
= JS_ValueToString(cx
, argv
[i
]);
193 fprintf(gOutFile
, "%s%s", i
? " " : "", JS_GetStringBytes(str
));
197 fputc('\n', gOutFile
);
201 JS_STATIC_DLL_CALLBACK(JSBool
)
202 Dump(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
208 str
= JS_ValueToString(cx
, argv
[0]);
212 char *bytes
= JS_GetStringBytes(str
);
213 bytes
= strdup(bytes
);
215 fputs(bytes
, gOutFile
);
220 JS_STATIC_DLL_CALLBACK(JSBool
)
221 Load(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
225 const char *filename
;
231 for (i
= 0; i
< argc
; i
++) {
232 str
= JS_ValueToString(cx
, argv
[i
]);
235 argv
[i
] = STRING_TO_JSVAL(str
);
236 filename
= JS_GetStringBytes(str
);
237 file
= fopen(filename
, "r");
238 script
= JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
,
244 ? JS_ExecuteScript(cx
, obj
, script
, &result
)
246 JS_DestroyScript(cx
, script
);
254 JS_STATIC_DLL_CALLBACK(JSBool
)
255 Version(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
257 if (argc
> 0 && JSVAL_IS_INT(argv
[0]))
258 *rval
= INT_TO_JSVAL(JS_SetVersion(cx
, JSVersion(JSVAL_TO_INT(argv
[0]))));
260 *rval
= INT_TO_JSVAL(JS_GetVersion(cx
));
264 JS_STATIC_DLL_CALLBACK(JSBool
)
265 BuildDate(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
267 fprintf(gOutFile
, "built on %s at %s\n", __DATE__
, __TIME__
);
271 JS_STATIC_DLL_CALLBACK(JSBool
)
272 Quit(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
275 JSJ_SimpleShutdown();
279 JS_ConvertArguments(cx
, argc
, argv
,"/ i", &gExitCode
);
286 JS_STATIC_DLL_CALLBACK(JSBool
)
287 DumpXPC(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
292 if (!JS_ValueToInt32(cx
, argv
[0], &depth
))
296 nsCOMPtr
<nsIXPConnect
> xpc
= do_GetService(nsIXPConnect::GetCID());
298 xpc
->DebugDump((int16
)depth
);
302 /* XXX needed only by GC() */
305 JS_STATIC_DLL_CALLBACK(JSBool
)
306 GC(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
312 preBytes
= rt
->gcBytes
;
314 fprintf(gOutFile
, "before %lu, after %lu, break %08lx\n",
315 (unsigned long)preBytes
, (unsigned long)rt
->gcBytes
,
317 (unsigned long)sbrk(0)
323 js_DumpGCStats(rt
, stdout
);
331 DumpHeap(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
333 char *fileName
= NULL
;
334 void* startThing
= NULL
;
335 uint32 startTraceKind
= 0;
336 void *thingToFind
= NULL
;
337 size_t maxDepth
= (size_t)-1;
338 void *thingToIgnore
= NULL
;
344 if (*vp
!= JSVAL_NULL
&& *vp
!= JSVAL_VOID
) {
347 str
= JS_ValueToString(cx
, *vp
);
350 *vp
= STRING_TO_JSVAL(str
);
351 fileName
= JS_GetStringBytes(str
);
355 if (*vp
!= JSVAL_NULL
&& *vp
!= JSVAL_VOID
) {
356 if (!JSVAL_IS_TRACEABLE(*vp
))
357 goto not_traceable_arg
;
358 startThing
= JSVAL_TO_TRACEABLE(*vp
);
359 startTraceKind
= JSVAL_TRACE_KIND(*vp
);
363 if (*vp
!= JSVAL_NULL
&& *vp
!= JSVAL_VOID
) {
364 if (!JSVAL_IS_TRACEABLE(*vp
))
365 goto not_traceable_arg
;
366 thingToFind
= JSVAL_TO_TRACEABLE(*vp
);
370 if (*vp
!= JSVAL_NULL
&& *vp
!= JSVAL_VOID
) {
373 if (!JS_ValueToECMAUint32(cx
, *vp
, &depth
))
379 if (*vp
!= JSVAL_NULL
&& *vp
!= JSVAL_VOID
) {
380 if (!JSVAL_IS_TRACEABLE(*vp
))
381 goto not_traceable_arg
;
382 thingToIgnore
= JSVAL_TO_TRACEABLE(*vp
);
388 dumpFile
= fopen(fileName
, "w");
390 fprintf(gErrFile
, "dumpHeap: can't open %s: %s\n",
391 fileName
, strerror(errno
));
396 ok
= JS_DumpHeap(cx
, dumpFile
, startThing
, startTraceKind
, thingToFind
,
397 maxDepth
, thingToIgnore
);
398 if (dumpFile
!= gOutFile
)
404 "dumpHeap: argument %u is not null or a heap-allocated thing\n",
405 (unsigned)(vp
- argv
));
411 JS_STATIC_DLL_CALLBACK(JSBool
)
412 Clear(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
, jsval
*rval
)
414 if (argc
> 0 && !JSVAL_IS_PRIMITIVE(argv
[0])) {
415 JS_ClearScope(cx
, JSVAL_TO_OBJECT(argv
[0]));
417 JS_ReportError(cx
, "'clear' requires an object");
423 static JSFunctionSpec glob_functions
[] = {
424 {"print", Print
, 0,0,0},
425 {"load", Load
, 1,0,0},
426 {"quit", Quit
, 0,0,0},
427 {"version", Version
, 1,0,0},
428 {"build", BuildDate
, 0,0,0},
429 {"dumpXPC", DumpXPC
, 1,0,0},
430 {"dump", Dump
, 1,0,0},
432 {"clear", Clear
, 1,0,0},
434 {"dumpHeap", DumpHeap
, 5,0,0},
437 {"startShark", js_StartShark
, 0,0,0},
438 {"stopShark", js_StopShark
, 0,0,0},
439 {"connectShark", js_ConnectShark
, 0,0,0},
440 {"disconnectShark", js_DisconnectShark
, 0,0,0},
442 {nsnull
,nsnull
,0,0,0}
445 JSClass global_class
= {
447 JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
,
448 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, JS_FinalizeStub
452 env_setProperty(JSContext
*cx
, JSObject
*obj
, jsval id
, jsval
*vp
)
454 /* XXX porting may be easy, but these don't seem to supply setenv by default */
455 #if !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS
456 JSString
*idstr
, *valstr
;
457 const char *name
, *value
;
460 idstr
= JS_ValueToString(cx
, id
);
461 valstr
= JS_ValueToString(cx
, *vp
);
462 if (!idstr
|| !valstr
)
464 name
= JS_GetStringBytes(idstr
);
465 value
= JS_GetStringBytes(valstr
);
466 #if defined XP_WIN || defined HPUX || defined OSF1 || defined IRIX \
469 char *waste
= JS_smprintf("%s=%s", name
, value
);
471 JS_ReportOutOfMemory(cx
);
477 * HPUX9 at least still has the bad old non-copying putenv.
479 * Per mail from <s.shanmuganathan@digital.com>, OSF1 also has a putenv
480 * that will crash if you pass it an auto char array (so it must place
481 * its argument directly in the char *environ[] array).
487 rv
= setenv(name
, value
, 1);
490 JS_ReportError(cx
, "can't set envariable %s to %s", name
, value
);
493 *vp
= STRING_TO_JSVAL(valstr
);
494 #endif /* !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS */
499 env_enumerate(JSContext
*cx
, JSObject
*obj
)
501 static JSBool reflected
;
502 char **evp
, *name
, *value
;
509 for (evp
= (char **)JS_GetPrivate(cx
, obj
); (name
= *evp
) != NULL
; evp
++) {
510 value
= strchr(name
, '=');
514 valstr
= JS_NewStringCopyZ(cx
, value
);
518 ok
= JS_DefineProperty(cx
, obj
, name
, STRING_TO_JSVAL(valstr
),
519 NULL
, NULL
, JSPROP_ENUMERATE
);
531 env_resolve(JSContext
*cx
, JSObject
*obj
, jsval id
, uintN flags
,
534 JSString
*idstr
, *valstr
;
535 const char *name
, *value
;
537 if (flags
& JSRESOLVE_ASSIGNING
)
540 idstr
= JS_ValueToString(cx
, id
);
543 name
= JS_GetStringBytes(idstr
);
544 value
= getenv(name
);
546 valstr
= JS_NewStringCopyZ(cx
, value
);
549 if (!JS_DefineProperty(cx
, obj
, name
, STRING_TO_JSVAL(valstr
),
550 NULL
, NULL
, JSPROP_ENUMERATE
)) {
558 static JSClass env_class
= {
559 "environment", JSCLASS_HAS_PRIVATE
| JSCLASS_NEW_RESOLVE
,
560 JS_PropertyStub
, JS_PropertyStub
,
561 JS_PropertyStub
, env_setProperty
,
562 env_enumerate
, (JSResolveOp
) env_resolve
,
563 JS_ConvertStub
, JS_FinalizeStub
566 /***************************************************************************/
568 typedef enum JSShellErrNum
{
569 #define MSG_DEF(name, number, count, exception, format) \
571 #include "jsshell.msg"
577 JSErrorFormatString jsShell_ErrorFormatString
[JSErr_Limit
] = {
578 #if JS_HAS_DFLT_MSG_STRINGS
579 #define MSG_DEF(name, number, count, exception, format) \
582 #define MSG_DEF(name, number, count, exception, format) \
585 #include "jsshell.msg"
589 JS_STATIC_DLL_CALLBACK(const JSErrorFormatString
*)
590 my_GetErrorMessage(void *userRef
, const char *locale
, const uintN errorNumber
)
592 if ((errorNumber
> 0) && (errorNumber
< JSShellErr_Limit
))
593 return &jsShell_ErrorFormatString
[errorNumber
];
600 extern char *readline(const char *prompt
);
601 extern void add_history(char *line
);
606 GetLine(JSContext
*cx
, char *bufp
, FILE *file
, const char *prompt
) {
609 * Use readline only if file is stdin, because there's no way to specify
610 * another handle. Are other filehandles interactive?
613 char *linep
= readline(prompt
);
620 bufp
+= strlen(bufp
);
627 fprintf(gOutFile
, prompt
);
629 if (!fgets(line
, sizeof line
, file
))
637 ProcessFile(JSContext
*cx
, JSObject
*obj
, const char *filename
, FILE *file
,
642 int lineno
, startline
;
644 char *bufp
, buffer
[4096];
649 } else if (!isatty(fileno(file
))) {
651 * It's not interactive - just execute it.
653 * Support the UNIX #! shell hack; gobble the first line if it starts
654 * with '#'. TODO - this isn't quite compatible with sharp variables,
655 * as a legal js program (using sharp variables) might start with '#'.
656 * But that would require multi-character lookahead.
658 int ch
= fgetc(file
);
660 while((ch
= fgetc(file
)) != EOF
) {
661 if(ch
== '\n' || ch
== '\r')
668 script
= JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
,
673 (void)JS_ExecuteScript(cx
, obj
, script
, &result
);
674 JS_DestroyScript(cx
, script
);
681 /* It's an interactive filehandle; drop into read-eval-print loop. */
689 * Accumulate lines until we get a 'compilable unit' - one that either
690 * generates an error (before running out of source) or that compiles
691 * cleanly. This should be whenever we get a complete statement that
692 * coincides with the end of a line.
696 if (!GetLine(cx
, bufp
, file
, startline
== lineno
? "js> " : "")) {
700 bufp
+= strlen(bufp
);
702 } while (!JS_BufferIsCompilableUnit(cx
, obj
, buffer
, strlen(buffer
)));
705 /* Clear any pending exception from previous failed compiles. */
706 JS_ClearPendingException(cx
);
707 script
= JS_CompileScriptForPrincipals(cx
, obj
, gJSPrincipals
, buffer
,
708 strlen(buffer
), "typein", startline
);
710 JSErrorReporter older
;
713 ok
= JS_ExecuteScript(cx
, obj
, script
, &result
);
714 if (ok
&& result
!= JSVAL_VOID
) {
715 /* Suppress error reports from JS_ValueToString(). */
716 older
= JS_SetErrorReporter(cx
, NULL
);
717 str
= JS_ValueToString(cx
, result
);
718 JS_SetErrorReporter(cx
, older
);
721 fprintf(gOutFile
, "%s\n", JS_GetStringBytes(str
));
726 JS_DestroyScript(cx
, script
);
729 } while (!hitEOF
&& !gQuitting
);
731 fprintf(gOutFile
, "\n");
735 Process(JSContext
*cx
, JSObject
*obj
, const char *filename
, JSBool forceTTY
)
739 if (forceTTY
|| !filename
|| strcmp(filename
, "-") == 0) {
742 file
= fopen(filename
, "r");
744 JS_ReportErrorNumber(cx
, my_GetErrorMessage
, NULL
,
746 filename
, strerror(errno
));
747 gExitCode
= EXITCODE_FILE_NOT_FOUND
;
752 ProcessFile(cx
, obj
, filename
, file
, forceTTY
);
758 fprintf(gErrFile
, "%s\n", JS_GetImplementationVersion());
759 fprintf(gErrFile
, "usage: xpcshell [-PswWxCi] [-v version] [-f scriptfile] [-e script] [scriptfile] [scriptarg...]\n");
763 extern JSClass global_class
;
766 ProcessArgs(JSContext
*cx
, JSObject
*obj
, char **argv
, int argc
)
768 const char rcfilename
[] = "xpcshell.js";
772 char *filename
= NULL
;
773 JSBool isInteractive
= JS_TRUE
;
774 JSBool forceTTY
= JS_FALSE
;
776 rcfile
= fopen(rcfilename
, "r");
778 printf("[loading '%s'...]\n", rcfilename
);
779 ProcessFile(cx
, obj
, rcfilename
, rcfile
, JS_FALSE
);
783 * Scan past all optional arguments so we can create the arguments object
784 * before processing any -f options, which must interleave properly with
785 * -v and -w options. This requires two passes, and without getopt, we'll
786 * have to keep the option logic here and in the second for loop in sync.
788 for (i
= 0; i
< argc
; i
++) {
789 if (argv
[i
][0] != '-' || argv
[i
][1] == '\0') {
793 switch (argv
[i
][1]) {
804 * Create arguments early and define it to root it, so it's safe from any
805 * GC calls nested below, and so it is available to -f <file> arguments.
807 argsObj
= JS_NewArrayObject(cx
, 0, NULL
);
810 if (!JS_DefineProperty(cx
, obj
, "arguments", OBJECT_TO_JSVAL(argsObj
),
816 for (j
= 0; j
< length
; j
++) {
817 JSString
*str
= JS_NewStringCopyZ(cx
, argv
[i
++]);
820 if (!JS_DefineElement(cx
, argsObj
, j
, STRING_TO_JSVAL(str
),
821 NULL
, NULL
, JSPROP_ENUMERATE
)) {
826 for (i
= 0; i
< argc
; i
++) {
827 if (argv
[i
][0] != '-' || argv
[i
][1] == '\0') {
828 filename
= argv
[i
++];
829 isInteractive
= JS_FALSE
;
832 switch (argv
[i
][1]) {
837 JS_SetVersion(cx
, JSVersion(atoi(argv
[i
])));
840 reportWarnings
= JS_FALSE
;
843 reportWarnings
= JS_TRUE
;
846 JS_ToggleOptions(cx
, JSOPTION_STRICT
);
849 JS_ToggleOptions(cx
, JSOPTION_XML
);
852 if (JS_GET_CLASS(cx
, JS_GetPrototype(cx
, obj
)) != &global_class
) {
855 if (!JS_SealObject(cx
, obj
, JS_TRUE
))
857 gobj
= JS_NewObject(cx
, &global_class
, NULL
, NULL
);
860 if (!JS_SetPrototype(cx
, gobj
, obj
))
862 JS_SetParent(cx
, gobj
, NULL
);
863 JS_SetGlobalObject(cx
, gobj
);
871 Process(cx
, obj
, argv
[i
], JS_FALSE
);
873 * XXX: js -f foo.js should interpret foo.js and then
874 * drop into interactive mode, but that breaks test
875 * harness. Just execute foo.js for now.
877 isInteractive
= JS_FALSE
;
880 isInteractive
= forceTTY
= JS_TRUE
;
890 JS_EvaluateScript(cx
, obj
, argv
[i
], strlen(argv
[i
]),
893 isInteractive
= JS_FALSE
;
897 compileOnly
= JS_TRUE
;
898 isInteractive
= JS_FALSE
;
910 if (filename
|| isInteractive
)
911 Process(cx
, obj
, filename
, forceTTY
);
915 /***************************************************************************/
917 class FullTrustSecMan
918 #ifndef XPCONNECT_STANDALONE
919 : public nsIScriptSecurityManager
921 : public nsIXPCSecurityManager
926 NS_DECL_NSIXPCSECURITYMANAGER
927 #ifndef XPCONNECT_STANDALONE
928 NS_DECL_NSISCRIPTSECURITYMANAGER
932 virtual ~FullTrustSecMan();
934 #ifndef XPCONNECT_STANDALONE
935 void SetSystemPrincipal(nsIPrincipal
*aPrincipal
) {
936 mSystemPrincipal
= aPrincipal
;
940 nsCOMPtr
<nsIPrincipal
> mSystemPrincipal
;
944 NS_INTERFACE_MAP_BEGIN(FullTrustSecMan
)
945 NS_INTERFACE_MAP_ENTRY(nsIXPCSecurityManager
)
946 #ifndef XPCONNECT_STANDALONE
947 NS_INTERFACE_MAP_ENTRY(nsIScriptSecurityManager
)
949 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIXPCSecurityManager
)
952 NS_IMPL_ADDREF(FullTrustSecMan
)
953 NS_IMPL_RELEASE(FullTrustSecMan
)
955 FullTrustSecMan::FullTrustSecMan()
957 #ifndef XPCONNECT_STANDALONE
958 mSystemPrincipal
= nsnull
;
962 FullTrustSecMan::~FullTrustSecMan()
967 FullTrustSecMan::CanCreateWrapper(JSContext
* aJSContext
, const nsIID
& aIID
,
968 nsISupports
*aObj
, nsIClassInfo
*aClassInfo
,
975 FullTrustSecMan::CanCreateInstance(JSContext
* aJSContext
, const nsCID
& aCID
)
981 FullTrustSecMan::CanGetService(JSContext
* aJSContext
, const nsCID
& aCID
)
986 #ifndef XPCONNECT_STANDALONE
987 /* 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); */
989 FullTrustSecMan::CanAccess(PRUint32 aAction
,
990 nsAXPCNativeCallContext
*aCallContext
,
991 JSContext
* aJSContext
, JSObject
* aJSObject
,
992 nsISupports
*aObj
, nsIClassInfo
*aClassInfo
,
993 jsval aName
, void * *aPolicy
)
998 /* [noscript] void checkPropertyAccess (in JSContextPtr aJSContext, in JSObjectPtr aJSObject, in string aClassName, in JSVal aProperty, in PRUint32 aAction); */
1000 FullTrustSecMan::CheckPropertyAccess(JSContext
* aJSContext
,
1001 JSObject
* aJSObject
,
1002 const char *aClassName
,
1003 jsval aProperty
, PRUint32 aAction
)
1008 /* [noscript] void checkConnect (in JSContextPtr aJSContext, in nsIURI aTargetURI, in string aClassName, in string aProperty); */
1010 FullTrustSecMan::CheckConnect(JSContext
* aJSContext
, nsIURI
*aTargetURI
,
1011 const char *aClassName
, const char *aProperty
)
1016 /* [noscript] void checkLoadURIFromScript (in JSContextPtr cx, in nsIURI uri); */
1018 FullTrustSecMan::CheckLoadURIFromScript(JSContext
* cx
, nsIURI
*uri
)
1023 /* void checkLoadURIWithPrincipal (in nsIPrincipal aPrincipal, in nsIURI uri, in unsigned long flags); */
1025 FullTrustSecMan::CheckLoadURIWithPrincipal(nsIPrincipal
*aPrincipal
,
1026 nsIURI
*uri
, PRUint32 flags
)
1031 /* void checkLoadURI (in nsIURI from, in nsIURI uri, in unsigned long flags); */
1033 FullTrustSecMan::CheckLoadURI(nsIURI
*from
, nsIURI
*uri
, PRUint32 flags
)
1038 /* void checkLoadURIStrWithPrincipal (in nsIPrincipal aPrincipal, in AUTF8String uri, in unsigned long flags); */
1040 FullTrustSecMan::CheckLoadURIStrWithPrincipal(nsIPrincipal
*aPrincipal
,
1041 const nsACString
& uri
,
1047 /* void checkLoadURIStr (in AUTF8String from, in AUTF8String uri, in unsigned long flags); */
1049 FullTrustSecMan::CheckLoadURIStr(const nsACString
& from
,
1050 const nsACString
& uri
, PRUint32 flags
)
1055 /* [noscript] void checkFunctionAccess (in JSContextPtr cx, in voidPtr funObj, in voidPtr targetObj); */
1057 FullTrustSecMan::CheckFunctionAccess(JSContext
* cx
, void * funObj
,
1063 /* [noscript] boolean canExecuteScripts (in JSContextPtr cx, in nsIPrincipal principal); */
1065 FullTrustSecMan::CanExecuteScripts(JSContext
* cx
, nsIPrincipal
*principal
,
1072 /* [noscript] nsIPrincipal getSubjectPrincipal (); */
1074 FullTrustSecMan::GetSubjectPrincipal(nsIPrincipal
**_retval
)
1076 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
1077 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
1080 /* [noscript] nsIPrincipal getSystemPrincipal (); */
1082 FullTrustSecMan::GetSystemPrincipal(nsIPrincipal
**_retval
)
1084 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
1085 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
1088 /* [noscript] nsIPrincipal getCertificatePrincipal (in AUTF8String aCertFingerprint, in AUTF8String aSubjectName, in AUTF8String aPrettyName, in nsISupports aCert, in nsIURI aURI); */
1090 FullTrustSecMan::GetCertificatePrincipal(const nsACString
& aCertFingerprint
,
1091 const nsACString
& aSubjectName
,
1092 const nsACString
& aPrettyName
,
1093 nsISupports
*aCert
, nsIURI
*aURI
,
1094 nsIPrincipal
**_retval
)
1096 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
1097 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
1100 /* [noscript] nsIPrincipal getCodebasePrincipal (in nsIURI aURI); */
1102 FullTrustSecMan::GetCodebasePrincipal(nsIURI
*aURI
, nsIPrincipal
**_retval
)
1104 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
1105 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
1108 /* [noscript] short requestCapability (in nsIPrincipal principal, in string capability); */
1110 FullTrustSecMan::RequestCapability(nsIPrincipal
*principal
,
1111 const char *capability
, PRInt16
*_retval
)
1113 *_retval
= nsIPrincipal::ENABLE_GRANTED
;
1117 /* boolean isCapabilityEnabled (in string capability); */
1119 FullTrustSecMan::IsCapabilityEnabled(const char *capability
, PRBool
*_retval
)
1125 /* void enableCapability (in string capability); */
1127 FullTrustSecMan::EnableCapability(const char *capability
)
1132 /* void revertCapability (in string capability); */
1134 FullTrustSecMan::RevertCapability(const char *capability
)
1139 /* void disableCapability (in string capability); */
1141 FullTrustSecMan::DisableCapability(const char *capability
)
1146 /* void setCanEnableCapability (in AUTF8String certificateFingerprint, in string capability, in short canEnable); */
1148 FullTrustSecMan::SetCanEnableCapability(const nsACString
& certificateFingerprint
,
1149 const char *capability
,
1155 /* [noscript] nsIPrincipal getObjectPrincipal (in JSContextPtr cx, in JSObjectPtr obj); */
1157 FullTrustSecMan::GetObjectPrincipal(JSContext
* cx
, JSObject
* obj
,
1158 nsIPrincipal
**_retval
)
1160 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
1161 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
1164 /* [noscript] boolean subjectPrincipalIsSystem (); */
1166 FullTrustSecMan::SubjectPrincipalIsSystem(PRBool
*_retval
)
1172 /* [noscript] void checkSameOrigin (in JSContextPtr aJSContext, in nsIURI aTargetURI); */
1174 FullTrustSecMan::CheckSameOrigin(JSContext
* aJSContext
, nsIURI
*aTargetURI
)
1179 /* void checkSameOriginURI (in nsIURI aSourceURI, in nsIURI aTargetURI); */
1181 FullTrustSecMan::CheckSameOriginURI(nsIURI
*aSourceURI
, nsIURI
*aTargetURI
,
1187 /* [noscript] nsIPrincipal getPrincipalFromContext (in JSContextPtr cx); */
1189 FullTrustSecMan::GetPrincipalFromContext(JSContext
* cx
, nsIPrincipal
**_retval
)
1191 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
1192 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
1195 /* [noscript] nsIPrincipal getChannelPrincipal (in nsIChannel aChannel); */
1197 FullTrustSecMan::GetChannelPrincipal(nsIChannel
*aChannel
, nsIPrincipal
**_retval
)
1199 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
1200 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
1203 /* boolean isSystemPrincipal (in nsIPrincipal aPrincipal); */
1205 FullTrustSecMan::IsSystemPrincipal(nsIPrincipal
*aPrincipal
, PRBool
*_retval
)
1207 *_retval
= aPrincipal
== mSystemPrincipal
;
1211 NS_IMETHODIMP_(nsIPrincipal
*)
1212 FullTrustSecMan::GetCxSubjectPrincipal(JSContext
*cx
)
1214 return mSystemPrincipal
;
1219 /***************************************************************************/
1221 // #define TEST_InitClassesWithNewWrappedGlobal
1223 #ifdef TEST_InitClassesWithNewWrappedGlobal
1224 // XXX hacky test code...
1225 #include "xpctest.h"
1227 class TestGlobal
: public nsIXPCTestNoisy
, public nsIXPCScriptable
1231 NS_DECL_NSIXPCTESTNOISY
1232 NS_DECL_NSIXPCSCRIPTABLE
1237 NS_IMPL_ISUPPORTS2(TestGlobal
, nsIXPCTestNoisy
, nsIXPCScriptable
)
1239 // The nsIXPCScriptable map declaration that will generate stubs for us...
1240 #define XPC_MAP_CLASSNAME TestGlobal
1241 #define XPC_MAP_QUOTED_CLASSNAME "TestGlobal"
1242 #define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY |\
1243 nsIXPCScriptable::USE_JSSTUB_FOR_DELPROPERTY |\
1244 nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY
1245 #include "xpc_map_end.h" /* This will #undef the above */
1247 NS_IMETHODIMP
TestGlobal::Squawk() {return NS_OK
;}
1251 // uncomment to install the test 'this' translator
1252 // #define TEST_TranslateThis
1254 #ifdef TEST_TranslateThis
1256 #include "xpctest.h"
1258 class nsXPCFunctionThisTranslator
: public nsIXPCFunctionThisTranslator
1262 NS_DECL_NSIXPCFUNCTIONTHISTRANSLATOR
1264 nsXPCFunctionThisTranslator();
1265 virtual ~nsXPCFunctionThisTranslator();
1266 /* additional members */
1269 /* Implementation file */
1270 NS_IMPL_ISUPPORTS1(nsXPCFunctionThisTranslator
, nsIXPCFunctionThisTranslator
)
1272 nsXPCFunctionThisTranslator::nsXPCFunctionThisTranslator()
1274 /* member initializers and constructor code */
1277 nsXPCFunctionThisTranslator::~nsXPCFunctionThisTranslator()
1279 /* destructor code */
1281 printf("destroying nsXPCFunctionThisTranslator\n");
1285 /* nsISupports TranslateThis (in nsISupports aInitialThis, in nsIInterfaceInfo aInterfaceInfo, in PRUint16 aMethodIndex, out PRBool aHideFirstParamFromJS, out nsIIDPtr aIIDOfResult); */
1287 nsXPCFunctionThisTranslator::TranslateThis(nsISupports
*aInitialThis
,
1288 nsIInterfaceInfo
*aInterfaceInfo
,
1289 PRUint16 aMethodIndex
,
1290 PRBool
*aHideFirstParamFromJS
,
1291 nsIID
* *aIIDOfResult
,
1292 nsISupports
**_retval
)
1294 NS_IF_ADDREF(aInitialThis
);
1295 *_retval
= aInitialThis
;
1296 *aHideFirstParamFromJS
= JS_FALSE
;
1297 *aIIDOfResult
= nsnull
;
1303 JS_STATIC_DLL_CALLBACK(JSBool
)
1304 ContextCallback(JSContext
*cx
, uintN contextOp
)
1306 if (contextOp
== JSCONTEXT_NEW
) {
1307 JS_SetErrorReporter(cx
, my_ErrorReporter
);
1308 JS_SetVersion(cx
, JSVERSION_LATEST
);
1314 main(int argc
, char **argv
, char **envp
)
1317 InitAutoreleasePool();
1321 JSObject
*glob
, *envobj
;
1325 // unbuffer stdout so that output is in the correct order; note that stderr
1326 // is unbuffered by default
1332 nsCOMPtr
<nsIServiceManager
> servMan
;
1333 rv
= NS_InitXPCOM2(getter_AddRefs(servMan
), nsnull
, nsnull
);
1334 if (NS_FAILED(rv
)) {
1335 printf("NS_InitXPCOM failed!\n");
1339 nsCOMPtr
<nsIComponentRegistrar
> registrar
= do_QueryInterface(servMan
);
1340 NS_ASSERTION(registrar
, "Null nsIComponentRegistrar");
1342 registrar
->AutoRegister(nsnull
);
1345 nsCOMPtr
<nsIJSRuntimeService
> rtsvc
= do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
1346 // get the JSRuntime from the runtime svc
1348 printf("failed to get nsJSRuntimeService!\n");
1352 if (NS_FAILED(rtsvc
->GetRuntime(&rt
)) || !rt
) {
1353 printf("failed to get JSRuntime from nsJSRuntimeService!\n");
1357 JS_SetContextCallback(rt
, ContextCallback
);
1359 cx
= JS_NewContext(rt
, 8192);
1361 printf("JS_NewContext failed!\n");
1365 nsCOMPtr
<nsIXPConnect
> xpc
= do_GetService(nsIXPConnect::GetCID());
1367 printf("failed to get nsXPConnect service!\n");
1371 // Since the caps security system might set a default security manager
1372 // we will be sure that the secman on this context gives full trust.
1373 nsRefPtr
<FullTrustSecMan
> secman
= new FullTrustSecMan();
1374 xpc
->SetSecurityManagerForJSContext(cx
, secman
, 0xFFFF);
1376 #ifndef XPCONNECT_STANDALONE
1377 // Fetch the system principal and store it away in a global, to use for
1378 // script compilation in Load() and ProcessFile() (including interactive
1381 nsCOMPtr
<nsIPrincipal
> princ
;
1383 nsCOMPtr
<nsIScriptSecurityManager
> securityManager
=
1384 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID
, &rv
);
1385 if (NS_SUCCEEDED(rv
) && securityManager
) {
1386 rv
= securityManager
->GetSystemPrincipal(getter_AddRefs(princ
));
1387 if (NS_FAILED(rv
)) {
1388 fprintf(gErrFile
, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
1390 // fetch the JS principals and stick in a global
1391 rv
= princ
->GetJSPrincipals(cx
, &gJSPrincipals
);
1392 if (NS_FAILED(rv
)) {
1393 fprintf(gErrFile
, "+++ Failed to obtain JS principals from SystemPrincipal.\n");
1395 secman
->SetSystemPrincipal(princ
);
1398 fprintf(gErrFile
, "+++ Failed to get ScriptSecurityManager service, running without principals");
1403 #ifdef TEST_TranslateThis
1404 nsCOMPtr
<nsIXPCFunctionThisTranslator
>
1405 translator(new nsXPCFunctionThisTranslator
);
1406 xpc
->SetFunctionThisTranslator(NS_GET_IID(nsITestXPCFunctionCallback
), translator
, nsnull
);
1409 nsCOMPtr
<nsIJSContextStack
> cxstack
= do_GetService("@mozilla.org/js/xpc/ContextStack;1");
1411 printf("failed to get the nsThreadJSContextStack service!\n");
1415 if(NS_FAILED(cxstack
->Push(cx
))) {
1416 printf("failed to push the current JSContext on the nsThreadJSContextStack!\n");
1420 nsCOMPtr
<nsIXPCScriptable
> backstagePass
;
1421 nsresult rv
= rtsvc
->GetBackstagePass(getter_AddRefs(backstagePass
));
1422 if (NS_FAILED(rv
)) {
1423 fprintf(gErrFile
, "+++ Failed to get backstage pass from rtsvc: %8x\n",
1428 nsCOMPtr
<nsIXPConnectJSObjectHolder
> holder
;
1429 rv
= xpc
->InitClassesWithNewWrappedGlobal(cx
, backstagePass
,
1430 NS_GET_IID(nsISupports
),
1432 FLAG_SYSTEM_GLOBAL_OBJECT
,
1433 getter_AddRefs(holder
));
1437 rv
= holder
->GetJSObject(&glob
);
1438 if (NS_FAILED(rv
)) {
1439 NS_ASSERTION(glob
== nsnull
, "bad GetJSObject?");
1443 JS_BeginRequest(cx
);
1445 if (!JS_DefineFunctions(cx
, glob
, glob_functions
)) {
1450 envobj
= JS_DefineObject(cx
, glob
, "environment", &env_class
, NULL
, 0);
1451 if (!envobj
|| !JS_SetPrivate(cx
, envobj
, envp
)) {
1459 result
= ProcessArgs(cx
, glob
, argv
, argc
);
1462 //#define TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN 1
1464 #ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
1465 // test of late call and release (see below)
1466 nsCOMPtr
<nsIJSContextStack
> bogus
;
1467 xpc
->WrapJS(cx
, glob
, NS_GET_IID(nsIJSContextStack
),
1468 (void**) getter_AddRefs(bogus
));
1471 JSPRINCIPALS_DROP(cx
, gJSPrincipals
);
1472 JS_ClearScope(cx
, glob
);
1475 cxstack
->Pop(&oldcx
);
1476 NS_ASSERTION(oldcx
== cx
, "JS thread context push/pop mismatch");
1479 JS_DestroyContext(cx
);
1480 xpc
->SyncJSContexts();
1481 } // this scopes the nsCOMPtrs
1482 // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
1483 rv
= NS_ShutdownXPCOM( NULL
);
1484 NS_ASSERTION(NS_SUCCEEDED(rv
), "NS_ShutdownXPCOM failed");
1486 #ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
1487 // test of late call and release (see above)
1489 bogus
->Peek(&bogusCX
);
1494 FinishAutoreleasePool();