/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** 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. * * 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): * Chris Waterson * L. David Baron * Ben Goodger * Mark Hammond * * 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 ***** */ #include "nsXULPrototypeDocument.h" #include "nsXULDocument.h" #include "nsAString.h" #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h" #include "nsIPrincipal.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptObjectPrincipal.h" #include "nsIScriptSecurityManager.h" #include "nsIScriptRuntime.h" #include "nsIServiceManager.h" #include "nsIArray.h" #include "nsIURI.h" #include "jsapi.h" #include "nsString.h" #include "nsIConsoleService.h" #include "nsIScriptError.h" #include "nsIDOMScriptObjectFactory.h" #include "nsDOMCID.h" #include "nsNodeInfoManager.h" #include "nsContentUtils.h" #include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); class nsXULPDGlobalObject : public nsIScriptGlobalObject, public nsIScriptObjectPrincipal { public: nsXULPDGlobalObject(nsXULPrototypeDocument* owner); // nsISupports interface NS_DECL_CYCLE_COLLECTING_ISUPPORTS // nsIScriptGlobalObject methods virtual void OnFinalize(PRUint32 aLangID, void *aGlobal); virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts); virtual nsresult SetNewArguments(nsIArray *aArguments); virtual void *GetScriptGlobal(PRUint32 lang); virtual nsresult EnsureScriptEnvironment(PRUint32 aLangID); virtual nsIScriptContext *GetScriptContext(PRUint32 lang); virtual nsresult SetScriptContext(PRUint32 language, nsIScriptContext *ctx); // nsIScriptObjectPrincipal methods virtual nsIPrincipal* GetPrincipal(); NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULPDGlobalObject, nsIScriptGlobalObject) void ClearGlobalObjectOwner(); protected: virtual ~nsXULPDGlobalObject(); nsXULPrototypeDocument* mGlobalObjectOwner; // weak reference nsCOMPtr mScriptContexts[NS_STID_ARRAY_UBOUND]; void * mScriptGlobals[NS_STID_ARRAY_UBOUND]; nsCOMPtr mCachedPrincipal; static JSClass gSharedGlobalClass; }; nsIPrincipal* nsXULPrototypeDocument::gSystemPrincipal; nsXULPDGlobalObject* nsXULPrototypeDocument::gSystemGlobal; PRUint32 nsXULPrototypeDocument::gRefCnt; void PR_CALLBACK nsXULPDGlobalObject_finalize(JSContext *cx, JSObject *obj) { nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(cx, obj); nsCOMPtr sgo(do_QueryInterface(nativeThis)); if (sgo) { sgo->OnFinalize(nsIProgrammingLanguage::JAVASCRIPT, obj); } // The addref was part of JSObject construction NS_RELEASE(nativeThis); } JSBool PR_CALLBACK nsXULPDGlobalObject_resolve(JSContext *cx, JSObject *obj, jsval id) { JSBool did_resolve = JS_FALSE; return JS_ResolveStandardClass(cx, obj, id, &did_resolve); } JSClass nsXULPDGlobalObject::gSharedGlobalClass = { "nsXULPrototypeScript compilation scope", JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_GLOBAL_FLAGS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, nsXULPDGlobalObject_resolve, JS_ConvertStub, nsXULPDGlobalObject_finalize }; //---------------------------------------------------------------------- // // ctors, dtors, n' stuff // nsXULPrototypeDocument::nsXULPrototypeDocument() : mRoot(nsnull), mLoaded(PR_FALSE) { ++gRefCnt; } nsresult nsXULPrototypeDocument::Init() { mNodeInfoManager = new nsNodeInfoManager(); NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY); return mNodeInfoManager->Init(nsnull); } nsXULPrototypeDocument::~nsXULPrototypeDocument() { if (mGlobalObject) { // cleaup cycles etc. mGlobalObject->ClearGlobalObjectOwner(); } PRUint32 count = mProcessingInstructions.Length(); for (PRUint32 i = 0; i < count; i++) { mProcessingInstructions[i]->Release(); } if (mRoot) mRoot->ReleaseSubtree(); if (--gRefCnt == 0) { NS_IF_RELEASE(gSystemPrincipal); NS_IF_RELEASE(gSystemGlobal); } } NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsXULPrototypeDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPrototypeDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mRoot, nsXULPrototypeElement) cb.NoteXPCOMChild(static_cast(tmp->mGlobalObject)); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mNodeInfoManager, nsNodeInfoManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPrototypeDocument) NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObjectOwner) NS_INTERFACE_MAP_ENTRY(nsISerializable) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObjectOwner) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXULPrototypeDocument, nsIScriptGlobalObjectOwner) NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXULPrototypeDocument, nsIScriptGlobalObjectOwner) NS_IMETHODIMP NS_NewXULPrototypeDocument(nsXULPrototypeDocument** aResult) { *aResult = new nsXULPrototypeDocument(); if (! *aResult) return NS_ERROR_OUT_OF_MEMORY; nsresult rv; rv = (*aResult)->Init(); if (NS_FAILED(rv)) { delete *aResult; *aResult = nsnull; return rv; } NS_ADDREF(*aResult); return rv; } // Helper method that shares a system global among all prototype documents // that have the system principal as their security principal. Called by // nsXULPrototypeDocument::Read and nsXULPDGlobalObject::GetGlobalObject. // This method greatly reduces the number of nsXULPDGlobalObjects and their // nsIScriptContexts in apps that load many XUL documents via chrome: URLs. nsXULPDGlobalObject * nsXULPrototypeDocument::NewXULPDGlobalObject() { // Now compare DocumentPrincipal() to gSystemPrincipal, in order to create // gSystemGlobal if the two pointers are equal. Thus, gSystemGlobal // implies gSystemPrincipal. nsXULPDGlobalObject *global; if (DocumentPrincipal() == gSystemPrincipal) { if (!gSystemGlobal) { gSystemGlobal = new nsXULPDGlobalObject(nsnull); if (! gSystemGlobal) return nsnull; NS_ADDREF(gSystemGlobal); } global = gSystemGlobal; } else { global = new nsXULPDGlobalObject(this); // does not refcount if (! global) return nsnull; } return global; } //---------------------------------------------------------------------- // // nsISerializable methods // NS_IMETHODIMP nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream) { nsresult rv; rv = aStream->ReadObject(PR_TRUE, getter_AddRefs(mURI)); PRUint32 count, i; nsCOMPtr styleOverlayURI; rv |= aStream->Read32(&count); if (NS_FAILED(rv)) return rv; for (i = 0; i < count; ++i) { rv |= aStream->ReadObject(PR_TRUE, getter_AddRefs(styleOverlayURI)); mStyleSheetReferences.AppendObject(styleOverlayURI); } // nsIPrincipal mNodeInfoManager->mPrincipal nsCOMPtr principal; rv |= aStream->ReadObject(PR_TRUE, getter_AddRefs(principal)); // Better safe than sorry.... mNodeInfoManager->SetDocumentPrincipal(principal); // nsIScriptGlobalObject mGlobalObject mGlobalObject = NewXULPDGlobalObject(); if (! mGlobalObject) return NS_ERROR_OUT_OF_MEMORY; mRoot = new nsXULPrototypeElement(); if (! mRoot) return NS_ERROR_OUT_OF_MEMORY; // nsINodeInfo table nsCOMArray nodeInfos; rv |= aStream->Read32(&count); nsAutoString namespaceURI, qualifiedName; for (i = 0; i < count; ++i) { rv |= aStream->ReadString(namespaceURI); rv |= aStream->ReadString(qualifiedName); nsCOMPtr nodeInfo; rv |= mNodeInfoManager->GetNodeInfo(qualifiedName, namespaceURI, getter_AddRefs(nodeInfo)); if (!nodeInfos.AppendObject(nodeInfo)) rv |= NS_ERROR_OUT_OF_MEMORY; } // Document contents PRUint32 type; while (NS_SUCCEEDED(rv)) { rv |= aStream->Read32(&type); if ((nsXULPrototypeNode::Type)type == nsXULPrototypeNode::eType_PI) { nsXULPrototypePI* pi = new nsXULPrototypePI(); if (! pi) { rv |= NS_ERROR_OUT_OF_MEMORY; break; } rv |= pi->Deserialize(aStream, mGlobalObject, mURI, &nodeInfos); rv |= AddProcessingInstruction(pi); } else if ((nsXULPrototypeNode::Type)type == nsXULPrototypeNode::eType_Element) { rv |= mRoot->Deserialize(aStream, mGlobalObject, mURI, &nodeInfos); break; } else { NS_NOTREACHED("Unexpected prototype node type"); rv |= NS_ERROR_FAILURE; break; } } rv |= NotifyLoadDone(); return rv; } static nsresult GetNodeInfos(nsXULPrototypeElement* aPrototype, nsCOMArray& aArray) { nsresult rv; if (aArray.IndexOf(aPrototype->mNodeInfo) < 0) { if (!aArray.AppendObject(aPrototype->mNodeInfo)) { return NS_ERROR_OUT_OF_MEMORY; } } // Search attributes PRUint32 i; for (i = 0; i < aPrototype->mNumAttributes; ++i) { nsCOMPtr ni; nsAttrName* name = &aPrototype->mAttributes[i].mName; if (name->IsAtom()) { rv = aPrototype->mNodeInfo->NodeInfoManager()-> GetNodeInfo(name->Atom(), nsnull, kNameSpaceID_None, getter_AddRefs(ni)); NS_ENSURE_SUCCESS(rv, rv); } else { ni = name->NodeInfo(); } if (aArray.IndexOf(ni) < 0) { if (!aArray.AppendObject(ni)) { return NS_ERROR_OUT_OF_MEMORY; } } } // Search children for (i = 0; i < aPrototype->mNumChildren; ++i) { nsXULPrototypeNode* child = aPrototype->mChildren[i]; if (child->mType == nsXULPrototypeNode::eType_Element) { rv = GetNodeInfos(static_cast(child), aArray); NS_ENSURE_SUCCESS(rv, rv); } } return NS_OK; } NS_IMETHODIMP nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream) { nsresult rv; rv = aStream->WriteCompoundObject(mURI, NS_GET_IID(nsIURI), PR_TRUE); PRUint32 count; count = mStyleSheetReferences.Count(); rv |= aStream->Write32(count); PRUint32 i; for (i = 0; i < count; ++i) { rv |= aStream->WriteCompoundObject(mStyleSheetReferences[i], NS_GET_IID(nsIURI), PR_TRUE); } // nsIPrincipal mNodeInfoManager->mPrincipal rv |= aStream->WriteObject(mNodeInfoManager->DocumentPrincipal(), PR_TRUE); // nsINodeInfo table nsCOMArray nodeInfos; if (mRoot) rv |= GetNodeInfos(mRoot, nodeInfos); PRUint32 nodeInfoCount = nodeInfos.Count(); rv |= aStream->Write32(nodeInfoCount); for (i = 0; i < nodeInfoCount; ++i) { nsINodeInfo *nodeInfo = nodeInfos[i]; NS_ENSURE_TRUE(nodeInfo, NS_ERROR_FAILURE); nsAutoString namespaceURI; rv |= nodeInfo->GetNamespaceURI(namespaceURI); rv |= aStream->WriteWStringZ(namespaceURI.get()); nsAutoString qualifiedName; nodeInfo->GetQualifiedName(qualifiedName); rv |= aStream->WriteWStringZ(qualifiedName.get()); } // Now serialize the document contents nsIScriptGlobalObject* globalObject = GetScriptGlobalObject(); NS_ENSURE_TRUE(globalObject, NS_ERROR_UNEXPECTED); count = mProcessingInstructions.Length(); for (i = 0; i < count; ++i) { nsXULPrototypePI* pi = mProcessingInstructions[i]; rv |= pi->Serialize(aStream, globalObject, &nodeInfos); } if (mRoot) rv |= mRoot->Serialize(aStream, globalObject, &nodeInfos); return rv; } //---------------------------------------------------------------------- // nsresult nsXULPrototypeDocument::InitPrincipal(nsIURI* aURI, nsIPrincipal* aPrincipal) { NS_ENSURE_ARG_POINTER(aURI); mURI = aURI; mNodeInfoManager->SetDocumentPrincipal(aPrincipal); return NS_OK; } nsIURI* nsXULPrototypeDocument::GetURI() { NS_ASSERTION(mURI, "null URI"); return mURI; } nsXULPrototypeElement* nsXULPrototypeDocument::GetRootElement() { return mRoot; } void nsXULPrototypeDocument::SetRootElement(nsXULPrototypeElement* aElement) { mRoot = aElement; } nsresult nsXULPrototypeDocument::AddProcessingInstruction(nsXULPrototypePI* aPI) { NS_PRECONDITION(aPI, "null ptr"); if (!mProcessingInstructions.AppendElement(aPI)) { return NS_ERROR_OUT_OF_MEMORY; } return NS_OK; } const nsTArray& nsXULPrototypeDocument::GetProcessingInstructions() const { return mProcessingInstructions; } void nsXULPrototypeDocument::AddStyleSheetReference(nsIURI* aURI) { NS_PRECONDITION(aURI, "null ptr"); if (!mStyleSheetReferences.AppendObject(aURI)) { NS_WARNING("mStyleSheetReferences->AppendElement() failed." "Stylesheet overlay dropped."); } } const nsCOMArray& nsXULPrototypeDocument::GetStyleSheetReferences() const { return mStyleSheetReferences; } NS_IMETHODIMP nsXULPrototypeDocument::GetHeaderData(nsIAtom* aField, nsAString& aData) const { // XXX Not implemented aData.Truncate(); return NS_OK; } NS_IMETHODIMP nsXULPrototypeDocument::SetHeaderData(nsIAtom* aField, const nsAString& aData) { // XXX Not implemented return NS_OK; } nsIPrincipal* nsXULPrototypeDocument::DocumentPrincipal() { NS_PRECONDITION(mNodeInfoManager, "missing nodeInfoManager"); return mNodeInfoManager->DocumentPrincipal(); } void nsXULPrototypeDocument::SetDocumentPrincipal(nsIPrincipal* aPrincipal) { mNodeInfoManager->SetDocumentPrincipal(aPrincipal); } nsNodeInfoManager* nsXULPrototypeDocument::GetNodeInfoManager() { return mNodeInfoManager; } nsresult nsXULPrototypeDocument::AwaitLoadDone(nsXULDocument* aDocument, PRBool* aResult) { nsresult rv = NS_OK; *aResult = mLoaded; if (!mLoaded) { rv = mPrototypeWaiters.AppendElement(aDocument) ? NS_OK : NS_ERROR_OUT_OF_MEMORY; // addrefs } return rv; } nsresult nsXULPrototypeDocument::NotifyLoadDone() { // Call back to each XUL document that raced to start the same // prototype document load, lost the race, but hit the XUL // prototype cache because the winner filled the cache with // the not-yet-loaded prototype object. nsresult rv = NS_OK; mLoaded = PR_TRUE; for (PRUint32 i = mPrototypeWaiters.Length(); i > 0; ) { --i; // PR_TRUE means that OnPrototypeLoadDone will also // call ResumeWalk(). rv = mPrototypeWaiters[i]->OnPrototypeLoadDone(PR_TRUE); if (NS_FAILED(rv)) break; } mPrototypeWaiters.Clear(); return rv; } //---------------------------------------------------------------------- // // nsIScriptGlobalObjectOwner methods // nsIScriptGlobalObject* nsXULPrototypeDocument::GetScriptGlobalObject() { if (!mGlobalObject) mGlobalObject = NewXULPDGlobalObject(); return mGlobalObject; } //---------------------------------------------------------------------- // // nsXULPDGlobalObject // nsXULPDGlobalObject::nsXULPDGlobalObject(nsXULPrototypeDocument* owner) : mGlobalObjectOwner(owner) { memset(mScriptGlobals, 0, sizeof(mScriptGlobals)); } nsXULPDGlobalObject::~nsXULPDGlobalObject() { } NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPDGlobalObject) NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsXULPDGlobalObject) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPDGlobalObject) { PRUint32 lang_index; NS_STID_FOR_INDEX(lang_index) { cb.NoteXPCOMChild(tmp->mScriptContexts[lang_index]); } } NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPDGlobalObject) NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject) NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObject) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXULPDGlobalObject, nsIScriptGlobalObject) NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXULPDGlobalObject, nsIScriptGlobalObject) //---------------------------------------------------------------------- // // nsIScriptGlobalObject methods // nsresult nsXULPDGlobalObject::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aScriptContext) { // almost a clone of nsGlobalWindow nsresult rv; PRBool ok = NS_STID_VALID(lang_id); NS_ASSERTION(ok, "Invalid programming language ID requested"); NS_ENSURE_TRUE(ok, NS_ERROR_INVALID_ARG); PRUint32 lang_ndx = NS_STID_INDEX(lang_id); if (!aScriptContext) NS_WARNING("Possibly early removal of script object, see bug #41608"); else { // should probably assert the context is clean??? aScriptContext->WillInitializeContext(); // NOTE: We init this context with a NULL global - this is subtly // different than nsGlobalWindow which passes 'this' rv = aScriptContext->InitContext(nsnull); NS_ENSURE_SUCCESS(rv, rv); } NS_ASSERTION(!aScriptContext || !mScriptContexts[lang_ndx], "Bad call to SetContext()!"); void *script_glob = nsnull; if (aScriptContext) { aScriptContext->DidInitializeContext(); script_glob = aScriptContext->GetNativeGlobal(); NS_ASSERTION(script_glob, "GetNativeGlobal returned NULL!"); } mScriptContexts[lang_ndx] = aScriptContext; mScriptGlobals[lang_ndx] = script_glob; return NS_OK; } nsresult nsXULPDGlobalObject::EnsureScriptEnvironment(PRUint32 lang_id) { PRBool ok = NS_STID_VALID(lang_id); NS_ASSERTION(ok, "Invalid programming language ID requested"); NS_ENSURE_TRUE(ok, NS_ERROR_INVALID_ARG); PRUint32 lang_ndx = NS_STID_INDEX(lang_id); if (mScriptContexts[lang_ndx] == nsnull) { nsresult rv; NS_ASSERTION(mScriptGlobals[lang_ndx] == nsnull, "Have global without context?"); nsCOMPtr languageRuntime; rv = NS_GetScriptRuntimeByID(lang_id, getter_AddRefs(languageRuntime)); NS_ENSURE_SUCCESS(rv, nsnull); nsCOMPtr ctxNew; rv = languageRuntime->CreateContext(getter_AddRefs(ctxNew)); // For JS, we have to setup a special global object. We do this then // attach it as the global for this context. Then, ::SetScriptContext // will re-fetch the global and set it up in our language globals array. if (lang_id == nsIProgrammingLanguage::JAVASCRIPT) { // some special JS specific code we should abstract JSContext *cx = (JSContext *)ctxNew->GetNativeContext(); JSAutoRequest ar(cx); JSObject *newGlob = ::JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull); if (!newGlob) return nsnull; ::JS_SetGlobalObject(cx, newGlob); // Add an owning reference from JS back to us. This'll be // released when the JSObject is finalized. ::JS_SetPrivate(cx, newGlob, this); NS_ADDREF(this); } NS_ENSURE_SUCCESS(rv, nsnull); rv = SetScriptContext(lang_id, ctxNew); NS_ENSURE_SUCCESS(rv, nsnull); } return NS_OK; } nsIScriptContext * nsXULPDGlobalObject::GetScriptContext(PRUint32 lang_id) { // This global object creates a context on demand - do that now. nsresult rv = EnsureScriptEnvironment(lang_id); if (NS_FAILED(rv)) { NS_ERROR("Failed to setup script language"); return nsnull; } // Note that EnsureScriptEnvironment has validated lang_id return mScriptContexts[NS_STID_INDEX(lang_id)]; } void * nsXULPDGlobalObject::GetScriptGlobal(PRUint32 lang_id) { PRBool ok = NS_STID_VALID(lang_id); NS_ASSERTION(ok, "Invalid programming language ID requested"); NS_ENSURE_TRUE(ok, nsnull); PRUint32 lang_ndx = NS_STID_INDEX(lang_id); NS_ASSERTION(mScriptContexts[lang_ndx] != nsnull, "Querying for global before setting up context?"); return mScriptGlobals[lang_ndx]; } void nsXULPDGlobalObject::ClearGlobalObjectOwner() { NS_ASSERTION(!mCachedPrincipal, "This shouldn't ever be set until now!"); // Cache mGlobalObjectOwner's principal if possible. if (this != nsXULPrototypeDocument::gSystemGlobal) mCachedPrincipal = mGlobalObjectOwner->DocumentPrincipal(); PRUint32 lang_ndx; NS_STID_FOR_INDEX(lang_ndx) { if (mScriptContexts[lang_ndx]) { mScriptContexts[lang_ndx]->FinalizeContext(); mScriptContexts[lang_ndx] = nsnull; } } mGlobalObjectOwner = nsnull; } void nsXULPDGlobalObject::OnFinalize(PRUint32 aLangID, void *aObject) { NS_ASSERTION(NS_STID_VALID(aLangID), "Invalid language ID"); NS_ASSERTION(aObject == mScriptGlobals[NS_STID_INDEX(aLangID)], "Wrong object finalized!"); mScriptGlobals[NS_STID_INDEX(aLangID)] = nsnull; } void nsXULPDGlobalObject::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) { // We don't care... } nsresult nsXULPDGlobalObject::SetNewArguments(nsIArray *aArguments) { NS_NOTREACHED("waaah!"); return NS_ERROR_UNEXPECTED; } //---------------------------------------------------------------------- // // nsIScriptObjectPrincipal methods // nsIPrincipal* nsXULPDGlobalObject::GetPrincipal() { if (!mGlobalObjectOwner) { // See nsXULPrototypeDocument::NewXULPDGlobalObject, the comment // about gSystemGlobal implying gSystemPrincipal. if (this == nsXULPrototypeDocument::gSystemGlobal) { return nsXULPrototypeDocument::gSystemPrincipal; } // Return the cached principal if it exists. return mCachedPrincipal; } return mGlobalObjectOwner->DocumentPrincipal(); }