1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is Mozilla IPCShell.
16 * The Initial Developer of the Original Code is
17 * Ben Turner <bent.mozilla@gmail.com>.
18 * Portions created by the Initial Developer are Copyright (C) 2009
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
40 #include <io.h> /* for isatty() */
43 #include <unistd.h> /* for isatty() */
46 #include "base/basictypes.h"
53 #include "xpcpublic.h"
55 #include "XPCShellEnvironment.h"
57 #include "mozilla/XPCOM.h"
59 #include "nsIChannel.h"
60 #include "nsIClassInfo.h"
61 #include "nsIDirectoryService.h"
62 #include "nsIJSContextStack.h"
63 #include "nsIJSRuntimeService.h"
64 #include "nsIPrincipal.h"
65 #include "nsIScriptSecurityManager.h"
67 #include "nsIXPConnect.h"
68 #include "nsIXPCScriptable.h"
70 #include "nsJSUtils.h"
71 #include "nsThreadUtils.h"
72 #include "nsXULAppAPI.h"
74 #include "TestShellChild.h"
75 #include "TestShellParent.h"
77 #define EXITCODE_RUNTIME_ERROR 3
78 #define EXITCODE_FILE_NOT_FOUND 4
80 using mozilla::ipc::XPCShellEnvironment
;
81 using mozilla::ipc::TestShellChild
;
82 using mozilla::ipc::TestShellParent
;
86 static const char kDefaultRuntimeScriptFilename
[] = "xpcshell.js";
88 class FullTrustSecMan
: public nsIScriptSecurityManager
92 NS_DECL_NSIXPCSECURITYMANAGER
93 NS_DECL_NSISCRIPTSECURITYMANAGER
96 virtual ~FullTrustSecMan() { }
98 void SetSystemPrincipal(nsIPrincipal
*aPrincipal
) {
99 mSystemPrincipal
= aPrincipal
;
103 nsCOMPtr
<nsIPrincipal
> mSystemPrincipal
;
106 class XPCShellDirProvider
: public nsIDirectoryServiceProvider
110 NS_DECL_NSIDIRECTORYSERVICEPROVIDER
112 XPCShellDirProvider() { }
113 ~XPCShellDirProvider() { }
115 PRBool
SetGREDir(const char *dir
);
116 void ClearGREDir() { mGREDir
= nsnull
; }
119 nsCOMPtr
<nsILocalFile
> mGREDir
;
122 inline XPCShellEnvironment
*
123 Environment(JSContext
* cx
)
125 XPCShellEnvironment
* env
=
126 static_cast<XPCShellEnvironment
*>(JS_GetContextPrivate(cx
));
127 NS_ASSERTION(env
, "Should never be null!");
132 ScriptErrorReporter(JSContext
*cx
,
134 JSErrorReport
*report
)
137 char *prefix
= NULL
, *tmp
;
139 JSStackFrame
* fp
= nsnull
;
140 nsCOMPtr
<nsIXPConnect
> xpc
;
142 // Don't report an exception from inner JS frames as the callers may intend
144 while ((fp
= JS_FrameIterator(cx
, &fp
))) {
145 if (JS_IsScriptFrame(cx
, fp
)) {
150 // In some cases cx->fp is null here so use XPConnect to tell us about inner
152 if ((xpc
= do_GetService(nsIXPConnect::GetCID()))) {
153 nsAXPCNativeCallContext
*cc
= nsnull
;
154 xpc
->GetCurrentNativeCallContext(&cc
);
156 nsAXPCNativeCallContext
*prev
= cc
;
157 while (NS_SUCCEEDED(prev
->GetPreviousCallContext(&prev
)) && prev
) {
159 if (NS_SUCCEEDED(prev
->GetLanguage(&lang
)) &&
160 lang
== nsAXPCNativeCallContext::LANG_JS
) {
168 fprintf(stderr
, "%s\n", message
);
172 /* Conditionally ignore reported warnings. */
173 if (JSREPORT_IS_WARNING(report
->flags
) &&
174 !Environment(cx
)->ShouldReportWarnings()) {
178 if (report
->filename
)
179 prefix
= JS_smprintf("%s:", report
->filename
);
180 if (report
->lineno
) {
182 prefix
= JS_smprintf("%s%u: ", tmp
? tmp
: "", report
->lineno
);
185 if (JSREPORT_IS_WARNING(report
->flags
)) {
187 prefix
= JS_smprintf("%s%swarning: ",
189 JSREPORT_IS_STRICT(report
->flags
) ? "strict " : "");
193 /* embedded newlines -- argh! */
194 while ((ctmp
= strchr(message
, '\n')) != 0) {
196 if (prefix
) fputs(prefix
, stderr
);
197 fwrite(message
, 1, ctmp
- message
, stderr
);
200 /* If there were no filename or lineno, the prefix might be empty */
202 fputs(prefix
, stderr
);
203 fputs(message
, stderr
);
205 if (!report
->linebuf
) {
210 fprintf(stderr
, ":\n%s%s\n%s", prefix
, report
->linebuf
, prefix
);
211 n
= report
->tokenptr
- report
->linebuf
;
212 for (i
= j
= 0; i
< n
; i
++) {
213 if (report
->linebuf
[i
] == '\t') {
214 for (k
= (j
+ 8) & ~7; j
< k
; j
++) {
222 fputs("^\n", stderr
);
224 if (!JSREPORT_IS_WARNING(report
->flags
)) {
225 Environment(cx
)->SetExitCode(EXITCODE_RUNTIME_ERROR
);
230 JSContextCallback gOldContextCallback
= NULL
;
233 ContextCallback(JSContext
*cx
,
236 if (gOldContextCallback
&& !gOldContextCallback(cx
, contextOp
))
239 if (contextOp
== JSCONTEXT_NEW
) {
240 JS_SetErrorReporter(cx
, ScriptErrorReporter
);
241 JS_SetVersion(cx
, JSVERSION_LATEST
);
254 jsval
*argv
= JS_ARGV(cx
, vp
);
255 for (i
= n
= 0; i
< argc
; i
++) {
256 str
= JS_ValueToString(cx
, argv
[i
]);
259 JSAutoByteString
bytes(cx
, str
);
262 fprintf(stdout
, "%s%s", i
? " " : "", bytes
.ptr());
268 JS_SET_RVAL(cx
, vp
, JSVAL_VOID
);
278 fputs(prompt
, stdout
);
280 if (!fgets(line
, sizeof line
, file
))
291 JS_SET_RVAL(cx
, vp
, JSVAL_VOID
);
297 str
= JS_ValueToString(cx
, JS_ARGV(cx
, vp
)[0]);
300 JS_FileEscapedString(stdout
, str
, 0);
317 JSObject
*obj
= JS_THIS_OBJECT(cx
, vp
);
321 jsval
*argv
= JS_ARGV(cx
, vp
);
322 for (i
= 0; i
< argc
; i
++) {
323 str
= JS_ValueToString(cx
, argv
[i
]);
326 argv
[i
] = STRING_TO_JSVAL(str
);
327 JSAutoByteString
filename(cx
, str
);
330 file
= fopen(filename
.ptr(), "r");
332 JS_ReportError(cx
, "cannot open file '%s' for reading", filename
.ptr());
335 script
= JS_CompileFileHandleForPrincipals(cx
, obj
, filename
.ptr(), file
,
336 Environment(cx
)->GetPrincipal());
341 ok
= !Environment(cx
)->ShouldCompileOnly()
342 ? JS_ExecuteScript(cx
, obj
, script
, &result
)
344 JS_DestroyScript(cx
, script
);
348 JS_SET_RVAL(cx
, vp
, JSVAL_VOID
);
353 Version(JSContext
*cx
,
357 jsval
*argv
= JS_ARGV(cx
, vp
);
358 if (argc
> 0 && JSVAL_IS_INT(argv
[0]))
359 JS_SET_RVAL(cx
, vp
, INT_TO_JSVAL(JS_SetVersion(cx
, JSVersion(JSVAL_TO_INT(argv
[0])))));
361 JS_SET_RVAL(cx
, vp
, INT_TO_JSVAL(JS_GetVersion(cx
)));
366 BuildDate(JSContext
*cx
, uintN argc
, jsval
*vp
)
368 fprintf(stdout
, "built on %s at %s\n", __DATE__
, __TIME__
);
378 JS_ConvertArguments(cx
, argc
, JS_ARGV(cx
, vp
), "/ i", &exitCode
);
380 XPCShellEnvironment
* env
= Environment(cx
);
381 env
->SetExitCode(exitCode
);
382 env
->SetIsQuitting();
388 DumpXPC(JSContext
*cx
,
395 if (!JS_ValueToInt32(cx
, JS_ARGV(cx
, vp
)[0], &depth
))
399 nsCOMPtr
<nsIXPConnect
> xpc
= do_GetService(nsIXPConnect::GetCID());
401 xpc
->DebugDump((int16
)depth
);
402 JS_SET_RVAL(cx
, vp
, JSVAL_VOID
);
415 preBytes
= rt
->gcBytes
;
417 fprintf(stdout
, "before %lu, after %lu, break %08lx\n",
418 (unsigned long)preBytes
, (unsigned long)rt
->gcBytes
,
420 (unsigned long)sbrk(0)
426 js_DumpGCStats(rt
, stdout
);
428 JS_SET_RVAL(cx
, vp
, JSVAL_VOID
);
435 DumpHeap(JSContext
*cx
,
439 JSAutoByteString fileName
;
440 void* startThing
= NULL
;
441 uint32 startTraceKind
= 0;
442 void *thingToFind
= NULL
;
443 size_t maxDepth
= (size_t)-1;
444 void *thingToIgnore
= NULL
;
448 jsval
*argv
= JS_ARGV(cx
, vp
);
449 JS_SET_RVAL(cx
, vp
, JSVAL_VOID
);
452 if (argc
> 0 && *vp
!= JSVAL_NULL
&& *vp
!= JSVAL_VOID
) {
455 str
= JS_ValueToString(cx
, *vp
);
458 *vp
= STRING_TO_JSVAL(str
);
459 if (!fileName
.encode(cx
, str
))
464 if (argc
> 1 && *vp
!= JSVAL_NULL
&& *vp
!= JSVAL_VOID
) {
465 if (!JSVAL_IS_TRACEABLE(*vp
))
466 goto not_traceable_arg
;
467 startThing
= JSVAL_TO_TRACEABLE(*vp
);
468 startTraceKind
= JSVAL_TRACE_KIND(*vp
);
472 if (argc
> 2 && *vp
!= JSVAL_NULL
&& *vp
!= JSVAL_VOID
) {
473 if (!JSVAL_IS_TRACEABLE(*vp
))
474 goto not_traceable_arg
;
475 thingToFind
= JSVAL_TO_TRACEABLE(*vp
);
479 if (argc
> 3 && *vp
!= JSVAL_NULL
&& *vp
!= JSVAL_VOID
) {
482 if (!JS_ValueToECMAUint32(cx
, *vp
, &depth
))
488 if (argc
> 4 && *vp
!= JSVAL_NULL
&& *vp
!= JSVAL_VOID
) {
489 if (!JSVAL_IS_TRACEABLE(*vp
))
490 goto not_traceable_arg
;
491 thingToIgnore
= JSVAL_TO_TRACEABLE(*vp
);
497 dumpFile
= fopen(fileName
.ptr(), "w");
499 fprintf(stderr
, "dumpHeap: can't open %s: %s\n",
500 fileName
.ptr(), strerror(errno
));
505 ok
= JS_DumpHeap(cx
, dumpFile
, startThing
, startTraceKind
, thingToFind
,
506 maxDepth
, thingToIgnore
);
507 if (dumpFile
!= stdout
)
513 "dumpHeap: argument %u is not null or a heap-allocated thing\n",
514 (unsigned)(vp
- argv
));
525 jsval
*argv
= JS_ARGV(cx
, vp
);
526 if (argc
> 0 && !JSVAL_IS_PRIMITIVE(argv
[0])) {
527 JS_ClearScope(cx
, JSVAL_TO_OBJECT(argv
[0]));
529 JS_ReportError(cx
, "'clear' requires an object");
532 JS_SET_RVAL(cx
, vp
, JSVAL_VOID
);
536 JSFunctionSpec gGlobalFunctions
[] =
538 {"print", Print
, 0,0},
541 {"version", Version
, 1,0},
542 {"build", BuildDate
, 0,0},
543 {"dumpXPC", DumpXPC
, 1,0},
546 {"clear", Clear
, 1,0},
548 {"dumpHeap", DumpHeap
, 5,0},
551 {"startCallgrind", js_StartCallgrind
, 0,0},
552 {"stopCallgrind", js_StopCallgrind
, 0,0},
553 {"dumpCallgrind", js_DumpCallgrind
, 1,0},
558 typedef enum JSShellErrNum
560 #define MSG_DEF(name, number, count, exception, format) \
562 #include "jsshell.msg"
569 ProcessFile(JSContext
*cx
,
571 const char *filename
,
575 XPCShellEnvironment
* env
= Environment(cx
);
576 XPCShellEnvironment::AutoContextPusher
pusher(env
);
580 int lineno
, startline
;
582 char *bufp
, buffer
[4096];
590 if (!isatty(fileno(file
)))
594 * It's not interactive - just execute it.
596 * Support the UNIX #! shell hack; gobble the first line if it starts
597 * with '#'. TODO - this isn't quite compatible with sharp variables,
598 * as a legal js program (using sharp variables) might start with '#'.
599 * But that would require multi-character lookahead.
601 int ch
= fgetc(file
);
603 while((ch
= fgetc(file
)) != EOF
) {
604 if(ch
== '\n' || ch
== '\r')
610 JSAutoRequest
ar(cx
);
612 JSAutoEnterCompartment ac
;
613 if (!ac
.enter(cx
, obj
)) {
614 NS_ERROR("Failed to enter compartment!");
619 JS_CompileFileHandleForPrincipals(cx
, obj
, filename
, file
,
620 env
->GetPrincipal());
622 if (!env
->ShouldCompileOnly())
623 (void)JS_ExecuteScript(cx
, obj
, script
, &result
);
624 JS_DestroyScript(cx
, script
);
630 /* It's an interactive filehandle; drop into read-eval-print loop. */
637 JSAutoRequest
ar(cx
);
639 JSAutoEnterCompartment ac
;
640 if (!ac
.enter(cx
, obj
)) {
641 NS_ERROR("Failed to enter compartment!");
646 * Accumulate lines until we get a 'compilable unit' - one that either
647 * generates an error (before running out of source) or that compiles
648 * cleanly. This should be whenever we get a complete statement that
649 * coincides with the end of a line.
653 if (!GetLine(bufp
, file
, startline
== lineno
? "js> " : "")) {
657 bufp
+= strlen(bufp
);
659 } while (!JS_BufferIsCompilableUnit(cx
, obj
, buffer
, strlen(buffer
)));
661 /* Clear any pending exception from previous failed compiles. */
662 JS_ClearPendingException(cx
);
664 JS_CompileScriptForPrincipals(cx
, obj
, env
->GetPrincipal(), buffer
,
665 strlen(buffer
), "typein", startline
);
667 JSErrorReporter older
;
669 if (!env
->ShouldCompileOnly()) {
670 ok
= JS_ExecuteScript(cx
, obj
, script
, &result
);
671 if (ok
&& result
!= JSVAL_VOID
) {
672 /* Suppress error reports from JS_ValueToString(). */
673 older
= JS_SetErrorReporter(cx
, NULL
);
674 str
= JS_ValueToString(cx
, result
);
675 JSAutoByteString bytes
;
677 bytes
.encode(cx
, str
);
678 JS_SetErrorReporter(cx
, older
);
681 fprintf(stdout
, "%s\n", bytes
.ptr());
686 JS_DestroyScript(cx
, script
);
688 } while (!hitEOF
&& !env
->IsQuitting());
690 fprintf(stdout
, "\n");
693 } /* anonymous namespace */
695 NS_INTERFACE_MAP_BEGIN(FullTrustSecMan
)
696 NS_INTERFACE_MAP_ENTRY(nsIXPCSecurityManager
)
697 NS_INTERFACE_MAP_ENTRY(nsIScriptSecurityManager
)
698 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIXPCSecurityManager
)
701 NS_IMPL_ADDREF(FullTrustSecMan
)
702 NS_IMPL_RELEASE(FullTrustSecMan
)
705 FullTrustSecMan::CanCreateWrapper(JSContext
* aJSContext
,
708 nsIClassInfo
*aClassInfo
,
715 FullTrustSecMan::CanCreateInstance(JSContext
* aJSContext
,
722 FullTrustSecMan::CanGetService(JSContext
* aJSContext
,
729 FullTrustSecMan::CanAccess(PRUint32 aAction
,
730 nsAXPCNativeCallContext
*aCallContext
,
731 JSContext
* aJSContext
,
732 JSObject
* aJSObject
,
734 nsIClassInfo
*aClassInfo
,
742 FullTrustSecMan::CheckPropertyAccess(JSContext
* aJSContext
,
743 JSObject
* aJSObject
,
744 const char *aClassName
,
752 FullTrustSecMan::CheckLoadURIFromScript(JSContext
* cx
,
759 FullTrustSecMan::CheckLoadURIWithPrincipal(nsIPrincipal
*aPrincipal
,
767 FullTrustSecMan::CheckLoadURI(nsIURI
*from
,
775 FullTrustSecMan::CheckLoadURIStrWithPrincipal(nsIPrincipal
*aPrincipal
,
776 const nsACString
& uri
,
783 FullTrustSecMan::CheckLoadURIStr(const nsACString
& from
,
784 const nsACString
& uri
,
791 FullTrustSecMan::CheckFunctionAccess(JSContext
* cx
,
799 FullTrustSecMan::CanExecuteScripts(JSContext
* cx
,
800 nsIPrincipal
*principal
,
808 FullTrustSecMan::GetSubjectPrincipal(nsIPrincipal
**_retval
)
810 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
811 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
815 FullTrustSecMan::GetSystemPrincipal(nsIPrincipal
**_retval
)
817 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
818 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
822 FullTrustSecMan::GetCertificatePrincipal(const nsACString
& aCertFingerprint
,
823 const nsACString
& aSubjectName
,
824 const nsACString
& aPrettyName
,
827 nsIPrincipal
**_retval
)
829 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
830 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
834 FullTrustSecMan::GetCodebasePrincipal(nsIURI
*aURI
,
835 nsIPrincipal
**_retval
)
837 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
838 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
842 FullTrustSecMan::RequestCapability(nsIPrincipal
*principal
,
843 const char *capability
,
846 *_retval
= nsIPrincipal::ENABLE_GRANTED
;
851 FullTrustSecMan::IsCapabilityEnabled(const char *capability
,
859 FullTrustSecMan::EnableCapability(const char *capability
)
865 FullTrustSecMan::RevertCapability(const char *capability
)
871 FullTrustSecMan::DisableCapability(const char *capability
)
877 FullTrustSecMan::SetCanEnableCapability(const nsACString
& certificateFingerprint
,
878 const char *capability
,
885 FullTrustSecMan::GetObjectPrincipal(JSContext
* cx
,
887 nsIPrincipal
**_retval
)
889 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
890 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
894 FullTrustSecMan::SubjectPrincipalIsSystem(PRBool
*_retval
)
901 FullTrustSecMan::CheckSameOrigin(JSContext
* aJSContext
,
908 FullTrustSecMan::CheckSameOriginURI(nsIURI
*aSourceURI
,
916 FullTrustSecMan::GetPrincipalFromContext(JSContext
* cx
,
917 nsIPrincipal
**_retval
)
919 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
920 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
924 FullTrustSecMan::GetChannelPrincipal(nsIChannel
*aChannel
,
925 nsIPrincipal
**_retval
)
927 NS_IF_ADDREF(*_retval
= mSystemPrincipal
);
928 return *_retval
? NS_OK
: NS_ERROR_FAILURE
;
932 FullTrustSecMan::IsSystemPrincipal(nsIPrincipal
*aPrincipal
,
935 *_retval
= aPrincipal
== mSystemPrincipal
;
939 NS_IMETHODIMP_(nsIPrincipal
*)
940 FullTrustSecMan::GetCxSubjectPrincipal(JSContext
*cx
)
942 return mSystemPrincipal
;
945 NS_IMETHODIMP_(nsIPrincipal
*)
946 FullTrustSecMan::GetCxSubjectPrincipalAndFrame(JSContext
*cx
,
950 return mSystemPrincipal
;
954 FullTrustSecMan::PushContextPrincipal(JSContext
*cx
,
956 nsIPrincipal
*principal
)
962 FullTrustSecMan::PopContextPrincipal(JSContext
*cx
)
967 NS_IMETHODIMP_(nsrefcnt
)
968 XPCShellDirProvider::AddRef()
973 NS_IMETHODIMP_(nsrefcnt
)
974 XPCShellDirProvider::Release()
979 NS_IMPL_QUERY_INTERFACE1(XPCShellDirProvider
, nsIDirectoryServiceProvider
)
982 XPCShellDirProvider::SetGREDir(const char *dir
)
984 nsresult rv
= XRE_GetFileFromPath(dir
, getter_AddRefs(mGREDir
));
985 return NS_SUCCEEDED(rv
);
989 XPCShellDirProvider::GetFile(const char *prop
,
993 if (mGREDir
&& !strcmp(prop
, NS_GRE_DIR
)) {
994 *persistent
= PR_TRUE
;
995 NS_ADDREF(*result
= mGREDir
);
999 return NS_ERROR_FAILURE
;
1002 XPCShellEnvironment::
1003 AutoContextPusher::AutoContextPusher(XPCShellEnvironment
* aEnv
)
1005 NS_ASSERTION(aEnv
->mCx
, "Null context?!");
1007 if (NS_SUCCEEDED(aEnv
->mCxStack
->Push(aEnv
->mCx
))) {
1012 XPCShellEnvironment::
1013 AutoContextPusher::~AutoContextPusher()
1017 mEnv
->mCxStack
->Pop(&cx
);
1018 NS_ASSERTION(cx
== mEnv
->mCx
, "Wrong context on the stack!");
1023 XPCShellEnvironment
*
1024 XPCShellEnvironment::CreateEnvironment()
1026 XPCShellEnvironment
* env
= new XPCShellEnvironment();
1027 if (env
&& !env
->Init()) {
1034 XPCShellEnvironment::XPCShellEnvironment()
1036 mJSPrincipals(NULL
),
1038 mQuitting(JS_FALSE
),
1039 mReportWarnings(JS_TRUE
),
1040 mCompileOnly(JS_FALSE
)
1044 XPCShellEnvironment::~XPCShellEnvironment()
1047 JS_BeginRequest(mCx
);
1049 JSObject
* global
= GetGlobalObject();
1051 JS_ClearScope(mCx
, global
);
1053 mGlobalHolder
.Release();
1059 if (mJSPrincipals
) {
1060 JSPRINCIPALS_DROP(mCx
, mJSPrincipals
);
1063 JSRuntime
* rt
= gOldContextCallback
? JS_GetRuntime(mCx
) : NULL
;
1065 JS_DestroyContext(mCx
);
1067 if (gOldContextCallback
) {
1068 NS_ASSERTION(rt
, "Should never be null!");
1069 JS_SetContextCallback(rt
, gOldContextCallback
);
1070 gOldContextCallback
= NULL
;
1076 XPCShellEnvironment::Init()
1081 // unbuffer stdout so that output is in the correct order; note that stderr
1082 // is unbuffered by default
1086 nsCOMPtr
<nsIJSRuntimeService
> rtsvc
=
1087 do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
1089 NS_ERROR("failed to get nsJSRuntimeService!");
1094 if (NS_FAILED(rtsvc
->GetRuntime(&rt
)) || !rt
) {
1095 NS_ERROR("failed to get JSRuntime from nsJSRuntimeService!");
1099 if (!mGlobalHolder
.Hold(rt
)) {
1100 NS_ERROR("Can't protect global object!");
1104 gOldContextCallback
= JS_SetContextCallback(rt
, ContextCallback
);
1106 JSContext
*cx
= JS_NewContext(rt
, 8192);
1108 NS_ERROR("JS_NewContext failed!");
1110 JS_SetContextCallback(rt
, gOldContextCallback
);
1111 gOldContextCallback
= NULL
;
1117 JS_SetContextPrivate(cx
, this);
1119 nsCOMPtr
<nsIXPConnect
> xpc
=
1120 do_GetService(nsIXPConnect::GetCID());
1122 NS_ERROR("failed to get nsXPConnect service!");
1126 xpc_LocalizeContext(cx
);
1128 nsRefPtr
<FullTrustSecMan
> secman(new FullTrustSecMan());
1129 xpc
->SetSecurityManagerForJSContext(cx
, secman
, 0xFFFF);
1131 nsCOMPtr
<nsIPrincipal
> principal
;
1133 nsCOMPtr
<nsIScriptSecurityManager
> securityManager
=
1134 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID
, &rv
);
1135 if (NS_SUCCEEDED(rv
) && securityManager
) {
1136 rv
= securityManager
->GetSystemPrincipal(getter_AddRefs(principal
));
1137 if (NS_FAILED(rv
)) {
1138 fprintf(stderr
, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
1140 // fetch the JS principals and stick in a global
1141 rv
= principal
->GetJSPrincipals(cx
, &mJSPrincipals
);
1142 if (NS_FAILED(rv
)) {
1143 fprintf(stderr
, "+++ Failed to obtain JS principals from SystemPrincipal.\n");
1145 secman
->SetSystemPrincipal(principal
);
1148 fprintf(stderr
, "+++ Failed to get ScriptSecurityManager service, running without principals");
1151 nsCOMPtr
<nsIJSContextStack
> cxStack
=
1152 do_GetService("@mozilla.org/js/xpc/ContextStack;1");
1154 NS_ERROR("failed to get the nsThreadJSContextStack service!");
1159 AutoContextPusher
pusher(this);
1161 nsCOMPtr
<nsIXPCScriptable
> backstagePass
;
1162 rv
= rtsvc
->GetBackstagePass(getter_AddRefs(backstagePass
));
1163 if (NS_FAILED(rv
)) {
1164 NS_ERROR("Failed to get backstage pass from rtsvc!");
1168 nsCOMPtr
<nsIXPConnectJSObjectHolder
> holder
;
1169 rv
= xpc
->InitClassesWithNewWrappedGlobal(cx
, backstagePass
,
1170 NS_GET_IID(nsISupports
),
1174 FLAG_SYSTEM_GLOBAL_OBJECT
,
1175 getter_AddRefs(holder
));
1176 if (NS_FAILED(rv
)) {
1177 NS_ERROR("InitClassesWithNewWrappedGlobal failed!");
1181 JSObject
*globalObj
;
1182 rv
= holder
->GetJSObject(&globalObj
);
1183 if (NS_FAILED(rv
)) {
1184 NS_ERROR("Failed to get global JSObject!");
1190 JSAutoRequest
ar(cx
);
1192 JSAutoEnterCompartment ac
;
1193 if (!ac
.enter(cx
, globalObj
)) {
1194 NS_ERROR("Failed to enter compartment!");
1198 if (!JS_DefineFunctions(cx
, globalObj
, gGlobalFunctions
) ||
1199 !JS_DefineProfilingFunctions(cx
, globalObj
)) {
1200 NS_ERROR("JS_DefineFunctions failed!");
1205 mGlobalHolder
= globalObj
;
1207 FILE* runtimeScriptFile
= fopen(kDefaultRuntimeScriptFilename
, "r");
1208 if (runtimeScriptFile
) {
1209 fprintf(stdout
, "[loading '%s'...]\n", kDefaultRuntimeScriptFilename
);
1210 ProcessFile(cx
, globalObj
, kDefaultRuntimeScriptFilename
,
1211 runtimeScriptFile
, JS_FALSE
);
1212 fclose(runtimeScriptFile
);
1219 XPCShellEnvironment::EvaluateString(const nsString
& aString
,
1222 XPCShellEnvironment
* env
= Environment(mCx
);
1223 XPCShellEnvironment::AutoContextPusher
pusher(env
);
1225 JSAutoRequest
ar(mCx
);
1227 JS_ClearPendingException(mCx
);
1229 JSObject
* global
= GetGlobalObject();
1231 JSAutoEnterCompartment ac
;
1232 if (!ac
.enter(mCx
, global
)) {
1233 NS_ERROR("Failed to enter compartment!");
1238 JS_CompileUCScriptForPrincipals(mCx
, global
, GetPrincipal(),
1239 aString
.get(), aString
.Length(),
1245 if (!ShouldCompileOnly()) {
1247 aResult
->Truncate();
1251 JSBool ok
= JS_ExecuteScript(mCx
, global
, script
, &result
);
1252 if (ok
&& result
!= JSVAL_VOID
) {
1253 JSErrorReporter old
= JS_SetErrorReporter(mCx
, NULL
);
1254 JSString
* str
= JS_ValueToString(mCx
, result
);
1255 nsDependentJSString depStr
;
1257 depStr
.init(mCx
, str
);
1258 JS_SetErrorReporter(mCx
, old
);
1260 if (!depStr
.IsEmpty() && aResult
) {
1261 aResult
->Assign(depStr
);
1266 JS_DestroyScript(mCx
, script
);