LCOV - code coverage report
Current view: directory - content/xbl/src - nsXBLBinding.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 677 2 0.3 %
Date: 2012-06-02 Functions: 49 2 4.1 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Brendan Eich (brendan@mozilla.org)
      24                 :  *   Scott MacGregor (mscott@netscape.com)
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "nsCOMPtr.h"
      41                 : #include "nsIAtom.h"
      42                 : #include "nsXBLDocumentInfo.h"
      43                 : #include "nsIInputStream.h"
      44                 : #include "nsINameSpaceManager.h"
      45                 : #include "nsHashtable.h"
      46                 : #include "nsIURI.h"
      47                 : #include "nsIURL.h"
      48                 : #include "nsIDOMEventTarget.h"
      49                 : #include "nsIChannel.h"
      50                 : #include "nsXPIDLString.h"
      51                 : #include "nsReadableUtils.h"
      52                 : #include "nsIParser.h"
      53                 : #include "nsParserCIID.h"
      54                 : #include "nsNetUtil.h"
      55                 : #include "plstr.h"
      56                 : #include "nsIContent.h"
      57                 : #include "nsIDocument.h"
      58                 : #include "nsContentUtils.h"
      59                 : #ifdef MOZ_XUL
      60                 : #include "nsIXULDocument.h"
      61                 : #endif
      62                 : #include "nsIXMLContentSink.h"
      63                 : #include "nsContentCID.h"
      64                 : #include "nsXMLDocument.h"
      65                 : #include "jsapi.h"
      66                 : #include "nsXBLService.h"
      67                 : #include "nsXBLInsertionPoint.h"
      68                 : #include "nsIXPConnect.h"
      69                 : #include "nsIScriptContext.h"
      70                 : #include "nsCRT.h"
      71                 : 
      72                 : // Event listeners
      73                 : #include "nsEventListenerManager.h"
      74                 : #include "nsIDOMEventListener.h"
      75                 : #include "nsAttrName.h"
      76                 : 
      77                 : #include "nsGkAtoms.h"
      78                 : 
      79                 : #include "nsIDOMAttr.h"
      80                 : #include "nsIDOMNamedNodeMap.h"
      81                 : 
      82                 : #include "nsXBLPrototypeHandler.h"
      83                 : 
      84                 : #include "nsXBLPrototypeBinding.h"
      85                 : #include "nsXBLBinding.h"
      86                 : #include "nsIPrincipal.h"
      87                 : #include "nsIScriptSecurityManager.h"
      88                 : #include "nsEventListenerManager.h"
      89                 : #include "nsGUIEvent.h"
      90                 : 
      91                 : #include "prprf.h"
      92                 : #include "nsNodeUtils.h"
      93                 : 
      94                 : // Nasty hack.  Maybe we could move some of the classinfo utility methods
      95                 : // (e.g. WrapNative and ThrowJSException) over to nsContentUtils?
      96                 : #include "nsDOMClassInfo.h"
      97                 : #include "nsJSUtils.h"
      98                 : 
      99                 : #include "mozilla/dom/Element.h"
     100                 : 
     101                 : // Helper classes
     102                 : 
     103                 : /***********************************************************************/
     104                 : //
     105                 : // The JS class for XBLBinding
     106                 : //
     107                 : static void
     108               0 : XBLFinalize(JSContext *cx, JSObject *obj)
     109                 : {
     110                 :   nsXBLDocumentInfo* docInfo =
     111               0 :     static_cast<nsXBLDocumentInfo*>(::JS_GetPrivate(obj));
     112               0 :   NS_RELEASE(docInfo);
     113                 :   
     114               0 :   nsXBLJSClass* c = static_cast<nsXBLJSClass*>(::JS_GetClass(obj));
     115               0 :   c->Drop();
     116               0 : }
     117                 : 
     118                 : static JSBool
     119               0 : XBLResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
     120                 :            JSObject **objp)
     121                 : {
     122                 :   // Note: if we get here, that means that the implementation for some binding
     123                 :   // was installed, which means that AllowScripts() tested true.  Hence no need
     124                 :   // to do checks like that here.
     125                 :   
     126                 :   // Default to not resolving things.
     127               0 :   NS_ASSERTION(*objp, "Must have starting object");
     128                 : 
     129               0 :   JSObject* origObj = *objp;
     130               0 :   *objp = NULL;
     131                 : 
     132               0 :   if (!JSID_IS_STRING(id)) {
     133               0 :     return JS_TRUE;
     134                 :   }
     135                 : 
     136               0 :   nsDependentJSString fieldName(id);
     137                 : 
     138               0 :   jsval slotVal = ::JS_GetReservedSlot(obj, 0);
     139               0 :   NS_ASSERTION(!JSVAL_IS_VOID(slotVal), "How did that happen?");
     140                 :     
     141                 :   nsXBLPrototypeBinding* protoBinding =
     142               0 :     static_cast<nsXBLPrototypeBinding*>(JSVAL_TO_PRIVATE(slotVal));
     143               0 :   NS_ASSERTION(protoBinding, "Must have prototype binding!");
     144                 : 
     145               0 :   nsXBLProtoImplField* field = protoBinding->FindField(fieldName);
     146               0 :   if (!field) {
     147               0 :     return JS_TRUE;
     148                 :   }
     149                 : 
     150                 :   // We have this field.  Time to install it.  Get our node.
     151               0 :   JSClass* nodeClass = ::JS_GetClass(origObj);
     152               0 :   if (!nodeClass) {
     153               0 :     return JS_FALSE;
     154                 :   }
     155                 :   
     156               0 :   if (~nodeClass->flags &
     157                 :       (JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS)) {
     158               0 :     nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
     159               0 :     return JS_FALSE;
     160                 :   }
     161                 : 
     162                 :   nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
     163               0 :     do_QueryInterface(static_cast<nsISupports*>(::JS_GetPrivate(origObj)));
     164               0 :   if (!xpcWrapper) {
     165                 :     // Looks like whatever |origObj| is it's not our nsIContent.  It might well
     166                 :     // be the proto our binding installed, however, where the private is the
     167                 :     // nsXBLDocumentInfo, so just baul out quietly.  Do NOT throw an exception
     168                 :     // here.
     169                 :     // We could make this stricter by checking the class maybe, but whatever
     170               0 :     return JS_TRUE;
     171                 :   }
     172                 : 
     173               0 :   nsCOMPtr<nsIContent> content = do_QueryWrappedNative(xpcWrapper);
     174               0 :   if (!content) {
     175               0 :     nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
     176               0 :     return JS_FALSE;
     177                 :   }
     178                 : 
     179                 :   // This mirrors code in nsXBLProtoImpl::InstallImplementation
     180               0 :   nsIDocument* doc = content->OwnerDoc();
     181                 : 
     182               0 :   nsIScriptGlobalObject* global = doc->GetScriptGlobalObject();
     183               0 :   if (!global) {
     184               0 :     return JS_TRUE;
     185                 :   }
     186                 : 
     187               0 :   nsCOMPtr<nsIScriptContext> context = global->GetContext();
     188               0 :   if (!context) {
     189               0 :     return JS_TRUE;
     190                 :   }
     191                 : 
     192                 : 
     193                 :   // Now we either resolve or fail
     194                 :   bool didInstall;
     195                 :   nsresult rv = field->InstallField(context, origObj,
     196               0 :                                     content->NodePrincipal(),
     197                 :                                     protoBinding->DocURI(),
     198               0 :                                     &didInstall);
     199               0 :   if (NS_FAILED(rv)) {
     200               0 :     if (!::JS_IsExceptionPending(cx)) {
     201               0 :       nsDOMClassInfo::ThrowJSException(cx, rv);
     202                 :     }
     203                 : 
     204               0 :     return JS_FALSE;
     205                 :   }
     206                 : 
     207               0 :   if (didInstall) {
     208               0 :     *objp = origObj;
     209                 :   }
     210                 :   // else we didn't resolve this field after all
     211                 : 
     212               0 :   return JS_TRUE;
     213                 : }
     214                 : 
     215               0 : nsXBLJSClass::nsXBLJSClass(const nsAFlatCString& aClassName)
     216                 : {
     217               0 :   memset(this, 0, sizeof(nsXBLJSClass));
     218               0 :   next = prev = static_cast<JSCList*>(this);
     219               0 :   name = ToNewCString(aClassName);
     220                 :   flags =
     221                 :     JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
     222                 :     JSCLASS_NEW_RESOLVE | JSCLASS_NEW_RESOLVE_GETS_START |
     223                 :     // Our one reserved slot holds the relevant nsXBLPrototypeBinding
     224               0 :     JSCLASS_HAS_RESERVED_SLOTS(1);
     225               0 :   addProperty = delProperty = getProperty = ::JS_PropertyStub;
     226               0 :   setProperty = ::JS_StrictPropertyStub;
     227               0 :   enumerate = ::JS_EnumerateStub;
     228               0 :   resolve = (JSResolveOp)XBLResolve;
     229               0 :   convert = ::JS_ConvertStub;
     230               0 :   finalize = XBLFinalize;
     231               0 : }
     232                 : 
     233                 : nsrefcnt
     234               0 : nsXBLJSClass::Destroy()
     235                 : {
     236               0 :   NS_ASSERTION(next == prev && prev == static_cast<JSCList*>(this),
     237                 :                "referenced nsXBLJSClass is on LRU list already!?");
     238                 : 
     239               0 :   if (nsXBLService::gClassTable) {
     240               0 :     nsCStringKey key(name);
     241               0 :     (nsXBLService::gClassTable)->Remove(&key);
     242                 :   }
     243                 : 
     244               0 :   if (nsXBLService::gClassLRUListLength >= nsXBLService::gClassLRUListQuota) {
     245                 :     // Over LRU list quota, just unhash and delete this class.
     246               0 :     delete this;
     247                 :   } else {
     248                 :     // Put this most-recently-used class on end of the LRU-sorted freelist.
     249               0 :     JSCList* mru = static_cast<JSCList*>(this);
     250               0 :     JS_APPEND_LINK(mru, &nsXBLService::gClassLRUList);
     251               0 :     nsXBLService::gClassLRUListLength++;
     252                 :   }
     253                 : 
     254               0 :   return 0;
     255                 : }
     256                 : 
     257                 : // Implementation /////////////////////////////////////////////////////////////////
     258                 : 
     259                 : // Constructors/Destructors
     260               0 : nsXBLBinding::nsXBLBinding(nsXBLPrototypeBinding* aBinding)
     261                 :   : mPrototypeBinding(aBinding),
     262                 :     mInsertionPointTable(nsnull),
     263                 :     mIsStyleBinding(true),
     264               0 :     mMarkedForDeath(false)
     265                 : {
     266               0 :   NS_ASSERTION(mPrototypeBinding, "Must have a prototype binding!");
     267                 :   // Grab a ref to the document info so the prototype binding won't die
     268               0 :   NS_ADDREF(mPrototypeBinding->XBLDocumentInfo());
     269               0 : }
     270                 : 
     271                 : 
     272               0 : nsXBLBinding::~nsXBLBinding(void)
     273                 : {
     274               0 :   if (mContent) {
     275               0 :     nsXBLBinding::UninstallAnonymousContent(mContent->OwnerDoc(), mContent);
     276                 :   }
     277               0 :   delete mInsertionPointTable;
     278               0 :   nsXBLDocumentInfo* info = mPrototypeBinding->XBLDocumentInfo();
     279               0 :   NS_RELEASE(info);
     280               0 : }
     281                 : 
     282                 : static PLDHashOperator
     283               0 : TraverseKey(nsISupports* aKey, nsInsertionPointList* aData, void* aClosure)
     284                 : {
     285                 :   nsCycleCollectionTraversalCallback &cb = 
     286               0 :     *static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
     287                 : 
     288               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mInsertionPointTable key");
     289               0 :   cb.NoteXPCOMChild(aKey);
     290               0 :   if (aData) {
     291               0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(*aData, nsXBLInsertionPoint,
     292                 :                                                "mInsertionPointTable value")
     293                 :   }
     294               0 :   return PL_DHASH_NEXT;
     295                 : }
     296                 : 
     297            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLBinding)
     298               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLBinding)
     299                 :   // XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because
     300                 :   //     mPrototypeBinding is weak.
     301               0 :   if (tmp->mContent) {
     302               0 :     nsXBLBinding::UninstallAnonymousContent(tmp->mContent->OwnerDoc(),
     303               0 :                                             tmp->mContent);
     304                 :   }
     305               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContent)
     306               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNextBinding)
     307               0 :   delete tmp->mInsertionPointTable;
     308               0 :   tmp->mInsertionPointTable = nsnull;
     309               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     310               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsXBLBinding)
     311               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
     312                 :                                      "mPrototypeBinding->XBLDocumentInfo()");
     313                 :   cb.NoteXPCOMChild(static_cast<nsIScriptGlobalObjectOwner*>(
     314               0 :                       tmp->mPrototypeBinding->XBLDocumentInfo()));
     315               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContent)
     316               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mNextBinding, nsXBLBinding)
     317               0 :   if (tmp->mInsertionPointTable)
     318               0 :     tmp->mInsertionPointTable->EnumerateRead(TraverseKey, &cb);
     319               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     320               0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsXBLBinding, AddRef)
     321               0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsXBLBinding, Release)
     322                 : 
     323                 : void
     324               0 : nsXBLBinding::SetBaseBinding(nsXBLBinding* aBinding)
     325                 : {
     326               0 :   if (mNextBinding) {
     327               0 :     NS_ERROR("Base XBL binding is already defined!");
     328               0 :     return;
     329                 :   }
     330                 : 
     331               0 :   mNextBinding = aBinding; // Comptr handles rel/add
     332                 : }
     333                 : 
     334                 : void
     335               0 : nsXBLBinding::InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElement)
     336                 : {
     337                 :   // We need to ensure two things.
     338                 :   // (1) The anonymous content should be fooled into thinking it's in the bound
     339                 :   // element's document, assuming that the bound element is in a document
     340                 :   // Note that we don't change the current doc of aAnonParent here, since that
     341                 :   // quite simply does not matter.  aAnonParent is just a way of keeping refs
     342                 :   // to all its kids, which are anonymous content from the point of view of
     343                 :   // aElement.
     344                 :   // (2) The children's parent back pointer should not be to this synthetic root
     345                 :   // but should instead point to the enclosing parent element.
     346               0 :   nsIDocument* doc = aElement->GetCurrentDoc();
     347               0 :   bool allowScripts = AllowScripts();
     348                 : 
     349               0 :   nsAutoScriptBlocker scriptBlocker;
     350               0 :   for (nsIContent* child = aAnonParent->GetFirstChild();
     351                 :        child;
     352               0 :        child = child->GetNextSibling()) {
     353               0 :     child->UnbindFromTree();
     354                 :     nsresult rv =
     355               0 :       child->BindToTree(doc, aElement, mBoundElement, allowScripts);
     356               0 :     if (NS_FAILED(rv)) {
     357                 :       // Oh, well... Just give up.
     358                 :       // XXXbz This really shouldn't be a void method!
     359               0 :       child->UnbindFromTree();
     360                 :       return;
     361                 :     }        
     362                 : 
     363               0 :     child->SetFlags(NODE_IS_ANONYMOUS);
     364                 : 
     365                 : #ifdef MOZ_XUL
     366                 :     // To make XUL templates work (and other goodies that happen when
     367                 :     // an element is added to a XUL document), we need to notify the
     368                 :     // XUL document using its special API.
     369               0 :     nsCOMPtr<nsIXULDocument> xuldoc(do_QueryInterface(doc));
     370               0 :     if (xuldoc)
     371               0 :       xuldoc->AddSubtreeToDocument(child);
     372                 : #endif
     373                 :   }
     374                 : }
     375                 : 
     376                 : void
     377               0 : nsXBLBinding::UninstallAnonymousContent(nsIDocument* aDocument,
     378                 :                                         nsIContent* aAnonParent)
     379                 : {
     380               0 :   nsAutoScriptBlocker scriptBlocker;
     381                 :   // Hold a strong ref while doing this, just in case.
     382               0 :   nsCOMPtr<nsIContent> anonParent = aAnonParent;
     383                 : #ifdef MOZ_XUL
     384                 :   nsCOMPtr<nsIXULDocument> xuldoc =
     385               0 :     do_QueryInterface(aDocument);
     386                 : #endif
     387               0 :   for (nsIContent* child = aAnonParent->GetFirstChild();
     388                 :        child;
     389               0 :        child = child->GetNextSibling()) {
     390               0 :     child->UnbindFromTree();
     391                 : #ifdef MOZ_XUL
     392               0 :     if (xuldoc) {
     393               0 :       xuldoc->RemoveSubtreeFromDocument(child);
     394                 :     }
     395                 : #endif
     396                 :   }
     397               0 : }
     398                 : 
     399                 : void
     400               0 : nsXBLBinding::SetBoundElement(nsIContent* aElement)
     401                 : {
     402               0 :   mBoundElement = aElement;
     403               0 :   if (mNextBinding)
     404               0 :     mNextBinding->SetBoundElement(aElement);
     405               0 : }
     406                 : 
     407                 : bool
     408               0 : nsXBLBinding::HasStyleSheets() const
     409                 : {
     410                 :   // Find out if we need to re-resolve style.  We'll need to do this
     411                 :   // if we have additional stylesheets in our binding document.
     412               0 :   if (mPrototypeBinding->HasStyleSheets())
     413               0 :     return true;
     414                 : 
     415               0 :   return mNextBinding ? mNextBinding->HasStyleSheets() : false;
     416                 : }
     417                 : 
     418                 : struct EnumData {
     419                 :   nsXBLBinding* mBinding;
     420                 :  
     421               0 :   EnumData(nsXBLBinding* aBinding)
     422               0 :     :mBinding(aBinding)
     423               0 :   {}
     424                 : };
     425                 : 
     426                 : struct ContentListData : public EnumData {
     427                 :   nsBindingManager* mBindingManager;
     428                 :   nsresult          mRv;
     429                 : 
     430               0 :   ContentListData(nsXBLBinding* aBinding, nsBindingManager* aManager)
     431               0 :     :EnumData(aBinding), mBindingManager(aManager), mRv(NS_OK)
     432               0 :   {}
     433                 : };
     434                 : 
     435                 : static PLDHashOperator
     436               0 : BuildContentLists(nsISupports* aKey,
     437                 :                   nsAutoPtr<nsInsertionPointList>& aData,
     438                 :                   void* aClosure)
     439                 : {
     440               0 :   ContentListData* data = (ContentListData*)aClosure;
     441               0 :   nsBindingManager* bm = data->mBindingManager;
     442               0 :   nsXBLBinding* binding = data->mBinding;
     443                 : 
     444               0 :   nsIContent *boundElement = binding->GetBoundElement();
     445                 : 
     446               0 :   PRInt32 count = aData->Length();
     447                 :   
     448               0 :   if (count == 0)
     449               0 :     return PL_DHASH_NEXT;
     450                 : 
     451                 :   // Figure out the relevant content node.
     452               0 :   nsXBLInsertionPoint* currPoint = aData->ElementAt(0);
     453               0 :   nsCOMPtr<nsIContent> parent = currPoint->GetInsertionParent();
     454               0 :   if (!parent) {
     455               0 :     data->mRv = NS_ERROR_FAILURE;
     456               0 :     return PL_DHASH_STOP;
     457                 :   }
     458               0 :   PRInt32 currIndex = currPoint->GetInsertionIndex();
     459                 : 
     460                 :   // XXX Could this array just be altered in place and passed directly to
     461                 :   // SetContentListFor?  We'd save space if we could pull this off.
     462               0 :   nsInsertionPointList* contentList = new nsInsertionPointList;
     463               0 :   if (!contentList) {
     464               0 :     data->mRv = NS_ERROR_OUT_OF_MEMORY;
     465               0 :     return PL_DHASH_STOP;
     466                 :   }
     467                 : 
     468               0 :   nsCOMPtr<nsIDOMNodeList> nodeList;
     469               0 :   if (parent == boundElement) {
     470                 :     // We are altering anonymous nodes to accommodate insertion points.
     471               0 :     nodeList = binding->GetAnonymousNodes();
     472                 :   }
     473                 :   else {
     474                 :     // We are altering the explicit content list of a node to accommodate insertion points.
     475               0 :     nsCOMPtr<nsIDOMNode> node(do_QueryInterface(parent));
     476               0 :     node->GetChildNodes(getter_AddRefs(nodeList));
     477                 :   }
     478                 : 
     479               0 :   nsXBLInsertionPoint* pseudoPoint = nsnull;
     480                 :   PRUint32 childCount;
     481               0 :   nodeList->GetLength(&childCount);
     482               0 :   PRInt32 j = 0;
     483                 : 
     484               0 :   for (PRUint32 i = 0; i < childCount; i++) {
     485               0 :     nsCOMPtr<nsIDOMNode> node;
     486               0 :     nodeList->Item(i, getter_AddRefs(node));
     487               0 :     nsCOMPtr<nsIContent> child(do_QueryInterface(node));
     488               0 :     if (((PRInt32)i) == currIndex) {
     489                 :       // Add the currPoint to the insertion point list.
     490               0 :       contentList->AppendElement(currPoint);
     491                 : 
     492                 :       // Get the next real insertion point and update our currIndex.
     493               0 :       j++;
     494               0 :       if (j < count) {
     495               0 :         currPoint = aData->ElementAt(j);
     496               0 :         currIndex = currPoint->GetInsertionIndex();
     497                 :       }
     498                 : 
     499                 :       // Null out our current pseudo-point.
     500               0 :       pseudoPoint = nsnull;
     501                 :     }
     502                 :     
     503               0 :     if (!pseudoPoint) {
     504               0 :       pseudoPoint = new nsXBLInsertionPoint(parent, (PRUint32) -1, nsnull);
     505               0 :       if (pseudoPoint) {
     506               0 :         contentList->AppendElement(pseudoPoint);
     507                 :       }
     508                 :     }
     509               0 :     if (pseudoPoint) {
     510               0 :       pseudoPoint->AddChild(child);
     511                 :     }
     512                 :   }
     513                 : 
     514                 :   // Add in all the remaining insertion points.
     515               0 :   contentList->AppendElements(aData->Elements() + j, count - j);
     516                 :   
     517                 :   // Now set the content list using the binding manager,
     518                 :   // If the bound element is the parent, then we alter the anonymous node list
     519                 :   // instead.  This allows us to always maintain two distinct lists should
     520                 :   // insertion points be nested into an inner binding.
     521               0 :   if (parent == boundElement)
     522               0 :     bm->SetAnonymousNodesFor(parent, contentList);
     523                 :   else 
     524               0 :     bm->SetContentListFor(parent, contentList);
     525               0 :   return PL_DHASH_NEXT;
     526                 : }
     527                 : 
     528                 : static PLDHashOperator
     529               0 : RealizeDefaultContent(nsISupports* aKey,
     530                 :                       nsAutoPtr<nsInsertionPointList>& aData,
     531                 :                       void* aClosure)
     532                 : {
     533               0 :   ContentListData* data = (ContentListData*)aClosure;
     534               0 :   nsBindingManager* bm = data->mBindingManager;
     535               0 :   nsXBLBinding* binding = data->mBinding;
     536                 : 
     537               0 :   PRInt32 count = aData->Length();
     538                 :  
     539               0 :   for (PRInt32 i = 0; i < count; i++) {
     540               0 :     nsXBLInsertionPoint* currPoint = aData->ElementAt(i);
     541               0 :     PRInt32 insCount = currPoint->ChildCount();
     542                 :     
     543               0 :     if (insCount == 0) {
     544               0 :       nsCOMPtr<nsIContent> defContent = currPoint->GetDefaultContentTemplate();
     545               0 :       if (defContent) {
     546                 :         // We need to take this template and use it to realize the
     547                 :         // actual default content (through cloning).
     548                 :         // Clone this insertion point element.
     549               0 :         nsCOMPtr<nsIContent> insParent = currPoint->GetInsertionParent();
     550               0 :         if (!insParent) {
     551               0 :           data->mRv = NS_ERROR_FAILURE;
     552               0 :           return PL_DHASH_STOP;
     553                 :         }
     554               0 :         nsIDocument *document = insParent->OwnerDoc();
     555               0 :         nsCOMPtr<nsIDOMNode> clonedNode;
     556               0 :         nsCOMArray<nsINode> nodesWithProperties;
     557                 :         nsNodeUtils::Clone(defContent, true, document->NodeInfoManager(),
     558               0 :                            nodesWithProperties, getter_AddRefs(clonedNode));
     559                 : 
     560                 :         // Now that we have the cloned content, install the default content as
     561                 :         // if it were additional anonymous content.
     562               0 :         nsCOMPtr<nsIContent> clonedContent(do_QueryInterface(clonedNode));
     563               0 :         binding->InstallAnonymousContent(clonedContent, insParent);
     564                 : 
     565                 :         // Cache the clone so that it can be properly destroyed if/when our
     566                 :         // other anonymous content is destroyed.
     567               0 :         currPoint->SetDefaultContent(clonedContent);
     568                 : 
     569                 :         // Now make sure the kids of the clone are added to the insertion point as
     570                 :         // children.
     571               0 :         for (nsIContent* child = clonedContent->GetFirstChild();
     572                 :              child;
     573               0 :              child = child->GetNextSibling()) {
     574               0 :           bm->SetInsertionParent(child, insParent);
     575               0 :           currPoint->AddChild(child);
     576                 :         }
     577                 :       }
     578                 :     }
     579                 :   }
     580                 : 
     581               0 :   return PL_DHASH_NEXT;
     582                 : }
     583                 : 
     584                 : static PLDHashOperator
     585               0 : ChangeDocumentForDefaultContent(nsISupports* aKey,
     586                 :                                 nsAutoPtr<nsInsertionPointList>& aData,
     587                 :                                 void* aClosure)
     588                 : {
     589               0 :   PRInt32 count = aData->Length();
     590               0 :   for (PRInt32 i = 0; i < count; i++) {
     591               0 :     aData->ElementAt(i)->UnbindDefaultContent();
     592                 :   }
     593                 : 
     594               0 :   return PL_DHASH_NEXT;
     595                 : }
     596                 : 
     597                 : void
     598               0 : nsXBLBinding::GenerateAnonymousContent()
     599                 : {
     600               0 :   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
     601                 :                "Someone forgot a script blocker");
     602                 : 
     603                 :   // Fetch the content element for this binding.
     604                 :   nsIContent* content =
     605               0 :     mPrototypeBinding->GetImmediateChild(nsGkAtoms::content);
     606                 : 
     607               0 :   if (!content) {
     608                 :     // We have no anonymous content.
     609               0 :     if (mNextBinding)
     610               0 :       mNextBinding->GenerateAnonymousContent();
     611                 : 
     612               0 :     return;
     613                 :   }
     614                 :      
     615                 :   // Find out if we're really building kids or if we're just
     616                 :   // using the attribute-setting shorthand hack.
     617               0 :   PRUint32 contentCount = content->GetChildCount();
     618                 : 
     619                 :   // Plan to build the content by default.
     620               0 :   bool hasContent = (contentCount > 0);
     621               0 :   bool hasInsertionPoints = mPrototypeBinding->HasInsertionPoints();
     622                 : 
     623                 : #ifdef DEBUG
     624                 :   // See if there's an includes attribute.
     625               0 :   if (nsContentUtils::HasNonEmptyAttr(content, kNameSpaceID_None,
     626               0 :                                       nsGkAtoms::includes)) {
     627               0 :     nsCAutoString message("An XBL Binding with URI ");
     628               0 :     nsCAutoString uri;
     629               0 :     mPrototypeBinding->BindingURI()->GetSpec(uri);
     630               0 :     message += uri;
     631               0 :     message += " is still using the deprecated\n<content includes=\"\"> syntax! Use <children> instead!\n"; 
     632               0 :     NS_WARNING(message.get());
     633                 :   }
     634                 : #endif
     635                 : 
     636               0 :   if (hasContent || hasInsertionPoints) {
     637               0 :     nsIDocument* doc = mBoundElement->OwnerDoc();
     638                 :     
     639               0 :     nsBindingManager *bindingManager = doc->BindingManager();
     640                 : 
     641               0 :     nsCOMPtr<nsIDOMNodeList> children;
     642               0 :     bindingManager->GetContentListFor(mBoundElement, getter_AddRefs(children));
     643                 :  
     644               0 :     nsCOMPtr<nsIDOMNode> node;
     645               0 :     nsCOMPtr<nsIContent> childContent;
     646                 :     PRUint32 length;
     647               0 :     children->GetLength(&length);
     648               0 :     if (length > 0 && !hasInsertionPoints) {
     649                 :       // There are children being placed underneath us, but we have no specified
     650                 :       // insertion points, and therefore no place to put the kids.  Don't generate
     651                 :       // anonymous content.
     652                 :       // Special case template and observes.
     653               0 :       for (PRUint32 i = 0; i < length; i++) {
     654               0 :         children->Item(i, getter_AddRefs(node));
     655               0 :         childContent = do_QueryInterface(node);
     656                 : 
     657               0 :         nsINodeInfo *ni = childContent->NodeInfo();
     658               0 :         nsIAtom *localName = ni->NameAtom();
     659               0 :         if (ni->NamespaceID() != kNameSpaceID_XUL ||
     660                 :             (localName != nsGkAtoms::observes &&
     661                 :              localName != nsGkAtoms::_template)) {
     662               0 :           hasContent = false;
     663               0 :           break;
     664                 :         }
     665                 :       }
     666                 :     }
     667                 : 
     668               0 :     if (hasContent || hasInsertionPoints) {
     669               0 :       nsCOMPtr<nsIDOMNode> clonedNode;
     670               0 :       nsCOMArray<nsINode> nodesWithProperties;
     671                 :       nsNodeUtils::Clone(content, true, doc->NodeInfoManager(),
     672               0 :                          nodesWithProperties, getter_AddRefs(clonedNode));
     673                 : 
     674               0 :       mContent = do_QueryInterface(clonedNode);
     675               0 :       InstallAnonymousContent(mContent, mBoundElement);
     676                 : 
     677               0 :       if (hasInsertionPoints) {
     678                 :         // Now check and see if we have a single insertion point 
     679                 :         // or multiple insertion points.
     680                 :       
     681                 :         // Enumerate the prototype binding's insertion table to build
     682                 :         // our table of instantiated insertion points.
     683               0 :         mPrototypeBinding->InstantiateInsertionPoints(this);
     684                 : 
     685                 :         // We now have our insertion point table constructed.  We
     686                 :         // enumerate this table.  For each array of insertion points
     687                 :         // bundled under the same content node, we generate a content
     688                 :         // list.  In the case of the bound element, we generate a new
     689                 :         // anonymous node list that will be used in place of the binding's
     690                 :         // cached anonymous node list.
     691               0 :         ContentListData data(this, bindingManager);
     692               0 :         mInsertionPointTable->Enumerate(BuildContentLists, &data);
     693               0 :         if (NS_FAILED(data.mRv)) {
     694                 :           return;
     695                 :         }
     696                 : 
     697                 :         // We need to place the children
     698                 :         // at their respective insertion points.
     699               0 :         PRUint32 index = 0;
     700               0 :         bool multiplePoints = false;
     701                 :         nsIContent *singlePoint = GetSingleInsertionPoint(&index,
     702               0 :                                                           &multiplePoints);
     703                 :       
     704               0 :         if (children) {
     705               0 :           if (multiplePoints) {
     706                 :             // We must walk the entire content list in order to determine where
     707                 :             // each child belongs.
     708               0 :             children->GetLength(&length);
     709               0 :             for (PRUint32 i = 0; i < length; i++) {
     710               0 :               children->Item(i, getter_AddRefs(node));
     711               0 :               childContent = do_QueryInterface(node);
     712                 : 
     713                 :               // Now determine the insertion point in the prototype table.
     714                 :               PRUint32 index;
     715               0 :               nsIContent *point = GetInsertionPoint(childContent, &index);
     716               0 :               bindingManager->SetInsertionParent(childContent, point);
     717                 : 
     718                 :               // Find the correct nsIXBLInsertion point in our table.
     719               0 :               nsInsertionPointList* arr = nsnull;
     720               0 :               GetInsertionPointsFor(point, &arr);
     721               0 :               nsXBLInsertionPoint* insertionPoint = nsnull;
     722               0 :               PRInt32 arrCount = arr->Length();
     723               0 :               for (PRInt32 j = 0; j < arrCount; j++) {
     724               0 :                 insertionPoint = arr->ElementAt(j);
     725               0 :                 if (insertionPoint->Matches(point, index))
     726               0 :                   break;
     727               0 :                 insertionPoint = nsnull;
     728                 :               }
     729                 : 
     730               0 :               if (insertionPoint) 
     731               0 :                 insertionPoint->AddChild(childContent);
     732                 :               else {
     733                 :                 // We were unable to place this child.  All anonymous content
     734                 :                 // should be thrown out.  Special-case template and observes.
     735                 : 
     736               0 :                 nsINodeInfo *ni = childContent->NodeInfo();
     737               0 :                 nsIAtom *localName = ni->NameAtom();
     738               0 :                 if (ni->NamespaceID() != kNameSpaceID_XUL ||
     739                 :                     (localName != nsGkAtoms::observes &&
     740                 :                      localName != nsGkAtoms::_template)) {
     741                 :                   // Undo InstallAnonymousContent
     742               0 :                   UninstallAnonymousContent(doc, mContent);
     743                 : 
     744                 :                   // Kill all anonymous content.
     745               0 :                   mContent = nsnull;
     746               0 :                   bindingManager->SetContentListFor(mBoundElement, nsnull);
     747               0 :                   bindingManager->SetAnonymousNodesFor(mBoundElement, nsnull);
     748                 :                   return;
     749                 :                 }
     750                 :               }
     751                 :             }
     752                 :           }
     753                 :           else {
     754                 :             // All of our children are shunted to this single insertion point.
     755               0 :             nsInsertionPointList* arr = nsnull;
     756               0 :             GetInsertionPointsFor(singlePoint, &arr);
     757               0 :             nsXBLInsertionPoint* insertionPoint = arr->ElementAt(0);
     758                 :         
     759               0 :             nsCOMPtr<nsIDOMNode> node;
     760               0 :             nsCOMPtr<nsIContent> content;
     761                 :             PRUint32 length;
     762               0 :             children->GetLength(&length);
     763                 :           
     764               0 :             for (PRUint32 i = 0; i < length; i++) {
     765               0 :               children->Item(i, getter_AddRefs(node));
     766               0 :               content = do_QueryInterface(node);
     767               0 :               bindingManager->SetInsertionParent(content, singlePoint);
     768               0 :               insertionPoint->AddChild(content);
     769                 :             }
     770                 :           }
     771                 :         }
     772                 : 
     773                 :         // Now that all of our children have been added, we need to walk all of our
     774                 :         // nsIXBLInsertion points to see if any of them have default content that
     775                 :         // needs to be built.
     776               0 :         mInsertionPointTable->Enumerate(RealizeDefaultContent, &data);
     777               0 :         if (NS_FAILED(data.mRv)) {
     778                 :           return;
     779                 :         }
     780                 :       }
     781                 :     }
     782                 : 
     783               0 :     mPrototypeBinding->SetInitialAttributes(mBoundElement, mContent);
     784                 :   }
     785                 : 
     786                 :   // Always check the content element for potential attributes.
     787                 :   // This shorthand hack always happens, even when we didn't
     788                 :   // build anonymous content.
     789                 :   const nsAttrName* attrName;
     790               0 :   for (PRUint32 i = 0; (attrName = content->GetAttrNameAt(i)); ++i) {
     791               0 :     PRInt32 namespaceID = attrName->NamespaceID();
     792                 :     // Hold a strong reference here so that the atom doesn't go away during
     793                 :     // UnsetAttr.
     794               0 :     nsCOMPtr<nsIAtom> name = attrName->LocalName();
     795                 : 
     796               0 :     if (name != nsGkAtoms::includes) {
     797               0 :       if (!nsContentUtils::HasNonEmptyAttr(mBoundElement, namespaceID, name)) {
     798               0 :         nsAutoString value2;
     799               0 :         content->GetAttr(namespaceID, name, value2);
     800                 :         mBoundElement->SetAttr(namespaceID, name, attrName->GetPrefix(),
     801               0 :                                value2, false);
     802                 :       }
     803                 :     }
     804                 : 
     805                 :     // Conserve space by wiping the attributes off the clone.
     806               0 :     if (mContent)
     807               0 :       mContent->UnsetAttr(namespaceID, name, false);
     808                 :   }
     809                 : }
     810                 : 
     811                 : void
     812               0 : nsXBLBinding::InstallEventHandlers()
     813                 : {
     814                 :   // Don't install handlers if scripts aren't allowed.
     815               0 :   if (AllowScripts()) {
     816                 :     // Fetch the handlers prototypes for this binding.
     817               0 :     nsXBLPrototypeHandler* handlerChain = mPrototypeBinding->GetPrototypeHandlers();
     818                 : 
     819               0 :     if (handlerChain) {
     820                 :       nsEventListenerManager* manager =
     821               0 :         mBoundElement->GetListenerManager(true);
     822               0 :       if (!manager)
     823               0 :         return;
     824                 : 
     825                 :       bool isChromeDoc =
     826               0 :         nsContentUtils::IsChromeDoc(mBoundElement->OwnerDoc());
     827               0 :       bool isChromeBinding = mPrototypeBinding->IsChrome();
     828                 :       nsXBLPrototypeHandler* curr;
     829               0 :       for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
     830                 :         // Fetch the event type.
     831               0 :         nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
     832               0 :         if (!eventAtom ||
     833               0 :             eventAtom == nsGkAtoms::keyup ||
     834               0 :             eventAtom == nsGkAtoms::keydown ||
     835               0 :             eventAtom == nsGkAtoms::keypress)
     836               0 :           continue;
     837                 : 
     838               0 :         nsXBLEventHandler* handler = curr->GetEventHandler();
     839               0 :         if (handler) {
     840                 :           // Figure out if we're using capturing or not.
     841               0 :           PRInt32 flags = (curr->GetPhase() == NS_PHASE_CAPTURING) ?
     842               0 :             NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
     843                 : 
     844                 :           // If this is a command, add it in the system event group
     845               0 :           if ((curr->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND |
     846                 :                                   NS_HANDLER_TYPE_SYSTEM)) &&
     847               0 :               (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
     848               0 :             flags |= NS_EVENT_FLAG_SYSTEM_EVENT;
     849                 :           }
     850                 : 
     851               0 :           bool hasAllowUntrustedAttr = curr->HasAllowUntrustedAttr();
     852               0 :           if ((hasAllowUntrustedAttr && curr->AllowUntrustedEvents()) ||
     853               0 :               (!hasAllowUntrustedAttr && !isChromeDoc)) {
     854               0 :             flags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
     855                 :           }
     856                 : 
     857                 :           manager->AddEventListenerByType(handler,
     858               0 :                                           nsDependentAtomString(eventAtom),
     859               0 :                                           flags);
     860                 :         }
     861                 :       }
     862                 : 
     863                 :       const nsCOMArray<nsXBLKeyEventHandler>* keyHandlers =
     864               0 :         mPrototypeBinding->GetKeyEventHandlers();
     865                 :       PRInt32 i;
     866               0 :       for (i = 0; i < keyHandlers->Count(); ++i) {
     867               0 :         nsXBLKeyEventHandler* handler = keyHandlers->ObjectAt(i);
     868               0 :         handler->SetIsBoundToChrome(isChromeDoc);
     869                 : 
     870               0 :         nsAutoString type;
     871               0 :         handler->GetEventName(type);
     872                 : 
     873                 :         // If this is a command, add it in the system event group, otherwise 
     874                 :         // add it to the standard event group.
     875                 : 
     876                 :         // Figure out if we're using capturing or not.
     877               0 :         PRInt32 flags = (handler->GetPhase() == NS_PHASE_CAPTURING) ?
     878               0 :           NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
     879                 : 
     880               0 :         if ((handler->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND |
     881                 :                                    NS_HANDLER_TYPE_SYSTEM)) &&
     882               0 :             (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
     883               0 :           flags |= NS_EVENT_FLAG_SYSTEM_EVENT;
     884                 :         }
     885                 : 
     886                 :         // For key handlers we have to set NS_PRIV_EVENT_UNTRUSTED_PERMITTED flag.
     887                 :         // Whether the handling of the event is allowed or not is handled in
     888                 :         // nsXBLKeyEventHandler::HandleEvent
     889               0 :         flags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
     890                 : 
     891               0 :         manager->AddEventListenerByType(handler, type, flags);
     892                 :       }
     893                 :     }
     894                 :   }
     895                 : 
     896               0 :   if (mNextBinding)
     897               0 :     mNextBinding->InstallEventHandlers();
     898                 : }
     899                 : 
     900                 : nsresult
     901               0 : nsXBLBinding::InstallImplementation()
     902                 : {
     903                 :   // Always install the base class properties first, so that
     904                 :   // derived classes can reference the base class properties.
     905                 : 
     906               0 :   if (mNextBinding) {
     907               0 :     nsresult rv = mNextBinding->InstallImplementation();
     908               0 :     NS_ENSURE_SUCCESS(rv, rv);
     909                 :   }
     910                 :   
     911                 :   // iterate through each property in the prototype's list and install the property.
     912               0 :   if (AllowScripts())
     913               0 :     return mPrototypeBinding->InstallImplementation(mBoundElement);
     914                 : 
     915               0 :   return NS_OK;
     916                 : }
     917                 : 
     918                 : nsIAtom*
     919               0 : nsXBLBinding::GetBaseTag(PRInt32* aNameSpaceID)
     920                 : {
     921               0 :   nsIAtom *tag = mPrototypeBinding->GetBaseTag(aNameSpaceID);
     922               0 :   if (!tag && mNextBinding)
     923               0 :     return mNextBinding->GetBaseTag(aNameSpaceID);
     924                 : 
     925               0 :   return tag;
     926                 : }
     927                 : 
     928                 : void
     929               0 : nsXBLBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID,
     930                 :                                bool aRemoveFlag, bool aNotify)
     931                 : {
     932                 :   // XXX Change if we ever allow multiple bindings in a chain to contribute anonymous content
     933               0 :   if (!mContent) {
     934               0 :     if (mNextBinding)
     935                 :       mNextBinding->AttributeChanged(aAttribute, aNameSpaceID,
     936               0 :                                      aRemoveFlag, aNotify);
     937                 :   } else {
     938                 :     mPrototypeBinding->AttributeChanged(aAttribute, aNameSpaceID, aRemoveFlag,
     939               0 :                                         mBoundElement, mContent, aNotify);
     940                 :   }
     941               0 : }
     942                 : 
     943                 : void
     944               0 : nsXBLBinding::ExecuteAttachedHandler()
     945                 : {
     946               0 :   if (mNextBinding)
     947               0 :     mNextBinding->ExecuteAttachedHandler();
     948                 : 
     949               0 :   if (AllowScripts())
     950               0 :     mPrototypeBinding->BindingAttached(mBoundElement);
     951               0 : }
     952                 : 
     953                 : void
     954               0 : nsXBLBinding::ExecuteDetachedHandler()
     955                 : {
     956               0 :   if (AllowScripts())
     957               0 :     mPrototypeBinding->BindingDetached(mBoundElement);
     958                 : 
     959               0 :   if (mNextBinding)
     960               0 :     mNextBinding->ExecuteDetachedHandler();
     961               0 : }
     962                 : 
     963                 : void
     964               0 : nsXBLBinding::UnhookEventHandlers()
     965                 : {
     966               0 :   nsXBLPrototypeHandler* handlerChain = mPrototypeBinding->GetPrototypeHandlers();
     967                 : 
     968               0 :   if (handlerChain) {
     969                 :     nsEventListenerManager* manager =
     970               0 :       mBoundElement->GetListenerManager(false);
     971               0 :     if (!manager) {
     972               0 :       return;
     973                 :     }
     974                 :                                       
     975               0 :     bool isChromeBinding = mPrototypeBinding->IsChrome();
     976                 :     nsXBLPrototypeHandler* curr;
     977               0 :     for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
     978               0 :       nsXBLEventHandler* handler = curr->GetCachedEventHandler();
     979               0 :       if (!handler) {
     980               0 :         continue;
     981                 :       }
     982                 :       
     983               0 :       nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
     984               0 :       if (!eventAtom ||
     985               0 :           eventAtom == nsGkAtoms::keyup ||
     986               0 :           eventAtom == nsGkAtoms::keydown ||
     987               0 :           eventAtom == nsGkAtoms::keypress)
     988               0 :         continue;
     989                 : 
     990                 :       // Figure out if we're using capturing or not.
     991               0 :       PRInt32 flags = (curr->GetPhase() == NS_PHASE_CAPTURING) ?
     992               0 :         NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
     993                 : 
     994                 :       // If this is a command, remove it from the system event group,
     995                 :       // otherwise remove it from the standard event group.
     996                 : 
     997               0 :       if ((curr->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND |
     998                 :                               NS_HANDLER_TYPE_SYSTEM)) &&
     999               0 :           (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
    1000               0 :         flags |= NS_EVENT_FLAG_SYSTEM_EVENT;
    1001                 :       }
    1002                 : 
    1003                 :       manager->RemoveEventListenerByType(handler,
    1004               0 :                                          nsDependentAtomString(eventAtom),
    1005               0 :                                          flags);
    1006                 :     }
    1007                 : 
    1008                 :     const nsCOMArray<nsXBLKeyEventHandler>* keyHandlers =
    1009               0 :       mPrototypeBinding->GetKeyEventHandlers();
    1010                 :     PRInt32 i;
    1011               0 :     for (i = 0; i < keyHandlers->Count(); ++i) {
    1012               0 :       nsXBLKeyEventHandler* handler = keyHandlers->ObjectAt(i);
    1013                 : 
    1014               0 :       nsAutoString type;
    1015               0 :       handler->GetEventName(type);
    1016                 : 
    1017                 :       // Figure out if we're using capturing or not.
    1018               0 :       PRInt32 flags = (handler->GetPhase() == NS_PHASE_CAPTURING) ?
    1019               0 :         NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
    1020                 : 
    1021                 :       // If this is a command, remove it from the system event group, otherwise 
    1022                 :       // remove it from the standard event group.
    1023                 : 
    1024               0 :       if ((handler->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) &&
    1025               0 :           (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
    1026               0 :         flags |= NS_EVENT_FLAG_SYSTEM_EVENT;
    1027                 :       }
    1028                 : 
    1029               0 :       manager->RemoveEventListenerByType(handler, type, flags);
    1030                 :     }
    1031                 :   }
    1032                 : }
    1033                 : 
    1034                 : void
    1035               0 : nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument)
    1036                 : {
    1037               0 :   if (aOldDocument != aNewDocument) {
    1038                 :     // Only style bindings get their prototypes unhooked.  First do ourselves.
    1039               0 :     if (mIsStyleBinding) {
    1040                 :       // Now the binding dies.  Unhook our prototypes.
    1041               0 :       if (mPrototypeBinding->HasImplementation()) { 
    1042               0 :         nsIScriptGlobalObject *global = aOldDocument->GetScopeObject();
    1043               0 :         if (global) {
    1044               0 :           JSObject *scope = global->GetGlobalJSObject();
    1045                 :           // scope might be null if we've cycle-collected the global
    1046                 :           // object, since the Unlink phase of cycle collection happens
    1047                 :           // after JS GC finalization.  But in that case, we don't care
    1048                 :           // about fixing the prototype chain, since everything's going
    1049                 :           // away immediately.
    1050                 : 
    1051               0 :           nsCOMPtr<nsIScriptContext> context = global->GetContext();
    1052               0 :           if (context && scope) {
    1053               0 :             JSContext *cx = context->GetNativeContext();
    1054                 :  
    1055               0 :             nsCxPusher pusher;
    1056               0 :             pusher.Push(cx);
    1057                 : 
    1058               0 :             nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
    1059               0 :             nsIXPConnect *xpc = nsContentUtils::XPConnect();
    1060                 :             nsresult rv =
    1061                 :               xpc->GetWrappedNativeOfNativeObject(cx, scope, mBoundElement,
    1062                 :                                                   NS_GET_IID(nsISupports),
    1063               0 :                                                   getter_AddRefs(wrapper));
    1064               0 :             if (NS_FAILED(rv))
    1065                 :               return;
    1066                 : 
    1067                 :             JSObject* scriptObject;
    1068               0 :             if (wrapper)
    1069               0 :                 wrapper->GetJSObject(&scriptObject);
    1070                 :             else
    1071               0 :                 scriptObject = nsnull;
    1072                 : 
    1073               0 :             if (scriptObject) {
    1074                 :               // XXX Stay in sync! What if a layered binding has an
    1075                 :               // <interface>?!
    1076                 :               // XXXbz what does that comment mean, really?  It seems to date
    1077                 :               // back to when there was such a thing as an <interface>, whever
    1078                 :               // that was...
    1079                 : 
    1080                 :               // Find the right prototype.
    1081               0 :               JSObject* base = scriptObject;
    1082                 :               JSObject* proto;
    1083               0 :               JSAutoRequest ar(cx);
    1084               0 :               JSAutoEnterCompartment ac;
    1085               0 :               if (!ac.enter(cx, scriptObject)) {
    1086                 :                 return;
    1087                 :               }
    1088                 : 
    1089               0 :               for ( ; true; base = proto) { // Will break out on null proto
    1090               0 :                 proto = ::JS_GetPrototype(base);
    1091               0 :                 if (!proto) {
    1092               0 :                   break;
    1093                 :                 }
    1094                 : 
    1095               0 :                 JSClass* clazz = ::JS_GetClass(proto);
    1096               0 :                 if (!clazz ||
    1097                 :                     (~clazz->flags &
    1098                 :                      (JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS)) ||
    1099                 :                     JSCLASS_RESERVED_SLOTS(clazz) != 1 ||
    1100                 :                     clazz->resolve != (JSResolveOp)XBLResolve ||
    1101                 :                     clazz->finalize != XBLFinalize) {
    1102                 :                   // Clearly not the right class
    1103               0 :                   continue;
    1104                 :                 }
    1105                 : 
    1106                 :                 nsRefPtr<nsXBLDocumentInfo> docInfo =
    1107               0 :                   static_cast<nsXBLDocumentInfo*>(::JS_GetPrivate(proto));
    1108               0 :                 if (!docInfo) {
    1109                 :                   // Not the proto we seek
    1110               0 :                   continue;
    1111                 :                 }
    1112                 : 
    1113               0 :                 jsval protoBinding = ::JS_GetReservedSlot(proto, 0);
    1114                 : 
    1115               0 :                 if (JSVAL_TO_PRIVATE(protoBinding) != mPrototypeBinding) {
    1116                 :                   // Not the right binding
    1117               0 :                   continue;
    1118                 :                 }
    1119                 : 
    1120                 :                 // Alright!  This is the right prototype.  Pull it out of the
    1121                 :                 // proto chain.
    1122               0 :                 JSObject* grandProto = ::JS_GetPrototype(proto);
    1123               0 :                 ::JS_SetPrototype(cx, base, grandProto);
    1124               0 :                 break;
    1125                 :               }
    1126                 : 
    1127               0 :               mPrototypeBinding->UndefineFields(cx, scriptObject);
    1128                 : 
    1129                 :               // Don't remove the reference from the document to the
    1130                 :               // wrapper here since it'll be removed by the element
    1131                 :               // itself when that's taken out of the document.
    1132                 :             }
    1133                 :           }
    1134                 :         }
    1135                 :       }
    1136                 : 
    1137                 :       // Remove our event handlers
    1138               0 :       UnhookEventHandlers();
    1139                 :     }
    1140                 : 
    1141                 :     {
    1142               0 :       nsAutoScriptBlocker scriptBlocker;
    1143                 : 
    1144                 :       // Then do our ancestors.  This reverses the construction order, so that at
    1145                 :       // all times things are consistent as far as everyone is concerned.
    1146               0 :       if (mNextBinding) {
    1147               0 :         mNextBinding->ChangeDocument(aOldDocument, aNewDocument);
    1148                 :       }
    1149                 : 
    1150                 :       // Update the anonymous content.
    1151                 :       // XXXbz why not only for style bindings?
    1152               0 :       nsIContent *anonymous = mContent;
    1153               0 :       if (anonymous) {
    1154                 :         // Also kill the default content within all our insertion points.
    1155               0 :         if (mInsertionPointTable)
    1156                 :           mInsertionPointTable->Enumerate(ChangeDocumentForDefaultContent,
    1157               0 :                                           nsnull);
    1158                 : 
    1159               0 :         nsXBLBinding::UninstallAnonymousContent(aOldDocument, anonymous);
    1160                 :       }
    1161                 : 
    1162                 :       // Make sure that henceforth we don't claim that mBoundElement's children
    1163                 :       // have insertion parents in the old document.
    1164               0 :       nsBindingManager* bindingManager = aOldDocument->BindingManager();
    1165               0 :       for (nsIContent* child = mBoundElement->GetLastChild();
    1166                 :            child;
    1167               0 :            child = child->GetPreviousSibling()) {
    1168               0 :         bindingManager->SetInsertionParent(child, nsnull);
    1169                 :       }
    1170                 :     }
    1171                 :   }
    1172                 : }
    1173                 : 
    1174                 : bool
    1175               0 : nsXBLBinding::InheritsStyle() const
    1176                 : {
    1177                 :   // XXX Will have to change if we ever allow multiple bindings to contribute anonymous content.
    1178                 :   // Most derived binding with anonymous content determines style inheritance for now.
    1179                 : 
    1180                 :   // XXX What about bindings with <content> but no kids, e.g., my treecell-text binding?
    1181               0 :   if (mContent)
    1182               0 :     return mPrototypeBinding->InheritsStyle();
    1183                 :   
    1184               0 :   if (mNextBinding)
    1185               0 :     return mNextBinding->InheritsStyle();
    1186                 : 
    1187               0 :   return true;
    1188                 : }
    1189                 : 
    1190                 : void
    1191               0 : nsXBLBinding::WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, void* aData)
    1192                 : {
    1193               0 :   if (mNextBinding)
    1194               0 :     mNextBinding->WalkRules(aFunc, aData);
    1195                 : 
    1196               0 :   nsIStyleRuleProcessor *rules = mPrototypeBinding->GetRuleProcessor();
    1197               0 :   if (rules)
    1198               0 :     (*aFunc)(rules, aData);
    1199               0 : }
    1200                 : 
    1201                 : // Internal helper methods ////////////////////////////////////////////////////////////////
    1202                 : 
    1203                 : // static
    1204                 : nsresult
    1205               0 : nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
    1206                 :                             const nsAFlatCString& aClassName,
    1207                 :                             nsXBLPrototypeBinding* aProtoBinding,
    1208                 :                             JSObject** aClassObject)
    1209                 : {
    1210                 :   // First ensure our JS class is initialized.
    1211               0 :   nsCAutoString className(aClassName);
    1212               0 :   JSObject* parent_proto = nsnull;  // If we have an "obj" we can set this
    1213               0 :   JSAutoRequest ar(cx);
    1214                 : 
    1215               0 :   JSAutoEnterCompartment ac;
    1216               0 :   if (!ac.enter(cx, global)) {
    1217               0 :     return NS_ERROR_FAILURE;
    1218                 :   }
    1219                 : 
    1220               0 :   if (obj) {
    1221                 :     // Retrieve the current prototype of obj.
    1222               0 :     parent_proto = ::JS_GetPrototype(obj);
    1223               0 :     if (parent_proto) {
    1224                 :       // We need to create a unique classname based on aClassName and
    1225                 :       // parent_proto.  Append a space (an invalid URI character) to ensure that
    1226                 :       // we don't have accidental collisions with the case when parent_proto is
    1227                 :       // null and aClassName ends in some bizarre numbers (yeah, it's unlikely).
    1228                 :       jsid parent_proto_id;
    1229               0 :       if (!::JS_GetObjectId(cx, parent_proto, &parent_proto_id)) {
    1230                 :         // Probably OOM
    1231               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1232                 :       }
    1233                 : 
    1234                 :       // One space, maybe "0x", at most 16 chars (on a 64-bit system) of long,
    1235                 :       // and a null-terminator (which PR_snprintf ensures is there even if the
    1236                 :       // string representation of what we're printing does not fit in the buffer
    1237                 :       // provided).
    1238                 :       char buf[20];
    1239               0 :       PR_snprintf(buf, sizeof(buf), " %lx", parent_proto_id);
    1240               0 :       className.Append(buf);
    1241                 :     }
    1242                 :   }
    1243                 : 
    1244                 :   jsval val;
    1245               0 :   JSObject* proto = NULL;
    1246               0 :   if ((!::JS_LookupPropertyWithFlags(cx, global, className.get(),
    1247                 :                                      JSRESOLVE_CLASSNAME,
    1248               0 :                                      &val)) ||
    1249               0 :       JSVAL_IS_PRIMITIVE(val)) {
    1250                 :     // We need to initialize the class.
    1251                 : 
    1252                 :     nsXBLJSClass* c;
    1253                 :     void* classObject;
    1254               0 :     nsCStringKey key(className);
    1255               0 :     classObject = (nsXBLService::gClassTable)->Get(&key);
    1256                 : 
    1257               0 :     if (classObject) {
    1258               0 :       c = static_cast<nsXBLJSClass*>(classObject);
    1259                 : 
    1260                 :       // If c is on the LRU list (i.e., not linked to itself), remove it now!
    1261               0 :       JSCList* link = static_cast<JSCList*>(c);
    1262               0 :       if (c->next != link) {
    1263               0 :         JS_REMOVE_AND_INIT_LINK(link);
    1264               0 :         nsXBLService::gClassLRUListLength--;
    1265                 :       }
    1266                 :     } else {
    1267               0 :       if (JS_CLIST_IS_EMPTY(&nsXBLService::gClassLRUList)) {
    1268                 :         // We need to create a struct for this class.
    1269               0 :         c = new nsXBLJSClass(className);
    1270                 : 
    1271               0 :         if (!c)
    1272               0 :           return NS_ERROR_OUT_OF_MEMORY;
    1273                 :       } else {
    1274                 :         // Pull the least recently used class struct off the list.
    1275               0 :         JSCList* lru = (nsXBLService::gClassLRUList).next;
    1276               0 :         JS_REMOVE_AND_INIT_LINK(lru);
    1277               0 :         nsXBLService::gClassLRUListLength--;
    1278                 : 
    1279                 :         // Remove any mapping from the old name to the class struct.
    1280               0 :         c = static_cast<nsXBLJSClass*>(lru);
    1281               0 :         nsCStringKey oldKey(c->name);
    1282               0 :         (nsXBLService::gClassTable)->Remove(&oldKey);
    1283                 : 
    1284                 :         // Change the class name and we're done.
    1285               0 :         nsMemory::Free((void*) c->name);
    1286               0 :         c->name = ToNewCString(className);
    1287                 :       }
    1288                 : 
    1289                 :       // Add c to our table.
    1290               0 :       (nsXBLService::gClassTable)->Put(&key, (void*)c);
    1291                 :     }
    1292                 : 
    1293                 :     // The prototype holds a strong reference to its class struct.
    1294               0 :     c->Hold();
    1295                 : 
    1296                 :     // Make a new object prototyped by parent_proto and parented by global.
    1297                 :     proto = ::JS_InitClass(cx,                  // context
    1298                 :                            global,              // global object
    1299                 :                            parent_proto,        // parent proto 
    1300                 :                            c,                   // JSClass
    1301                 :                            nsnull,              // JSNative ctor
    1302                 :                            0,                   // ctor args
    1303                 :                            nsnull,              // proto props
    1304                 :                            nsnull,              // proto funcs
    1305                 :                            nsnull,              // ctor props (static)
    1306               0 :                            nsnull);             // ctor funcs (static)
    1307               0 :     if (!proto) {
    1308                 :       // This will happen if we're OOM or if the security manager
    1309                 :       // denies defining the new class...
    1310                 : 
    1311               0 :       (nsXBLService::gClassTable)->Remove(&key);
    1312                 : 
    1313               0 :       c->Drop();
    1314                 : 
    1315               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1316                 :     }
    1317                 : 
    1318                 :     // Keep this proto binding alive while we're alive.  Do this first so that
    1319                 :     // we can guarantee that in XBLFinalize this will be non-null.
    1320                 :     // Note that we can't just store aProtoBinding in the private and
    1321                 :     // addref/release the nsXBLDocumentInfo through it, because cycle
    1322                 :     // collection doesn't seem to work right if the private is not an
    1323                 :     // nsISupports.
    1324               0 :     nsXBLDocumentInfo* docInfo = aProtoBinding->XBLDocumentInfo();
    1325               0 :     ::JS_SetPrivate(proto, docInfo);
    1326               0 :     NS_ADDREF(docInfo);
    1327                 : 
    1328               0 :     ::JS_SetReservedSlot(proto, 0, PRIVATE_TO_JSVAL(aProtoBinding));
    1329                 : 
    1330               0 :     *aClassObject = proto;
    1331                 :   }
    1332                 :   else {
    1333               0 :     proto = JSVAL_TO_OBJECT(val);
    1334                 :   }
    1335                 : 
    1336               0 :   if (obj) {
    1337                 :     // Set the prototype of our object to be the new class.
    1338               0 :     if (!::JS_SetPrototype(cx, obj, proto)) {
    1339               0 :       return NS_ERROR_FAILURE;
    1340                 :     }
    1341                 :   }
    1342                 : 
    1343               0 :   return NS_OK;
    1344                 : }
    1345                 : 
    1346                 : bool
    1347               0 : nsXBLBinding::AllowScripts()
    1348                 : {
    1349               0 :   if (!mPrototypeBinding->GetAllowScripts())
    1350               0 :     return false;
    1351                 : 
    1352                 :   // Nasty hack.  Use the JSContext of the bound node, since the
    1353                 :   // security manager API expects to get the docshell type from
    1354                 :   // that.  But use the nsIPrincipal of our document.
    1355               0 :   nsIScriptSecurityManager* mgr = nsContentUtils::GetSecurityManager();
    1356               0 :   if (!mgr) {
    1357               0 :     return false;
    1358                 :   }
    1359                 : 
    1360               0 :   nsIDocument* doc = mBoundElement ? mBoundElement->OwnerDoc() : nsnull;
    1361               0 :   if (!doc) {
    1362               0 :     return false;
    1363                 :   }
    1364                 : 
    1365               0 :   nsIScriptGlobalObject* global = doc->GetScriptGlobalObject();
    1366               0 :   if (!global) {
    1367               0 :     return false;
    1368                 :   }
    1369                 : 
    1370               0 :   nsCOMPtr<nsIScriptContext> context = global->GetContext();
    1371               0 :   if (!context) {
    1372               0 :     return false;
    1373                 :   }
    1374                 :   
    1375               0 :   JSContext* cx = context->GetNativeContext();
    1376                 : 
    1377                 :   nsCOMPtr<nsIDocument> ourDocument =
    1378               0 :     mPrototypeBinding->XBLDocumentInfo()->GetDocument();
    1379                 :   bool canExecute;
    1380                 :   nsresult rv =
    1381               0 :     mgr->CanExecuteScripts(cx, ourDocument->NodePrincipal(), &canExecute);
    1382               0 :   if (NS_FAILED(rv) || !canExecute) {
    1383               0 :     return false;
    1384                 :   }
    1385                 : 
    1386                 :   // Now one last check: make sure that we're not allowing a privilege
    1387                 :   // escalation here.
    1388                 :   bool haveCert;
    1389               0 :   doc->NodePrincipal()->GetHasCertificate(&haveCert);
    1390               0 :   if (!haveCert) {
    1391               0 :     return true;
    1392                 :   }
    1393                 : 
    1394                 :   bool subsumes;
    1395               0 :   rv = ourDocument->NodePrincipal()->Subsumes(doc->NodePrincipal(), &subsumes);
    1396               0 :   return NS_SUCCEEDED(rv) && subsumes;
    1397                 : }
    1398                 : 
    1399                 : void
    1400               0 : nsXBLBinding::RemoveInsertionParent(nsIContent* aParent)
    1401                 : {
    1402               0 :   if (mNextBinding) {
    1403               0 :     mNextBinding->RemoveInsertionParent(aParent);
    1404                 :   }
    1405               0 :   if (mInsertionPointTable) {
    1406               0 :     nsInsertionPointList* list = nsnull;
    1407               0 :     mInsertionPointTable->Get(aParent, &list);
    1408               0 :     if (list) {
    1409               0 :       PRInt32 count = list->Length();
    1410               0 :       for (PRInt32 i = 0; i < count; ++i) {
    1411               0 :         nsRefPtr<nsXBLInsertionPoint> currPoint = list->ElementAt(i);
    1412               0 :         currPoint->UnbindDefaultContent();
    1413                 : #ifdef DEBUG
    1414               0 :         nsCOMPtr<nsIContent> parent = currPoint->GetInsertionParent();
    1415               0 :         NS_ASSERTION(!parent || parent == aParent, "Wrong insertion parent!");
    1416                 : #endif
    1417               0 :         currPoint->ClearInsertionParent();
    1418                 :       }
    1419               0 :       mInsertionPointTable->Remove(aParent);
    1420                 :     }
    1421                 :   }
    1422               0 : }
    1423                 : 
    1424                 : bool
    1425               0 : nsXBLBinding::HasInsertionParent(nsIContent* aParent)
    1426                 : {
    1427               0 :   if (mInsertionPointTable) {
    1428               0 :     nsInsertionPointList* list = nsnull;
    1429               0 :     mInsertionPointTable->Get(aParent, &list);
    1430               0 :     if (list) {
    1431               0 :       return true;
    1432                 :     }
    1433                 :   }
    1434               0 :   return mNextBinding ? mNextBinding->HasInsertionParent(aParent) : false;
    1435                 : }
    1436                 : 
    1437                 : nsresult
    1438               0 : nsXBLBinding::GetInsertionPointsFor(nsIContent* aParent,
    1439                 :                                     nsInsertionPointList** aResult)
    1440                 : {
    1441               0 :   if (!mInsertionPointTable) {
    1442                 :     mInsertionPointTable =
    1443               0 :       new nsClassHashtable<nsISupportsHashKey, nsInsertionPointList>;
    1444               0 :     if (!mInsertionPointTable || !mInsertionPointTable->Init(4)) {
    1445               0 :       delete mInsertionPointTable;
    1446               0 :       mInsertionPointTable = nsnull;
    1447               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1448                 :     }
    1449                 :   }
    1450                 : 
    1451               0 :   mInsertionPointTable->Get(aParent, aResult);
    1452                 : 
    1453               0 :   if (!*aResult) {
    1454               0 :     *aResult = new nsInsertionPointList;
    1455               0 :     if (!*aResult || !mInsertionPointTable->Put(aParent, *aResult)) {
    1456               0 :       delete *aResult;
    1457               0 :       *aResult = nsnull;
    1458               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1459                 :     }
    1460               0 :     if (aParent) {
    1461               0 :       aParent->SetFlags(NODE_IS_INSERTION_PARENT);
    1462                 :     }
    1463                 :   }
    1464                 : 
    1465               0 :   return NS_OK;
    1466                 : }
    1467                 : 
    1468                 : nsInsertionPointList*
    1469               0 : nsXBLBinding::GetExistingInsertionPointsFor(nsIContent* aParent)
    1470                 : {
    1471               0 :   if (!mInsertionPointTable) {
    1472               0 :     return nsnull;
    1473                 :   }
    1474                 : 
    1475               0 :   nsInsertionPointList* result = nsnull;
    1476               0 :   mInsertionPointTable->Get(aParent, &result);
    1477               0 :   return result;
    1478                 : }
    1479                 : 
    1480                 : nsIContent*
    1481               0 : nsXBLBinding::GetInsertionPoint(const nsIContent* aChild, PRUint32* aIndex)
    1482                 : {
    1483               0 :   if (mContent) {
    1484                 :     return mPrototypeBinding->GetInsertionPoint(mBoundElement, mContent,
    1485               0 :                                                 aChild, aIndex);
    1486                 :   }
    1487                 : 
    1488               0 :   if (mNextBinding)
    1489               0 :     return mNextBinding->GetInsertionPoint(aChild, aIndex);
    1490                 : 
    1491               0 :   return nsnull;
    1492                 : }
    1493                 : 
    1494                 : nsIContent*
    1495               0 : nsXBLBinding::GetSingleInsertionPoint(PRUint32* aIndex,
    1496                 :                                       bool* aMultipleInsertionPoints)
    1497                 : {
    1498               0 :   *aMultipleInsertionPoints = false;
    1499               0 :   if (mContent) {
    1500                 :     return mPrototypeBinding->GetSingleInsertionPoint(mBoundElement, mContent, 
    1501                 :                                                       aIndex, 
    1502               0 :                                                       aMultipleInsertionPoints);
    1503                 :   }
    1504                 : 
    1505               0 :   if (mNextBinding)
    1506                 :     return mNextBinding->GetSingleInsertionPoint(aIndex,
    1507               0 :                                                  aMultipleInsertionPoints);
    1508                 : 
    1509               0 :   return nsnull;
    1510                 : }
    1511                 : 
    1512                 : nsXBLBinding*
    1513               0 : nsXBLBinding::RootBinding()
    1514                 : {
    1515               0 :   if (mNextBinding)
    1516               0 :     return mNextBinding->RootBinding();
    1517                 : 
    1518               0 :   return this;
    1519                 : }
    1520                 : 
    1521                 : nsXBLBinding*
    1522               0 : nsXBLBinding::GetFirstStyleBinding()
    1523                 : {
    1524               0 :   if (mIsStyleBinding)
    1525               0 :     return this;
    1526                 : 
    1527               0 :   return mNextBinding ? mNextBinding->GetFirstStyleBinding() : nsnull;
    1528                 : }
    1529                 : 
    1530                 : bool
    1531               0 : nsXBLBinding::ResolveAllFields(JSContext *cx, JSObject *obj) const
    1532                 : {
    1533               0 :   if (!mPrototypeBinding->ResolveAllFields(cx, obj)) {
    1534               0 :     return false;
    1535                 :   }
    1536                 : 
    1537               0 :   if (mNextBinding) {
    1538               0 :     return mNextBinding->ResolveAllFields(cx, obj);
    1539                 :   }
    1540                 : 
    1541               0 :   return true;
    1542                 : }
    1543                 : 
    1544                 : void
    1545               0 : nsXBLBinding::MarkForDeath()
    1546                 : {
    1547               0 :   mMarkedForDeath = true;
    1548               0 :   ExecuteDetachedHandler();
    1549               0 : }
    1550                 : 
    1551                 : bool
    1552               0 : nsXBLBinding::ImplementsInterface(REFNSIID aIID) const
    1553                 : {
    1554               0 :   return mPrototypeBinding->ImplementsInterface(aIID) ||
    1555               0 :     (mNextBinding && mNextBinding->ImplementsInterface(aIID));
    1556                 : }
    1557                 : 
    1558                 : nsINodeList*
    1559               0 : nsXBLBinding::GetAnonymousNodes()
    1560                 : {
    1561               0 :   if (mContent) {
    1562               0 :     return mContent->GetChildNodesList();
    1563                 :   }
    1564                 : 
    1565               0 :   if (mNextBinding)
    1566               0 :     return mNextBinding->GetAnonymousNodes();
    1567                 : 
    1568               0 :   return nsnull;
    1569            4392 : }

Generated by: LCOV version 1.7