LCOV - code coverage report
Current view: directory - content/xbl/src - nsXBLDocumentInfo.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 334 4 1.2 %
Date: 2012-06-02 Functions: 61 3 4.9 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=80: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsXBLDocumentInfo.h"
      40                 : #include "nsHashtable.h"
      41                 : #include "nsIDocument.h"
      42                 : #include "nsXBLPrototypeBinding.h"
      43                 : #include "nsIScriptObjectPrincipal.h"
      44                 : #include "nsIScriptGlobalObject.h"
      45                 : #include "nsIScriptContext.h"
      46                 : #include "nsIScriptRuntime.h"
      47                 : #include "nsIDOMScriptObjectFactory.h"
      48                 : #include "jsapi.h"
      49                 : #include "nsIURI.h"
      50                 : #include "nsIConsoleService.h"
      51                 : #include "nsIScriptError.h"
      52                 : #include "nsIChromeRegistry.h"
      53                 : #include "nsIPrincipal.h"
      54                 : #include "nsIScriptSecurityManager.h"
      55                 : #include "nsContentUtils.h"
      56                 : #include "nsDOMJSUtils.h"
      57                 : #include "mozilla/Services.h"
      58                 : #include "xpcpublic.h"
      59                 : #include "mozilla/scache/StartupCache.h"
      60                 : #include "mozilla/scache/StartupCacheUtils.h"
      61                 : #include "nsCCUncollectableMarker.h"
      62                 : 
      63                 : using namespace mozilla::scache;
      64                 : 
      65                 : static const char kXBLCachePrefix[] = "xblcache";
      66                 : 
      67                 : static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
      68                 : 
      69                 : // An XBLDocumentInfo object has a special context associated with it which we can use to pre-compile 
      70                 : // properties and methods of XBL bindings against.
      71                 : class nsXBLDocGlobalObject : public nsIScriptGlobalObject,
      72                 :                              public nsIScriptObjectPrincipal
      73                 : {
      74                 : public:
      75                 :   nsXBLDocGlobalObject(nsIScriptGlobalObjectOwner *aGlobalObjectOwner);
      76                 : 
      77                 :   // nsISupports interface
      78               0 :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
      79                 :   
      80                 :   // nsIScriptGlobalObject methods
      81                 :   virtual nsresult EnsureScriptEnvironment(PRUint32 aLangID);
      82                 :   virtual nsresult SetScriptContext(PRUint32 lang_id, nsIScriptContext *aContext);
      83                 : 
      84                 :   virtual nsIScriptContext *GetContext();
      85                 :   virtual JSObject *GetGlobalJSObject();
      86                 :   virtual void OnFinalize(JSObject* aObject);
      87                 :   virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts);
      88                 : 
      89                 :   // nsIScriptObjectPrincipal methods
      90                 :   virtual nsIPrincipal* GetPrincipal();
      91                 : 
      92                 :   static JSBool doCheckAccess(JSContext *cx, JSObject *obj, jsid id,
      93                 :                               PRUint32 accessType);
      94                 : 
      95            1464 :   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXBLDocGlobalObject,
      96                 :                                            nsIScriptGlobalObject)
      97                 : 
      98                 :   void ClearGlobalObjectOwner();
      99                 : 
     100                 : protected:
     101                 :   virtual ~nsXBLDocGlobalObject();
     102                 : 
     103                 :   void SetContext(nsIScriptContext *aContext);
     104                 :   nsIScriptContext *GetScriptContext(PRUint32 language);
     105                 : 
     106                 :   nsCOMPtr<nsIScriptContext> mScriptContext;
     107                 :   JSObject *mJSObject;    // XXX JS language rabies bigotry badness
     108                 : 
     109                 :   nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // weak reference
     110                 :   static JSClass gSharedGlobalClass;
     111                 : };
     112                 : 
     113                 : JSBool
     114               0 : nsXBLDocGlobalObject::doCheckAccess(JSContext *cx, JSObject *obj, jsid id, PRUint32 accessType)
     115                 : {
     116               0 :   nsIScriptSecurityManager *ssm = nsContentUtils::GetSecurityManager();
     117               0 :   if (!ssm) {
     118               0 :     ::JS_ReportError(cx, "Unable to verify access to a global object property.");
     119               0 :     return JS_FALSE;
     120                 :   }
     121                 : 
     122                 :   // Make sure to actually operate on our object, and not some object further
     123                 :   // down on the proto chain.
     124               0 :   while (JS_GetClass(obj) != &nsXBLDocGlobalObject::gSharedGlobalClass) {
     125               0 :     obj = ::JS_GetPrototype(obj);
     126               0 :     if (!obj) {
     127               0 :       ::JS_ReportError(cx, "Invalid access to a global object property.");
     128               0 :       return JS_FALSE;
     129                 :     }
     130                 :   }
     131                 : 
     132               0 :   nsresult rv = ssm->CheckPropertyAccess(cx, obj, JS_GetClass(obj)->name,
     133               0 :                                          id, accessType);
     134               0 :   return NS_SUCCEEDED(rv);
     135                 : }
     136                 : 
     137                 : static JSBool
     138               0 : nsXBLDocGlobalObject_getProperty(JSContext *cx, JSObject *obj,
     139                 :                                  jsid id, jsval *vp)
     140                 : {
     141                 :   return nsXBLDocGlobalObject::
     142               0 :     doCheckAccess(cx, obj, id, nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
     143                 : }
     144                 : 
     145                 : static JSBool
     146               0 : nsXBLDocGlobalObject_setProperty(JSContext *cx, JSObject *obj,
     147                 :                                  jsid id, JSBool strict, jsval *vp)
     148                 : {
     149                 :   return nsXBLDocGlobalObject::
     150               0 :     doCheckAccess(cx, obj, id, nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
     151                 : }
     152                 : 
     153                 : static JSBool
     154               0 : nsXBLDocGlobalObject_checkAccess(JSContext *cx, JSObject *obj, jsid id,
     155                 :                                  JSAccessMode mode, jsval *vp)
     156                 : {
     157                 :   PRUint32 translated;
     158               0 :   if (mode & JSACC_WRITE) {
     159               0 :     translated = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
     160                 :   } else {
     161               0 :     translated = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
     162                 :   }
     163                 : 
     164                 :   return nsXBLDocGlobalObject::
     165               0 :     doCheckAccess(cx, obj, id, translated);
     166                 : }
     167                 : 
     168                 : static void
     169               0 : nsXBLDocGlobalObject_finalize(JSContext *cx, JSObject *obj)
     170                 : {
     171               0 :   nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(obj);
     172                 : 
     173               0 :   nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
     174                 : 
     175               0 :   if (sgo)
     176               0 :     sgo->OnFinalize(obj);
     177                 : 
     178                 :   // The addref was part of JSObject construction
     179               0 :   NS_RELEASE(nativeThis);
     180               0 : }
     181                 : 
     182                 : static JSBool
     183               0 : nsXBLDocGlobalObject_resolve(JSContext *cx, JSObject *obj, jsid id)
     184                 : {
     185               0 :   JSBool did_resolve = JS_FALSE;
     186               0 :   return JS_ResolveStandardClass(cx, obj, id, &did_resolve);
     187                 : }
     188                 : 
     189                 : 
     190                 : JSClass nsXBLDocGlobalObject::gSharedGlobalClass = {
     191                 :     "nsXBLPrototypeScript compilation scope",
     192                 :     XPCONNECT_GLOBAL_FLAGS,
     193                 :     JS_PropertyStub,  JS_PropertyStub,
     194                 :     nsXBLDocGlobalObject_getProperty, nsXBLDocGlobalObject_setProperty,
     195                 :     JS_EnumerateStub, nsXBLDocGlobalObject_resolve,
     196                 :     JS_ConvertStub, nsXBLDocGlobalObject_finalize,
     197                 :     nsXBLDocGlobalObject_checkAccess, NULL, NULL, NULL,
     198                 :     TraceXPCGlobal
     199                 : };
     200                 : 
     201                 : //----------------------------------------------------------------------
     202                 : //
     203                 : // nsXBLDocGlobalObject
     204                 : //
     205                 : 
     206               0 : nsXBLDocGlobalObject::nsXBLDocGlobalObject(nsIScriptGlobalObjectOwner *aGlobalObjectOwner)
     207                 :     : mJSObject(nsnull),
     208               0 :       mGlobalObjectOwner(aGlobalObjectOwner) // weak reference
     209                 : {
     210               0 : }
     211                 : 
     212                 : 
     213               0 : nsXBLDocGlobalObject::~nsXBLDocGlobalObject()
     214               0 : {}
     215                 : 
     216                 : 
     217            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsXBLDocGlobalObject, mScriptContext)
     218                 : 
     219               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocGlobalObject)
     220               0 :   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
     221               0 :   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
     222               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObject)
     223               0 : NS_INTERFACE_MAP_END
     224                 : 
     225               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocGlobalObject)
     226               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLDocGlobalObject)
     227                 : 
     228                 : void
     229               0 : XBL_ProtoErrorReporter(JSContext *cx,
     230                 :                        const char *message,
     231                 :                        JSErrorReport *report)
     232                 : {
     233                 :   // Make an nsIScriptError and populate it with information from
     234                 :   // this error.
     235                 :   nsCOMPtr<nsIScriptError>
     236               0 :     errorObject(do_CreateInstance("@mozilla.org/scripterror;1"));
     237                 :   nsCOMPtr<nsIConsoleService>
     238               0 :     consoleService(do_GetService("@mozilla.org/consoleservice;1"));
     239                 : 
     240               0 :   if (errorObject && consoleService) {
     241               0 :     PRUint32 column = report->uctokenptr - report->uclinebuf;
     242                 : 
     243               0 :     errorObject->Init
     244                 :          (reinterpret_cast<const PRUnichar*>(report->ucmessage),
     245               0 :           NS_ConvertUTF8toUTF16(report->filename).get(),
     246                 :           reinterpret_cast<const PRUnichar*>(report->uclinebuf),
     247                 :           report->lineno, column, report->flags,
     248                 :           "xbl javascript"
     249               0 :           );
     250               0 :     consoleService->LogMessage(errorObject);
     251                 :   }
     252               0 : }
     253                 : 
     254                 : //----------------------------------------------------------------------
     255                 : //
     256                 : // nsIScriptGlobalObject methods
     257                 : //
     258                 : 
     259                 : void
     260               0 : nsXBLDocGlobalObject::SetContext(nsIScriptContext *aScriptContext)
     261                 : {
     262               0 :   if (!aScriptContext) {
     263               0 :     mScriptContext = nsnull;
     264               0 :     return;
     265                 :   }
     266               0 :   NS_ASSERTION(aScriptContext->GetScriptTypeID() ==
     267                 :                                         nsIProgrammingLanguage::JAVASCRIPT,
     268                 :                "xbl is not multi-language");
     269               0 :   aScriptContext->WillInitializeContext();
     270                 :   // NOTE: We init this context with a NULL global, so we automatically
     271                 :   // hook up to the existing nsIScriptGlobalObject global setup by
     272                 :   // nsGlobalWindow.
     273                 :   nsresult rv;
     274               0 :   rv = aScriptContext->InitContext();
     275               0 :   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Script Language's InitContext failed");
     276               0 :   aScriptContext->SetGCOnDestruction(false);
     277               0 :   aScriptContext->DidInitializeContext();
     278                 :   // and we set up our global manually
     279               0 :   mScriptContext = aScriptContext;
     280                 : }
     281                 : 
     282                 : nsresult
     283               0 : nsXBLDocGlobalObject::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aContext)
     284                 : {
     285               0 :   NS_ASSERTION(lang_id == nsIProgrammingLanguage::JAVASCRIPT, "Only JS allowed!");
     286               0 :   SetContext(aContext);
     287               0 :   return NS_OK;
     288                 : }
     289                 : 
     290                 : nsIScriptContext *
     291               0 : nsXBLDocGlobalObject::GetScriptContext(PRUint32 language)
     292                 : {
     293                 :   // This impl still assumes JS
     294               0 :   NS_ENSURE_TRUE(language==nsIProgrammingLanguage::JAVASCRIPT, nsnull);
     295               0 :   return GetContext();
     296                 : }
     297                 : 
     298                 : nsresult
     299               0 : nsXBLDocGlobalObject::EnsureScriptEnvironment(PRUint32 aLangID)
     300                 : {
     301               0 :   if (aLangID != nsIProgrammingLanguage::JAVASCRIPT) {
     302               0 :     NS_WARNING("XBL still JS only");
     303               0 :     return NS_ERROR_INVALID_ARG;
     304                 :   }
     305               0 :   if (mScriptContext)
     306               0 :     return NS_OK; // already initialized for this lang
     307               0 :   nsCOMPtr<nsIDOMScriptObjectFactory> factory = do_GetService(kDOMScriptObjectFactoryCID);
     308               0 :   NS_ENSURE_TRUE(factory, NS_OK);
     309                 : 
     310                 :   nsresult rv;
     311                 : 
     312               0 :   nsCOMPtr<nsIScriptRuntime> scriptRuntime;
     313               0 :   rv = NS_GetScriptRuntimeByID(aLangID, getter_AddRefs(scriptRuntime));
     314               0 :   NS_ENSURE_SUCCESS(rv, rv);
     315               0 :   nsCOMPtr<nsIScriptContext> newCtx = scriptRuntime->CreateContext();
     316               0 :   rv = SetScriptContext(aLangID, newCtx);
     317                 : 
     318               0 :   JSContext *cx = mScriptContext->GetNativeContext();
     319               0 :   JSAutoRequest ar(cx);
     320                 : 
     321                 :   // nsJSEnvironment set the error reporter to NS_ScriptErrorReporter so
     322                 :   // we must apparently override that with our own (although it isn't clear 
     323                 :   // why - see bug 339647)
     324               0 :   JS_SetErrorReporter(cx, XBL_ProtoErrorReporter);
     325                 : 
     326               0 :   nsIPrincipal *principal = GetPrincipal();
     327                 :   JSCompartment *compartment;
     328                 : 
     329                 :   rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, principal, nsnull,
     330               0 :                               false, &mJSObject, &compartment);
     331               0 :   NS_ENSURE_SUCCESS(rv, NS_OK);
     332                 : 
     333               0 :   ::JS_SetGlobalObject(cx, mJSObject);
     334                 : 
     335                 :   // Add an owning reference from JS back to us. This'll be
     336                 :   // released when the JSObject is finalized.
     337               0 :   ::JS_SetPrivate(mJSObject, this);
     338               0 :   NS_ADDREF(this);
     339               0 :   return NS_OK;
     340                 : }
     341                 : 
     342                 : nsIScriptContext *
     343               0 : nsXBLDocGlobalObject::GetContext()
     344                 : {
     345                 :   // This whole fragile mess is predicated on the fact that
     346                 :   // GetContext() will be called before GetScriptObject() is.
     347               0 :   if (! mScriptContext) {
     348               0 :     nsresult rv = EnsureScriptEnvironment(nsIProgrammingLanguage::JAVASCRIPT);
     349                 :     // JS is builtin so we make noise if it fails to initialize.
     350               0 :     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to setup JS!?");
     351               0 :     NS_ENSURE_SUCCESS(rv, nsnull);
     352               0 :     NS_ASSERTION(mScriptContext, "Failed to find a script context!?");
     353                 :   }
     354               0 :   return mScriptContext;
     355                 : }
     356                 : 
     357                 : void
     358               0 : nsXBLDocGlobalObject::ClearGlobalObjectOwner()
     359                 : {
     360               0 :   mGlobalObjectOwner = nsnull;
     361               0 : }
     362                 : 
     363                 : JSObject *
     364               0 : nsXBLDocGlobalObject::GetGlobalJSObject()
     365                 : {
     366                 :   // The prototype document has its own special secret script object
     367                 :   // that can be used to compile scripts and event handlers.
     368                 : 
     369               0 :   if (!mScriptContext)
     370               0 :     return nsnull;
     371                 : 
     372               0 :   JSContext* cx = mScriptContext->GetNativeContext();
     373               0 :   if (!cx)
     374               0 :     return nsnull;
     375                 : 
     376               0 :   JSObject *ret = ::JS_GetGlobalObject(cx);
     377               0 :   NS_ASSERTION(mJSObject == ret, "How did this magic switch happen?");
     378               0 :   return ret;
     379                 : }
     380                 : 
     381                 : void
     382               0 : nsXBLDocGlobalObject::OnFinalize(JSObject* aObject)
     383                 : {
     384               0 :   NS_ASSERTION(aObject == mJSObject, "Wrong object finalized!");
     385               0 :   mJSObject = NULL;
     386               0 : }
     387                 : 
     388                 : void
     389               0 : nsXBLDocGlobalObject::SetScriptsEnabled(bool aEnabled, bool aFireTimeouts)
     390                 : {
     391                 :     // We don't care...
     392               0 : }
     393                 : 
     394                 : //----------------------------------------------------------------------
     395                 : //
     396                 : // nsIScriptObjectPrincipal methods
     397                 : //
     398                 : 
     399                 : nsIPrincipal*
     400               0 : nsXBLDocGlobalObject::GetPrincipal()
     401                 : {
     402               0 :   if (!mGlobalObjectOwner) {
     403                 :     // XXXbz this should really save the principal when
     404                 :     // ClearGlobalObjectOwner() happens.
     405               0 :     return nsnull;
     406                 :   }
     407                 : 
     408                 :   nsRefPtr<nsXBLDocumentInfo> docInfo =
     409               0 :     static_cast<nsXBLDocumentInfo*>(mGlobalObjectOwner);
     410                 : 
     411               0 :   nsCOMPtr<nsIDocument> document = docInfo->GetDocument();
     412               0 :   if (!document)
     413               0 :     return NULL;
     414                 : 
     415               0 :   return document->NodePrincipal();
     416                 : }
     417                 : 
     418               0 : static bool IsChromeURI(nsIURI* aURI)
     419                 : {
     420               0 :   bool isChrome = false;
     421               0 :   if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)))
     422               0 :       return isChrome;
     423               0 :   return false;
     424                 : }
     425                 : 
     426                 : /* Implementation file */
     427                 : 
     428                 : static bool
     429               0 : TraverseProtos(nsHashKey *aKey, void *aData, void* aClosure)
     430                 : {
     431                 :   nsCycleCollectionTraversalCallback *cb = 
     432               0 :     static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
     433               0 :   nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
     434               0 :   proto->Traverse(*cb);
     435               0 :   return kHashEnumerateNext;
     436                 : }
     437                 : 
     438                 : static bool
     439               0 : UnlinkProtoJSObjects(nsHashKey *aKey, void *aData, void* aClosure)
     440                 : {
     441               0 :   nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
     442               0 :   proto->UnlinkJSObjects();
     443               0 :   return kHashEnumerateNext;
     444                 : }
     445                 : 
     446                 : struct ProtoTracer
     447                 : {
     448                 :   TraceCallback mCallback;
     449                 :   void *mClosure;
     450                 : };
     451                 : 
     452                 : static bool
     453               0 : TraceProtos(nsHashKey *aKey, void *aData, void* aClosure)
     454                 : {
     455               0 :   ProtoTracer* closure = static_cast<ProtoTracer*>(aClosure);
     456               0 :   nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
     457               0 :   proto->Trace(closure->mCallback, closure->mClosure);
     458               0 :   return kHashEnumerateNext;
     459                 : }
     460                 : 
     461            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
     462               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
     463               0 :   if (tmp->mBindingTable) {
     464               0 :     tmp->mBindingTable->Enumerate(UnlinkProtoJSObjects, nsnull);
     465                 :   }
     466               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument)
     467               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobalObject)
     468               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     469               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
     470               0 :   if (tmp->mDocument &&
     471               0 :       nsCCUncollectableMarker::InGeneration(cb, tmp->mDocument->GetMarkedCCGeneration())) {
     472               0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
     473               0 :     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
     474                 :   }
     475               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument)
     476               0 :   if (tmp->mBindingTable) {
     477               0 :     tmp->mBindingTable->Enumerate(TraverseProtos, &cb);
     478                 :   }
     479               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mGlobalObject");
     480               0 :   cb.NoteXPCOMChild(static_cast<nsIScriptGlobalObject*>(tmp->mGlobalObject));
     481               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
     482               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     483               0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo)
     484               0 :   if (tmp->mBindingTable) {
     485               0 :     ProtoTracer closure = { aCallback, aClosure };
     486               0 :     tmp->mBindingTable->Enumerate(TraceProtos, &closure);
     487                 :   }
     488               0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
     489                 : 
     490                 : static void
     491               0 : UnmarkXBLJSObject(PRUint32 aLangID, void* aP, const char* aName, void* aClosure)
     492                 : {
     493               0 :   if (aLangID == nsIProgrammingLanguage::JAVASCRIPT) {
     494               0 :     xpc_UnmarkGrayObject(static_cast<JSObject*>(aP));
     495                 :   }
     496               0 : }
     497                 : 
     498                 : static bool
     499               0 : UnmarkProtos(nsHashKey* aKey, void* aData, void* aClosure)
     500                 : {
     501               0 :   nsXBLPrototypeBinding* proto = static_cast<nsXBLPrototypeBinding*>(aData);
     502               0 :   proto->Trace(UnmarkXBLJSObject, nsnull);
     503               0 :   return kHashEnumerateNext;
     504                 : }
     505                 : 
     506                 : void
     507               0 : nsXBLDocumentInfo::MarkInCCGeneration(PRUint32 aGeneration)
     508                 : {
     509               0 :   if (mDocument) {
     510               0 :     mDocument->MarkUncollectableForCCGeneration(aGeneration);
     511                 :   }
     512               0 :   if (mBindingTable) {
     513               0 :     mBindingTable->Enumerate(UnmarkProtos, nsnull);
     514                 :   }
     515               0 : }
     516                 : 
     517               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo)
     518               0 :   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObjectOwner)
     519               0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
     520               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObjectOwner)
     521               0 : NS_INTERFACE_MAP_END
     522                 : 
     523               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocumentInfo)
     524               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLDocumentInfo)
     525                 : 
     526               0 : nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument)
     527                 :   : mDocument(aDocument),
     528                 :     mScriptAccess(true),
     529                 :     mIsChrome(false),
     530                 :     mBindingTable(nsnull),
     531               0 :     mFirstBinding(nsnull)
     532                 : {
     533               0 :   nsIURI* uri = aDocument->GetDocumentURI();
     534               0 :   if (IsChromeURI(uri)) {
     535                 :     // Cache whether or not this chrome XBL can execute scripts.
     536                 :     nsCOMPtr<nsIXULChromeRegistry> reg =
     537               0 :       mozilla::services::GetXULChromeRegistryService();
     538               0 :     if (reg) {
     539               0 :       bool allow = true;
     540               0 :       reg->AllowScriptsForPackage(uri, &allow);
     541               0 :       mScriptAccess = allow;
     542                 :     }
     543               0 :     mIsChrome = true;
     544                 :   }
     545               0 : }
     546                 : 
     547               0 : nsXBLDocumentInfo::~nsXBLDocumentInfo()
     548                 : {
     549                 :   /* destructor code */
     550               0 :   if (mGlobalObject) {
     551                 :     // remove circular reference
     552               0 :     mGlobalObject->SetScriptContext(nsIProgrammingLanguage::JAVASCRIPT, nsnull);
     553               0 :     mGlobalObject->ClearGlobalObjectOwner(); // just in case
     554                 :   }
     555               0 :   if (mBindingTable) {
     556               0 :     NS_DROP_JS_OBJECTS(this, nsXBLDocumentInfo);
     557               0 :     delete mBindingTable;
     558                 :   }
     559               0 : }
     560                 : 
     561                 : nsXBLPrototypeBinding*
     562               0 : nsXBLDocumentInfo::GetPrototypeBinding(const nsACString& aRef)
     563                 : {
     564               0 :   if (!mBindingTable)
     565               0 :     return NULL;
     566                 : 
     567               0 :   if (aRef.IsEmpty()) {
     568                 :     // Return our first binding
     569               0 :     return mFirstBinding;
     570                 :   }
     571                 : 
     572               0 :   const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
     573               0 :   nsCStringKey key(flat.get());
     574               0 :   return static_cast<nsXBLPrototypeBinding*>(mBindingTable->Get(&key));
     575                 : }
     576                 : 
     577                 : static bool
     578               0 : DeletePrototypeBinding(nsHashKey* aKey, void* aData, void* aClosure)
     579                 : {
     580               0 :   nsXBLPrototypeBinding* binding = static_cast<nsXBLPrototypeBinding*>(aData);
     581               0 :   delete binding;
     582               0 :   return true;
     583                 : }
     584                 : 
     585                 : nsresult
     586               0 : nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding)
     587                 : {
     588               0 :   if (!mBindingTable) {
     589               0 :     mBindingTable = new nsObjectHashtable(nsnull, nsnull, DeletePrototypeBinding, nsnull);
     590                 : 
     591               0 :     NS_HOLD_JS_OBJECTS(this, nsXBLDocumentInfo);
     592                 :   }
     593                 : 
     594               0 :   const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
     595               0 :   nsCStringKey key(flat.get());
     596               0 :   NS_ENSURE_STATE(!mBindingTable->Get(&key));
     597               0 :   mBindingTable->Put(&key, aBinding);
     598                 : 
     599               0 :   return NS_OK;
     600                 : }
     601                 : 
     602                 : void
     603               0 : nsXBLDocumentInfo::RemovePrototypeBinding(const nsACString& aRef)
     604                 : {
     605               0 :   if (mBindingTable) {
     606                 :     // Use a flat string to avoid making a copy.
     607               0 :     const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
     608               0 :     nsCStringKey key(flat);
     609               0 :     mBindingTable->Remove(&key);
     610                 :   }
     611               0 : }
     612                 : 
     613                 : // Callback to enumerate over the bindings from this document and write them
     614                 : // out to the cache.
     615                 : bool
     616               0 : WriteBinding(nsHashKey *aKey, void *aData, void* aClosure)
     617                 : {
     618               0 :   nsXBLPrototypeBinding* binding = static_cast<nsXBLPrototypeBinding *>(aData);
     619               0 :   binding->Write((nsIObjectOutputStream*)aClosure);
     620                 : 
     621               0 :   return kHashEnumerateNext;
     622                 : }
     623                 : 
     624                 : // static
     625                 : nsresult
     626               0 : nsXBLDocumentInfo::ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo)
     627                 : {
     628               0 :   *aDocInfo = nsnull;
     629                 : 
     630               0 :   nsCAutoString spec(kXBLCachePrefix);
     631               0 :   nsresult rv = PathifyURI(aURI, spec);
     632               0 :   NS_ENSURE_SUCCESS(rv, rv);
     633                 : 
     634               0 :   StartupCache* startupCache = StartupCache::GetSingleton();
     635               0 :   NS_ENSURE_TRUE(startupCache, NS_ERROR_FAILURE);
     636                 : 
     637               0 :   nsAutoArrayPtr<char> buf;
     638                 :   PRUint32 len;
     639               0 :   rv = startupCache->GetBuffer(spec.get(), getter_Transfers(buf), &len);
     640                 :   // GetBuffer will fail if the binding is not in the cache.
     641               0 :   if (NS_FAILED(rv))
     642               0 :     return rv;
     643                 : 
     644               0 :   nsCOMPtr<nsIObjectInputStream> stream;
     645               0 :   rv = NewObjectInputStreamFromBuffer(buf, len, getter_AddRefs(stream));
     646               0 :   NS_ENSURE_SUCCESS(rv, rv);
     647               0 :   buf.forget();
     648                 : 
     649                 :   // The file compatibility.ini stores the build id. This is checked in
     650                 :   // nsAppRunner.cpp and will delete the cache if a different build is
     651                 :   // present. However, we check that the version matches here to be safe. 
     652                 :   PRUint32 version;
     653               0 :   rv = stream->Read32(&version);
     654               0 :   NS_ENSURE_SUCCESS(rv, rv);
     655               0 :   if (version != XBLBinding_Serialize_Version) {
     656                 :     // The version that exists is different than expected, likely created with a
     657                 :     // different build, so invalidate the cache.
     658               0 :     startupCache->InvalidateCache();
     659               0 :     return NS_ERROR_NOT_AVAILABLE;
     660                 :   }
     661                 : 
     662               0 :   nsCOMPtr<nsIPrincipal> principal;
     663               0 :   nsContentUtils::GetSecurityManager()->
     664               0 :     GetSystemPrincipal(getter_AddRefs(principal));
     665                 : 
     666               0 :   nsCOMPtr<nsIDOMDocument> domdoc;
     667               0 :   rv = NS_NewXBLDocument(getter_AddRefs(domdoc), aURI, nsnull, principal);
     668               0 :   NS_ENSURE_SUCCESS(rv, rv);
     669                 : 
     670               0 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
     671               0 :   nsRefPtr<nsXBLDocumentInfo> docInfo = NS_NewXBLDocumentInfo(doc);
     672                 : 
     673               0 :   while (1) {
     674                 :     PRUint8 flags;
     675               0 :     nsresult rv = stream->Read8(&flags);
     676               0 :     NS_ENSURE_SUCCESS(rv, rv);
     677               0 :     if (flags == XBLBinding_Serialize_NoMoreBindings)
     678                 :       break;
     679                 : 
     680               0 :     nsXBLPrototypeBinding* binding = new nsXBLPrototypeBinding();
     681               0 :     rv = binding->Read(stream, docInfo, doc, flags);
     682               0 :     if (NS_FAILED(rv)) {
     683               0 :       delete binding;
     684               0 :       return rv;
     685                 :     }
     686                 :   }
     687                 : 
     688               0 :   docInfo.swap(*aDocInfo);
     689               0 :   return NS_OK;
     690                 : }
     691                 : 
     692                 : nsresult
     693               0 : nsXBLDocumentInfo::WritePrototypeBindings()
     694                 : {
     695                 :   // Only write out bindings with the system principal
     696               0 :   if (!nsContentUtils::IsSystemPrincipal(mDocument->NodePrincipal()))
     697               0 :     return NS_OK;
     698                 : 
     699               0 :   nsCAutoString spec(kXBLCachePrefix);
     700               0 :   nsresult rv = PathifyURI(DocumentURI(), spec);
     701               0 :   NS_ENSURE_SUCCESS(rv, rv);
     702                 : 
     703               0 :   StartupCache* startupCache = StartupCache::GetSingleton();
     704               0 :   NS_ENSURE_TRUE(startupCache, rv);
     705                 : 
     706               0 :   nsCOMPtr<nsIObjectOutputStream> stream;
     707               0 :   nsCOMPtr<nsIStorageStream> storageStream;
     708               0 :   rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(stream),
     709               0 :                                            getter_AddRefs(storageStream),
     710               0 :                                            true);
     711               0 :   NS_ENSURE_SUCCESS(rv, rv);
     712                 : 
     713               0 :   rv = stream->Write32(XBLBinding_Serialize_Version);
     714               0 :   NS_ENSURE_SUCCESS(rv, rv);
     715                 : 
     716               0 :   if (mBindingTable)
     717               0 :     mBindingTable->Enumerate(WriteBinding, stream);
     718                 : 
     719                 :   // write a end marker at the end
     720               0 :   rv = stream->Write8(XBLBinding_Serialize_NoMoreBindings);
     721               0 :   NS_ENSURE_SUCCESS(rv, rv);
     722                 : 
     723               0 :   stream->Close();
     724               0 :   NS_ENSURE_SUCCESS(rv, rv);
     725                 : 
     726                 :   PRUint32 len;
     727               0 :   nsAutoArrayPtr<char> buf;
     728               0 :   rv = NewBufferFromStorageStream(storageStream, getter_Transfers(buf), &len);
     729               0 :   NS_ENSURE_SUCCESS(rv, rv);
     730                 : 
     731               0 :   return startupCache->PutBuffer(spec.get(), buf, len);
     732                 : }
     733                 : 
     734                 : void
     735               0 : nsXBLDocumentInfo::SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding)
     736                 : {
     737               0 :   mFirstBinding = aBinding;
     738               0 : }
     739                 : 
     740               0 : bool FlushScopedSkinSheets(nsHashKey* aKey, void* aData, void* aClosure)
     741                 : {
     742               0 :   nsXBLPrototypeBinding* proto = (nsXBLPrototypeBinding*)aData;
     743               0 :   proto->FlushSkinSheets();
     744               0 :   return true;
     745                 : }
     746                 : 
     747                 : void
     748               0 : nsXBLDocumentInfo::FlushSkinStylesheets()
     749                 : {
     750               0 :   if (mBindingTable)
     751               0 :     mBindingTable->Enumerate(FlushScopedSkinSheets);
     752               0 : }
     753                 : 
     754                 : //----------------------------------------------------------------------
     755                 : //
     756                 : // nsIScriptGlobalObjectOwner methods
     757                 : //
     758                 : 
     759                 : nsIScriptGlobalObject*
     760               0 : nsXBLDocumentInfo::GetScriptGlobalObject()
     761                 : {
     762               0 :   if (!mGlobalObject) {
     763               0 :     nsXBLDocGlobalObject *global = new nsXBLDocGlobalObject(this);
     764               0 :     if (!global)
     765               0 :       return nsnull;
     766                 : 
     767               0 :     mGlobalObject = global;
     768                 :   }
     769                 : 
     770               0 :   return mGlobalObject;
     771                 : }
     772                 : 
     773               0 : nsXBLDocumentInfo* NS_NewXBLDocumentInfo(nsIDocument* aDocument)
     774                 : {
     775               0 :   NS_PRECONDITION(aDocument, "Must have a document!");
     776                 : 
     777                 :   nsXBLDocumentInfo* result;
     778                 : 
     779               0 :   result = new nsXBLDocumentInfo(aDocument);
     780               0 :   NS_ADDREF(result);
     781               0 :   return result;
     782            4392 : }

Generated by: LCOV version 1.7