LCOV - app.info - content/xbl/src/nsXBLDocumentInfo.cpp

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-07-07 | 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