1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla Communicator client code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Chris Waterson <waterson@netscape.com>
24 * L. David Baron <dbaron@dbaron.org>
25 * Ben Goodger <ben@netscape.com>
26 * Mark Hammond <mhammond@skippinet.com.au>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either of the GNU General Public License Version 2 or later (the "GPL"),
30 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
43 #include "nsXULPrototypeDocument.h"
44 #include "nsXULDocument.h"
46 #include "nsAString.h"
47 #include "nsIObjectInputStream.h"
48 #include "nsIObjectOutputStream.h"
49 #include "nsIPrincipal.h"
50 #include "nsIScriptGlobalObject.h"
51 #include "nsIScriptObjectPrincipal.h"
52 #include "nsIScriptSecurityManager.h"
53 #include "nsIScriptRuntime.h"
54 #include "nsIServiceManager.h"
59 #include "nsIConsoleService.h"
60 #include "nsIScriptError.h"
61 #include "nsIDOMScriptObjectFactory.h"
63 #include "nsNodeInfoManager.h"
64 #include "nsContentUtils.h"
65 #include "nsCCUncollectableMarker.h"
66 #include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
68 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID
,
69 NS_DOM_SCRIPT_OBJECT_FACTORY_CID
);
72 class nsXULPDGlobalObject
: public nsIScriptGlobalObject
,
73 public nsIScriptObjectPrincipal
76 nsXULPDGlobalObject(nsXULPrototypeDocument
* owner
);
78 // nsISupports interface
79 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
81 // nsIScriptGlobalObject methods
82 virtual void OnFinalize(PRUint32 aLangID
, void *aGlobal
);
83 virtual void SetScriptsEnabled(PRBool aEnabled
, PRBool aFireTimeouts
);
84 virtual nsresult
SetNewArguments(nsIArray
*aArguments
);
86 virtual void *GetScriptGlobal(PRUint32 lang
);
87 virtual nsresult
EnsureScriptEnvironment(PRUint32 aLangID
);
89 virtual nsIScriptContext
*GetScriptContext(PRUint32 lang
);
90 virtual nsresult
SetScriptContext(PRUint32 language
, nsIScriptContext
*ctx
);
92 // nsIScriptObjectPrincipal methods
93 virtual nsIPrincipal
* GetPrincipal();
95 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULPDGlobalObject
,
96 nsIScriptGlobalObject
)
98 void ClearGlobalObjectOwner();
101 virtual ~nsXULPDGlobalObject();
103 nsXULPrototypeDocument
* mGlobalObjectOwner
; // weak reference
105 nsCOMPtr
<nsIScriptContext
> mScriptContexts
[NS_STID_ARRAY_UBOUND
];
106 void * mScriptGlobals
[NS_STID_ARRAY_UBOUND
];
108 nsCOMPtr
<nsIPrincipal
> mCachedPrincipal
;
110 static JSClass gSharedGlobalClass
;
113 nsIPrincipal
* nsXULPrototypeDocument::gSystemPrincipal
;
114 nsXULPDGlobalObject
* nsXULPrototypeDocument::gSystemGlobal
;
115 PRUint32
nsXULPrototypeDocument::gRefCnt
;
119 nsXULPDGlobalObject_finalize(JSContext
*cx
, JSObject
*obj
)
121 nsISupports
*nativeThis
= (nsISupports
*)JS_GetPrivate(cx
, obj
);
123 nsCOMPtr
<nsIScriptGlobalObject
> sgo(do_QueryInterface(nativeThis
));
126 sgo
->OnFinalize(nsIProgrammingLanguage::JAVASCRIPT
, obj
);
129 // The addref was part of JSObject construction
130 NS_RELEASE(nativeThis
);
135 nsXULPDGlobalObject_resolve(JSContext
*cx
, JSObject
*obj
, jsval id
)
137 JSBool did_resolve
= JS_FALSE
;
139 return JS_ResolveStandardClass(cx
, obj
, id
, &did_resolve
);
143 JSClass
nsXULPDGlobalObject::gSharedGlobalClass
= {
144 "nsXULPrototypeScript compilation scope",
145 JSCLASS_HAS_PRIVATE
| JSCLASS_PRIVATE_IS_NSISUPPORTS
| JSCLASS_GLOBAL_FLAGS
,
146 JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
,
147 JS_EnumerateStub
, nsXULPDGlobalObject_resolve
, JS_ConvertStub
,
148 nsXULPDGlobalObject_finalize
153 //----------------------------------------------------------------------
155 // ctors, dtors, n' stuff
158 nsXULPrototypeDocument::nsXULPrototypeDocument()
167 nsXULPrototypeDocument::Init()
169 mNodeInfoManager
= new nsNodeInfoManager();
170 NS_ENSURE_TRUE(mNodeInfoManager
, NS_ERROR_OUT_OF_MEMORY
);
172 return mNodeInfoManager
->Init(nsnull
);
175 nsXULPrototypeDocument::~nsXULPrototypeDocument()
178 // cleaup cycles etc.
179 mGlobalObject
->ClearGlobalObjectOwner();
183 mRoot
->ReleaseSubtree();
185 if (--gRefCnt
== 0) {
186 NS_IF_RELEASE(gSystemPrincipal
);
187 NS_IF_RELEASE(gSystemGlobal
);
191 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument
)
192 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsXULPrototypeDocument
)
193 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPrototypeDocument
)
194 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mRoot
,
195 nsXULPrototypeElement
)
196 cb
.NoteXPCOMChild(static_cast<nsIScriptGlobalObject
*>(tmp
->mGlobalObject
));
197 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mNodeInfoManager
,
199 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
201 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPrototypeDocument
)
202 NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObjectOwner
)
203 NS_INTERFACE_MAP_ENTRY(nsISerializable
)
204 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIScriptGlobalObjectOwner
)
207 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXULPrototypeDocument
,
208 nsIScriptGlobalObjectOwner
)
209 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXULPrototypeDocument
,
210 nsIScriptGlobalObjectOwner
)
213 NS_NewXULPrototypeDocument(nsXULPrototypeDocument
** aResult
)
215 *aResult
= new nsXULPrototypeDocument();
217 return NS_ERROR_OUT_OF_MEMORY
;
220 rv
= (*aResult
)->Init();
231 // Helper method that shares a system global among all prototype documents
232 // that have the system principal as their security principal. Called by
233 // nsXULPrototypeDocument::Read and nsXULPDGlobalObject::GetGlobalObject.
234 // This method greatly reduces the number of nsXULPDGlobalObjects and their
235 // nsIScriptContexts in apps that load many XUL documents via chrome: URLs.
237 nsXULPDGlobalObject
*
238 nsXULPrototypeDocument::NewXULPDGlobalObject()
240 // Now compare DocumentPrincipal() to gSystemPrincipal, in order to create
241 // gSystemGlobal if the two pointers are equal. Thus, gSystemGlobal
242 // implies gSystemPrincipal.
243 nsXULPDGlobalObject
*global
;
244 if (DocumentPrincipal() == gSystemPrincipal
) {
245 if (!gSystemGlobal
) {
246 gSystemGlobal
= new nsXULPDGlobalObject(nsnull
);
249 NS_ADDREF(gSystemGlobal
);
251 global
= gSystemGlobal
;
253 global
= new nsXULPDGlobalObject(this); // does not refcount
260 //----------------------------------------------------------------------
262 // nsISerializable methods
266 nsXULPrototypeDocument::Read(nsIObjectInputStream
* aStream
)
270 rv
= aStream
->ReadObject(PR_TRUE
, getter_AddRefs(mURI
));
273 nsCOMPtr
<nsIURI
> styleOverlayURI
;
275 rv
|= aStream
->Read32(&count
);
276 if (NS_FAILED(rv
)) return rv
;
278 for (i
= 0; i
< count
; ++i
) {
279 rv
|= aStream
->ReadObject(PR_TRUE
, getter_AddRefs(styleOverlayURI
));
280 mStyleSheetReferences
.AppendObject(styleOverlayURI
);
284 // nsIPrincipal mNodeInfoManager->mPrincipal
285 nsCOMPtr
<nsIPrincipal
> principal
;
286 rv
|= aStream
->ReadObject(PR_TRUE
, getter_AddRefs(principal
));
287 // Better safe than sorry....
288 mNodeInfoManager
->SetDocumentPrincipal(principal
);
291 // nsIScriptGlobalObject mGlobalObject
292 mGlobalObject
= NewXULPDGlobalObject();
294 return NS_ERROR_OUT_OF_MEMORY
;
296 mRoot
= new nsXULPrototypeElement();
298 return NS_ERROR_OUT_OF_MEMORY
;
301 nsCOMArray
<nsINodeInfo
> nodeInfos
;
303 rv
|= aStream
->Read32(&count
);
304 nsAutoString namespaceURI
, prefixStr
, localName
;
306 nsCOMPtr
<nsIAtom
> prefix
;
307 for (i
= 0; i
< count
; ++i
) {
308 rv
|= aStream
->ReadString(namespaceURI
);
309 rv
|= aStream
->ReadBoolean(&prefixIsNull
);
313 rv
|= aStream
->ReadString(prefixStr
);
314 prefix
= do_GetAtom(prefixStr
);
316 rv
|= aStream
->ReadString(localName
);
318 nsCOMPtr
<nsINodeInfo
> nodeInfo
;
319 rv
|= mNodeInfoManager
->GetNodeInfo(localName
, prefix
, namespaceURI
,
320 getter_AddRefs(nodeInfo
));
321 if (!nodeInfos
.AppendObject(nodeInfo
))
322 rv
|= NS_ERROR_OUT_OF_MEMORY
;
327 while (NS_SUCCEEDED(rv
)) {
328 rv
|= aStream
->Read32(&type
);
330 if ((nsXULPrototypeNode::Type
)type
== nsXULPrototypeNode::eType_PI
) {
331 nsRefPtr
<nsXULPrototypePI
> pi
= new nsXULPrototypePI();
333 rv
|= NS_ERROR_OUT_OF_MEMORY
;
337 rv
|= pi
->Deserialize(aStream
, mGlobalObject
, mURI
, &nodeInfos
);
338 rv
|= AddProcessingInstruction(pi
);
339 } else if ((nsXULPrototypeNode::Type
)type
== nsXULPrototypeNode::eType_Element
) {
340 rv
|= mRoot
->Deserialize(aStream
, mGlobalObject
, mURI
, &nodeInfos
);
343 NS_NOTREACHED("Unexpected prototype node type");
344 rv
|= NS_ERROR_FAILURE
;
348 rv
|= NotifyLoadDone();
354 GetNodeInfos(nsXULPrototypeElement
* aPrototype
,
355 nsCOMArray
<nsINodeInfo
>& aArray
)
358 if (aArray
.IndexOf(aPrototype
->mNodeInfo
) < 0) {
359 if (!aArray
.AppendObject(aPrototype
->mNodeInfo
)) {
360 return NS_ERROR_OUT_OF_MEMORY
;
366 for (i
= 0; i
< aPrototype
->mNumAttributes
; ++i
) {
367 nsCOMPtr
<nsINodeInfo
> ni
;
368 nsAttrName
* name
= &aPrototype
->mAttributes
[i
].mName
;
369 if (name
->IsAtom()) {
370 ni
= aPrototype
->mNodeInfo
->NodeInfoManager()->
371 GetNodeInfo(name
->Atom(), nsnull
, kNameSpaceID_None
);
372 NS_ENSURE_TRUE(ni
, NS_ERROR_OUT_OF_MEMORY
);
375 ni
= name
->NodeInfo();
378 if (aArray
.IndexOf(ni
) < 0) {
379 if (!aArray
.AppendObject(ni
)) {
380 return NS_ERROR_OUT_OF_MEMORY
;
386 for (i
= 0; i
< aPrototype
->mChildren
.Length(); ++i
) {
387 nsXULPrototypeNode
* child
= aPrototype
->mChildren
[i
];
388 if (child
->mType
== nsXULPrototypeNode::eType_Element
) {
389 rv
= GetNodeInfos(static_cast<nsXULPrototypeElement
*>(child
),
391 NS_ENSURE_SUCCESS(rv
, rv
);
399 nsXULPrototypeDocument::Write(nsIObjectOutputStream
* aStream
)
403 rv
= aStream
->WriteCompoundObject(mURI
, NS_GET_IID(nsIURI
), PR_TRUE
);
407 count
= mStyleSheetReferences
.Count();
408 rv
|= aStream
->Write32(count
);
411 for (i
= 0; i
< count
; ++i
) {
412 rv
|= aStream
->WriteCompoundObject(mStyleSheetReferences
[i
],
413 NS_GET_IID(nsIURI
), PR_TRUE
);
416 // nsIPrincipal mNodeInfoManager->mPrincipal
417 rv
|= aStream
->WriteObject(mNodeInfoManager
->DocumentPrincipal(),
421 nsCOMArray
<nsINodeInfo
> nodeInfos
;
423 rv
|= GetNodeInfos(mRoot
, nodeInfos
);
425 PRUint32 nodeInfoCount
= nodeInfos
.Count();
426 rv
|= aStream
->Write32(nodeInfoCount
);
427 for (i
= 0; i
< nodeInfoCount
; ++i
) {
428 nsINodeInfo
*nodeInfo
= nodeInfos
[i
];
429 NS_ENSURE_TRUE(nodeInfo
, NS_ERROR_FAILURE
);
431 nsAutoString namespaceURI
;
432 rv
|= nodeInfo
->GetNamespaceURI(namespaceURI
);
433 rv
|= aStream
->WriteWStringZ(namespaceURI
.get());
436 nodeInfo
->GetPrefix(prefix
);
437 PRBool nullPrefix
= DOMStringIsNull(prefix
);
438 rv
|= aStream
->WriteBoolean(nullPrefix
);
440 rv
|= aStream
->WriteWStringZ(prefix
.get());
443 nsAutoString localName
;
444 nodeInfo
->GetName(localName
);
445 rv
|= aStream
->WriteWStringZ(localName
.get());
448 // Now serialize the document contents
449 nsIScriptGlobalObject
* globalObject
= GetScriptGlobalObject();
450 NS_ENSURE_TRUE(globalObject
, NS_ERROR_UNEXPECTED
);
452 count
= mProcessingInstructions
.Length();
453 for (i
= 0; i
< count
; ++i
) {
454 nsXULPrototypePI
* pi
= mProcessingInstructions
[i
];
455 rv
|= pi
->Serialize(aStream
, globalObject
, &nodeInfos
);
459 rv
|= mRoot
->Serialize(aStream
, globalObject
, &nodeInfos
);
465 //----------------------------------------------------------------------
469 nsXULPrototypeDocument::InitPrincipal(nsIURI
* aURI
, nsIPrincipal
* aPrincipal
)
471 NS_ENSURE_ARG_POINTER(aURI
);
474 mNodeInfoManager
->SetDocumentPrincipal(aPrincipal
);
480 nsXULPrototypeDocument::GetURI()
482 NS_ASSERTION(mURI
, "null URI");
487 nsXULPrototypeElement
*
488 nsXULPrototypeDocument::GetRootElement()
495 nsXULPrototypeDocument::SetRootElement(nsXULPrototypeElement
* aElement
)
501 nsXULPrototypeDocument::AddProcessingInstruction(nsXULPrototypePI
* aPI
)
503 NS_PRECONDITION(aPI
, "null ptr");
504 if (!mProcessingInstructions
.AppendElement(aPI
)) {
505 return NS_ERROR_OUT_OF_MEMORY
;
510 const nsTArray
<nsRefPtr
<nsXULPrototypePI
> >&
511 nsXULPrototypeDocument::GetProcessingInstructions() const
513 return mProcessingInstructions
;
517 nsXULPrototypeDocument::AddStyleSheetReference(nsIURI
* aURI
)
519 NS_PRECONDITION(aURI
, "null ptr");
520 if (!mStyleSheetReferences
.AppendObject(aURI
)) {
521 NS_WARNING("mStyleSheetReferences->AppendElement() failed."
522 "Stylesheet overlay dropped.");
526 const nsCOMArray
<nsIURI
>&
527 nsXULPrototypeDocument::GetStyleSheetReferences() const
529 return mStyleSheetReferences
;
533 nsXULPrototypeDocument::GetHeaderData(nsIAtom
* aField
, nsAString
& aData
) const
535 // XXX Not implemented
542 nsXULPrototypeDocument::SetHeaderData(nsIAtom
* aField
, const nsAString
& aData
)
544 // XXX Not implemented
551 nsXULPrototypeDocument::DocumentPrincipal()
553 NS_PRECONDITION(mNodeInfoManager
, "missing nodeInfoManager");
554 return mNodeInfoManager
->DocumentPrincipal();
558 nsXULPrototypeDocument::SetDocumentPrincipal(nsIPrincipal
* aPrincipal
)
560 mNodeInfoManager
->SetDocumentPrincipal(aPrincipal
);
564 nsXULPrototypeDocument::GetNodeInfoManager()
566 return mNodeInfoManager
;
571 nsXULPrototypeDocument::AwaitLoadDone(nsXULDocument
* aDocument
, PRBool
* aResult
)
578 rv
= mPrototypeWaiters
.AppendElement(aDocument
)
579 ? NS_OK
: NS_ERROR_OUT_OF_MEMORY
; // addrefs
587 nsXULPrototypeDocument::NotifyLoadDone()
589 // Call back to each XUL document that raced to start the same
590 // prototype document load, lost the race, but hit the XUL
591 // prototype cache because the winner filled the cache with
592 // the not-yet-loaded prototype object.
598 for (PRUint32 i
= mPrototypeWaiters
.Length(); i
> 0; ) {
600 // PR_TRUE means that OnPrototypeLoadDone will also
601 // call ResumeWalk().
602 rv
= mPrototypeWaiters
[i
]->OnPrototypeLoadDone(PR_TRUE
);
603 if (NS_FAILED(rv
)) break;
605 mPrototypeWaiters
.Clear();
610 //----------------------------------------------------------------------
612 // nsIScriptGlobalObjectOwner methods
615 nsIScriptGlobalObject
*
616 nsXULPrototypeDocument::GetScriptGlobalObject()
619 mGlobalObject
= NewXULPDGlobalObject();
621 return mGlobalObject
;
624 //----------------------------------------------------------------------
626 // nsXULPDGlobalObject
629 nsXULPDGlobalObject::nsXULPDGlobalObject(nsXULPrototypeDocument
* owner
)
630 : mGlobalObjectOwner(owner
)
632 memset(mScriptGlobals
, 0, sizeof(mScriptGlobals
));
636 nsXULPDGlobalObject::~nsXULPDGlobalObject()
640 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPDGlobalObject
)
641 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsXULPDGlobalObject
)
642 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPDGlobalObject
)
645 NS_STID_FOR_INDEX(lang_index
) {
646 cb
.NoteXPCOMChild(tmp
->mScriptContexts
[lang_index
]);
649 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
651 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPDGlobalObject
)
652 NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject
)
653 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal
)
654 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIScriptGlobalObject
)
657 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXULPDGlobalObject
,
658 nsIScriptGlobalObject
)
659 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXULPDGlobalObject
,
660 nsIScriptGlobalObject
)
662 //----------------------------------------------------------------------
664 // nsIScriptGlobalObject methods
668 nsXULPDGlobalObject::SetScriptContext(PRUint32 lang_id
, nsIScriptContext
*aScriptContext
)
670 // almost a clone of nsGlobalWindow
673 PRBool ok
= NS_STID_VALID(lang_id
);
674 NS_ASSERTION(ok
, "Invalid programming language ID requested");
675 NS_ENSURE_TRUE(ok
, NS_ERROR_INVALID_ARG
);
676 PRUint32 lang_ndx
= NS_STID_INDEX(lang_id
);
679 NS_WARNING("Possibly early removal of script object, see bug #41608");
681 // should probably assert the context is clean???
682 aScriptContext
->WillInitializeContext();
683 // NOTE: We init this context with a NULL global - this is subtly
684 // different than nsGlobalWindow which passes 'this'
685 rv
= aScriptContext
->InitContext(nsnull
);
686 NS_ENSURE_SUCCESS(rv
, rv
);
689 NS_ASSERTION(!aScriptContext
|| !mScriptContexts
[lang_ndx
],
690 "Bad call to SetContext()!");
692 void *script_glob
= nsnull
;
694 if (aScriptContext
) {
695 aScriptContext
->DidInitializeContext();
696 script_glob
= aScriptContext
->GetNativeGlobal();
697 NS_ASSERTION(script_glob
, "GetNativeGlobal returned NULL!");
699 mScriptContexts
[lang_ndx
] = aScriptContext
;
700 mScriptGlobals
[lang_ndx
] = script_glob
;
705 nsXULPDGlobalObject::EnsureScriptEnvironment(PRUint32 lang_id
)
707 PRBool ok
= NS_STID_VALID(lang_id
);
708 NS_ASSERTION(ok
, "Invalid programming language ID requested");
709 NS_ENSURE_TRUE(ok
, NS_ERROR_INVALID_ARG
);
710 PRUint32 lang_ndx
= NS_STID_INDEX(lang_id
);
712 if (mScriptContexts
[lang_ndx
] == nsnull
) {
714 NS_ASSERTION(mScriptGlobals
[lang_ndx
] == nsnull
, "Have global without context?");
716 nsCOMPtr
<nsIScriptRuntime
> languageRuntime
;
717 rv
= NS_GetScriptRuntimeByID(lang_id
, getter_AddRefs(languageRuntime
));
718 NS_ENSURE_SUCCESS(rv
, nsnull
);
720 nsCOMPtr
<nsIScriptContext
> ctxNew
;
721 rv
= languageRuntime
->CreateContext(getter_AddRefs(ctxNew
));
722 // For JS, we have to setup a special global object. We do this then
723 // attach it as the global for this context. Then, ::SetScriptContext
724 // will re-fetch the global and set it up in our language globals array.
725 if (lang_id
== nsIProgrammingLanguage::JAVASCRIPT
) {
726 // some special JS specific code we should abstract
727 JSContext
*cx
= (JSContext
*)ctxNew
->GetNativeContext();
728 JSAutoRequest
ar(cx
);
729 JSObject
*newGlob
= ::JS_NewObject(cx
, &gSharedGlobalClass
, nsnull
, nsnull
);
733 ::JS_SetGlobalObject(cx
, newGlob
);
735 // Add an owning reference from JS back to us. This'll be
736 // released when the JSObject is finalized.
737 ::JS_SetPrivate(cx
, newGlob
, this);
741 NS_ENSURE_SUCCESS(rv
, nsnull
);
742 rv
= SetScriptContext(lang_id
, ctxNew
);
743 NS_ENSURE_SUCCESS(rv
, nsnull
);
749 nsXULPDGlobalObject::GetScriptContext(PRUint32 lang_id
)
751 // This global object creates a context on demand - do that now.
752 nsresult rv
= EnsureScriptEnvironment(lang_id
);
754 NS_ERROR("Failed to setup script language");
757 // Note that EnsureScriptEnvironment has validated lang_id
758 return mScriptContexts
[NS_STID_INDEX(lang_id
)];
762 nsXULPDGlobalObject::GetScriptGlobal(PRUint32 lang_id
)
764 PRBool ok
= NS_STID_VALID(lang_id
);
765 NS_ASSERTION(ok
, "Invalid programming language ID requested");
766 NS_ENSURE_TRUE(ok
, nsnull
);
767 PRUint32 lang_ndx
= NS_STID_INDEX(lang_id
);
769 NS_ASSERTION(mScriptContexts
[lang_ndx
] != nsnull
, "Querying for global before setting up context?");
770 return mScriptGlobals
[lang_ndx
];
775 nsXULPDGlobalObject::ClearGlobalObjectOwner()
777 NS_ASSERTION(!mCachedPrincipal
, "This shouldn't ever be set until now!");
779 // Cache mGlobalObjectOwner's principal if possible.
780 if (this != nsXULPrototypeDocument::gSystemGlobal
)
781 mCachedPrincipal
= mGlobalObjectOwner
->DocumentPrincipal();
784 NS_STID_FOR_INDEX(lang_ndx
) {
785 if (mScriptContexts
[lang_ndx
]) {
786 mScriptContexts
[lang_ndx
]->FinalizeContext();
787 mScriptContexts
[lang_ndx
] = nsnull
;
791 mGlobalObjectOwner
= nsnull
;
796 nsXULPDGlobalObject::OnFinalize(PRUint32 aLangID
, void *aObject
)
798 NS_ASSERTION(NS_STID_VALID(aLangID
), "Invalid language ID");
799 NS_ASSERTION(aObject
== mScriptGlobals
[NS_STID_INDEX(aLangID
)],
800 "Wrong object finalized!");
801 mScriptGlobals
[NS_STID_INDEX(aLangID
)] = nsnull
;
805 nsXULPDGlobalObject::SetScriptsEnabled(PRBool aEnabled
, PRBool aFireTimeouts
)
811 nsXULPDGlobalObject::SetNewArguments(nsIArray
*aArguments
)
813 NS_NOTREACHED("waaah!");
814 return NS_ERROR_UNEXPECTED
;
817 //----------------------------------------------------------------------
819 // nsIScriptObjectPrincipal methods
823 nsXULPDGlobalObject::GetPrincipal()
825 if (!mGlobalObjectOwner
) {
826 // See nsXULPrototypeDocument::NewXULPDGlobalObject, the comment
827 // about gSystemGlobal implying gSystemPrincipal.
828 if (this == nsXULPrototypeDocument::gSystemGlobal
) {
829 return nsXULPrototypeDocument::gSystemPrincipal
;
831 // Return the cached principal if it exists.
832 return mCachedPrincipal
;
835 return mGlobalObjectOwner
->DocumentPrincipal();