LCOV - code coverage report
Current view: top level - dom/xbl - nsXBLPrototypeBinding.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 524 840 62.4 %
Date: 2017-07-14 16:53:18 Functions: 44 65 67.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/ArrayUtils.h"
       8             : 
       9             : #include "nsCOMPtr.h"
      10             : #include "nsIAtom.h"
      11             : #include "nsIInputStream.h"
      12             : #include "nsNameSpaceManager.h"
      13             : #include "nsIURI.h"
      14             : #include "nsIURL.h"
      15             : #include "nsIChannel.h"
      16             : #include "nsXPIDLString.h"
      17             : #include "nsReadableUtils.h"
      18             : #include "nsNetUtil.h"
      19             : #include "plstr.h"
      20             : #include "nsContentCreatorFunctions.h"
      21             : #include "nsIDocument.h"
      22             : #include "nsIXMLContentSink.h"
      23             : #include "nsContentCID.h"
      24             : #include "mozilla/dom/XMLDocument.h"
      25             : #include "nsXBLService.h"
      26             : #include "nsXBLBinding.h"
      27             : #include "nsXBLPrototypeBinding.h"
      28             : #include "nsXBLContentSink.h"
      29             : #include "xptinfo.h"
      30             : #include "nsIInterfaceInfoManager.h"
      31             : #include "nsIDocumentObserver.h"
      32             : #include "nsGkAtoms.h"
      33             : #include "nsXBLProtoImpl.h"
      34             : #include "nsCRT.h"
      35             : #include "nsContentUtils.h"
      36             : #include "nsTextFragment.h"
      37             : #include "nsTextNode.h"
      38             : #include "nsIInterfaceInfo.h"
      39             : #include "nsIScriptError.h"
      40             : 
      41             : #include "nsCSSRuleProcessor.h"
      42             : #include "nsXBLResourceLoader.h"
      43             : #include "mozilla/AddonPathService.h"
      44             : #include "mozilla/dom/CDATASection.h"
      45             : #include "mozilla/dom/Comment.h"
      46             : #include "mozilla/dom/Element.h"
      47             : #include "mozilla/StyleSheet.h"
      48             : #include "mozilla/StyleSheetInlines.h"
      49             : 
      50             : #ifdef MOZ_XUL
      51             : #include "nsXULElement.h"
      52             : #endif
      53             : 
      54             : using namespace mozilla;
      55             : using namespace mozilla::dom;
      56             : 
      57             : // Helper Classes =====================================================================
      58             : 
      59             : // nsXBLAttributeEntry and helpers.  This class is used to efficiently handle
      60             : // attribute changes in anonymous content.
      61             : 
      62             : class nsXBLAttributeEntry {
      63             : public:
      64         635 :   nsXBLAttributeEntry(nsIAtom* aSrcAtom, nsIAtom* aDstAtom,
      65             :                       int32_t aDstNameSpace, nsIContent* aContent)
      66         635 :     : mElement(aContent),
      67             :       mSrcAttribute(aSrcAtom),
      68             :       mDstAttribute(aDstAtom),
      69             :       mDstNameSpace(aDstNameSpace),
      70         635 :       mNext(nullptr) { }
      71             : 
      72           0 :   ~nsXBLAttributeEntry() {
      73           0 :     NS_CONTENT_DELETE_LIST_MEMBER(nsXBLAttributeEntry, this, mNext);
      74           0 :   }
      75             : 
      76         736 :   nsIAtom* GetSrcAttribute() { return mSrcAttribute; }
      77         348 :   nsIAtom* GetDstAttribute() { return mDstAttribute; }
      78         348 :   int32_t GetDstNameSpace() { return mDstNameSpace; }
      79             : 
      80         348 :   nsIContent* GetElement() { return mElement; }
      81             : 
      82        1197 :   nsXBLAttributeEntry* GetNext() { return mNext; }
      83         205 :   void SetNext(nsXBLAttributeEntry* aEntry) { mNext = aEntry; }
      84             : 
      85             : protected:
      86             :   nsIContent* mElement;
      87             : 
      88             :   nsCOMPtr<nsIAtom> mSrcAttribute;
      89             :   nsCOMPtr<nsIAtom> mDstAttribute;
      90             :   int32_t mDstNameSpace;
      91             :   nsXBLAttributeEntry* mNext;
      92             : };
      93             : 
      94             : // =============================================================================
      95             : 
      96             : // Implementation /////////////////////////////////////////////////////////////////
      97             : 
      98             : // Constructors/Destructors
      99         145 : nsXBLPrototypeBinding::nsXBLPrototypeBinding()
     100             : : mImplementation(nullptr),
     101             :   mBaseBinding(nullptr),
     102             :   mInheritStyle(true),
     103             :   mCheckedBaseProto(false),
     104             :   mKeyHandlersRegistered(false),
     105             :   mChromeOnlyContent(false),
     106             :   mBindToUntrustedContent(false),
     107             :   mResources(nullptr),
     108         145 :   mBaseNameSpaceID(kNameSpaceID_None)
     109             : {
     110         145 :   MOZ_COUNT_CTOR(nsXBLPrototypeBinding);
     111         145 : }
     112             : 
     113             : nsresult
     114         145 : nsXBLPrototypeBinding::Init(const nsACString& aID,
     115             :                             nsXBLDocumentInfo* aInfo,
     116             :                             nsIContent* aElement,
     117             :                             bool aFirstBinding)
     118             : {
     119         145 :   nsresult rv = aInfo->DocumentURI()->Clone(getter_AddRefs(mBindingURI));
     120         145 :   NS_ENSURE_SUCCESS(rv, rv);
     121             : 
     122             :   // The binding URI might be an immutable URI (e.g. for about: URIs). In that case,
     123             :   // we'll fail in SetRef below, but that doesn't matter much for now.
     124         145 :   if (aFirstBinding) {
     125          26 :     rv = mBindingURI->Clone(getter_AddRefs(mAlternateBindingURI));
     126          26 :     NS_ENSURE_SUCCESS(rv, rv);
     127             :   }
     128         145 :   mBindingURI->SetRef(aID);
     129             : 
     130         145 :   mXBLDocInfoWeak = aInfo;
     131             : 
     132             :   // aElement will be null when reading from the cache, but the element will
     133             :   // still be set later.
     134         145 :   if (aElement) {
     135           3 :     SetBindingElement(aElement);
     136             :   }
     137         145 :   return NS_OK;
     138             : }
     139             : 
     140         215 : bool nsXBLPrototypeBinding::CompareBindingURI(nsIURI* aURI) const
     141             : {
     142         215 :   bool equal = false;
     143         215 :   mBindingURI->Equals(aURI, &equal);
     144         215 :   if (!equal && mAlternateBindingURI) {
     145          46 :     mAlternateBindingURI->Equals(aURI, &equal);
     146             :   }
     147         215 :   return equal;
     148             : }
     149             : 
     150             : void
     151           0 : nsXBLPrototypeBinding::Traverse(nsCycleCollectionTraversalCallback &cb) const
     152             : {
     153           0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "proto mBinding");
     154           0 :   cb.NoteXPCOMChild(mBinding);
     155           0 :   if (mResources) {
     156           0 :     mResources->Traverse(cb);
     157             :   }
     158           0 :   ImplCycleCollectionTraverse(cb, mInterfaceTable, "proto mInterfaceTable");
     159           0 : }
     160             : 
     161             : void
     162           0 : nsXBLPrototypeBinding::Unlink()
     163             : {
     164           0 :   if (mImplementation) {
     165           0 :     mImplementation->UnlinkJSObjects();
     166             :   }
     167             : 
     168           0 :   if (mResources) {
     169           0 :     mResources->Unlink();
     170             :   }
     171           0 : }
     172             : 
     173             : void
     174         142 : nsXBLPrototypeBinding::Trace(const TraceCallbacks& aCallbacks, void *aClosure) const
     175             : {
     176         142 :   if (mImplementation)
     177          83 :     mImplementation->Trace(aCallbacks, aClosure);
     178         142 : }
     179             : 
     180             : void
     181           3 : nsXBLPrototypeBinding::Initialize()
     182             : {
     183           3 :   nsIContent* content = GetImmediateChild(nsGkAtoms::content);
     184           3 :   if (content) {
     185           1 :     ConstructAttributeTable(content);
     186             :   }
     187           3 : }
     188             : 
     189           0 : nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
     190             : {
     191           0 :   delete mImplementation;
     192           0 :   MOZ_COUNT_DTOR(nsXBLPrototypeBinding);
     193           0 : }
     194             : 
     195             : void
     196          60 : nsXBLPrototypeBinding::SetBasePrototype(nsXBLPrototypeBinding* aBinding)
     197             : {
     198          60 :   if (mBaseBinding == aBinding)
     199           0 :     return;
     200             : 
     201          60 :   if (mBaseBinding) {
     202           0 :     NS_ERROR("Base XBL prototype binding is already defined!");
     203           0 :     return;
     204             :   }
     205             : 
     206          60 :   mBaseBinding = aBinding;
     207             : }
     208             : 
     209             : void
     210           3 : nsXBLPrototypeBinding::SetBindingElement(nsIContent* aElement)
     211             : {
     212           3 :   mBinding = aElement;
     213           3 :   if (mBinding->AttrValueIs(kNameSpaceID_None, nsGkAtoms::inheritstyle,
     214             :                             nsGkAtoms::_false, eCaseMatters))
     215           0 :     mInheritStyle = false;
     216             : 
     217           3 :   mChromeOnlyContent = mBinding->AttrValueIs(kNameSpaceID_None,
     218             :                                              nsGkAtoms::chromeOnlyContent,
     219             :                                              nsGkAtoms::_true, eCaseMatters);
     220             : 
     221           3 :   mBindToUntrustedContent = mBinding->AttrValueIs(kNameSpaceID_None,
     222             :                                                   nsGkAtoms::bindToUntrustedContent,
     223             :                                                   nsGkAtoms::_true, eCaseMatters);
     224           3 : }
     225             : 
     226             : bool
     227        2052 : nsXBLPrototypeBinding::GetAllowScripts() const
     228             : {
     229        2052 :   return mXBLDocInfoWeak->GetScriptAccess();
     230             : }
     231             : 
     232             : bool
     233         633 : nsXBLPrototypeBinding::LoadResources(nsIContent* aBoundElement)
     234             : {
     235         633 :   if (mResources) {
     236         164 :     return mResources->LoadResources(aBoundElement);
     237             :   }
     238             : 
     239         469 :   return true;
     240             : }
     241             : 
     242             : nsresult
     243          39 : nsXBLPrototypeBinding::AddResource(nsIAtom* aResourceType, const nsAString& aSrc)
     244             : {
     245          39 :   EnsureResources();
     246             : 
     247          39 :   mResources->AddResource(aResourceType, aSrc);
     248          39 :   return NS_OK;
     249             : }
     250             : 
     251             : nsresult
     252           0 : nsXBLPrototypeBinding::FlushSkinSheets()
     253             : {
     254           0 :   if (mResources)
     255           0 :     return mResources->FlushSkinSheets();
     256           0 :   return NS_OK;
     257             : }
     258             : 
     259             : nsresult
     260         633 : nsXBLPrototypeBinding::BindingAttached(nsIContent* aBoundElement)
     261             : {
     262        1156 :   if (mImplementation && mImplementation->CompiledMembers() &&
     263         523 :       mImplementation->mConstructor)
     264          48 :     return mImplementation->mConstructor->Execute(aBoundElement, MapURIToAddonID(mBindingURI));
     265         585 :   return NS_OK;
     266             : }
     267             : 
     268             : nsresult
     269           7 : nsXBLPrototypeBinding::BindingDetached(nsIContent* aBoundElement)
     270             : {
     271          13 :   if (mImplementation && mImplementation->CompiledMembers() &&
     272           6 :       mImplementation->mDestructor)
     273           0 :     return mImplementation->mDestructor->Execute(aBoundElement, MapURIToAddonID(mBindingURI));
     274           7 :   return NS_OK;
     275             : }
     276             : 
     277             : nsXBLProtoImplAnonymousMethod*
     278           0 : nsXBLPrototypeBinding::GetConstructor()
     279             : {
     280           0 :   if (mImplementation)
     281           0 :     return mImplementation->mConstructor;
     282             : 
     283           0 :   return nullptr;
     284             : }
     285             : 
     286             : nsXBLProtoImplAnonymousMethod*
     287           0 : nsXBLPrototypeBinding::GetDestructor()
     288             : {
     289           0 :   if (mImplementation)
     290           0 :     return mImplementation->mDestructor;
     291             : 
     292           0 :   return nullptr;
     293             : }
     294             : 
     295             : nsresult
     296           0 : nsXBLPrototypeBinding::SetConstructor(nsXBLProtoImplAnonymousMethod* aMethod)
     297             : {
     298           0 :   if (!mImplementation)
     299           0 :     return NS_ERROR_FAILURE;
     300           0 :   mImplementation->mConstructor = aMethod;
     301           0 :   return NS_OK;
     302             : }
     303             : 
     304             : nsresult
     305           0 : nsXBLPrototypeBinding::SetDestructor(nsXBLProtoImplAnonymousMethod* aMethod)
     306             : {
     307           0 :   if (!mImplementation)
     308           0 :     return NS_ERROR_FAILURE;
     309           0 :   mImplementation->mDestructor = aMethod;
     310           0 :   return NS_OK;
     311             : }
     312             : 
     313             : nsresult
     314         633 : nsXBLPrototypeBinding::InstallImplementation(nsXBLBinding* aBinding)
     315             : {
     316         633 :   if (mImplementation)
     317         523 :     return mImplementation->InstallImplementation(this, aBinding);
     318         110 :   return NS_OK;
     319             : }
     320             : 
     321             : // XXXbz this duplicates lots of SetAttrs
     322             : void
     323         177 : nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute,
     324             :                                         int32_t aNameSpaceID,
     325             :                                         bool aRemoveFlag,
     326             :                                         nsIContent* aChangedElement,
     327             :                                         nsIContent* aAnonymousContent,
     328             :                                         bool aNotify)
     329             : {
     330         177 :   if (!mAttributeTable)
     331         128 :     return;
     332             : 
     333         162 :   InnerAttributeTable *attributesNS = mAttributeTable->Get(aNameSpaceID);
     334         162 :   if (!attributesNS)
     335           0 :     return;
     336             : 
     337         162 :   nsXBLAttributeEntry* xblAttr = attributesNS->Get(aAttribute);
     338         162 :   if (!xblAttr)
     339          98 :     return;
     340             : 
     341             :   // Iterate over the elements in the array.
     342         128 :   nsCOMPtr<nsIContent> content = GetImmediateChild(nsGkAtoms::content);
     343         378 :   while (xblAttr) {
     344         157 :     nsIContent* element = xblAttr->GetElement();
     345             : 
     346             :     nsCOMPtr<nsIContent> realElement = LocateInstance(aChangedElement, content,
     347             :                                                       aAnonymousContent,
     348         314 :                                                       element);
     349             : 
     350         157 :     if (realElement) {
     351             :       // Hold a strong reference here so that the atom doesn't go away during
     352             :       // UnsetAttr.
     353         314 :       nsCOMPtr<nsIAtom> dstAttr = xblAttr->GetDstAttribute();
     354         157 :       int32_t dstNs = xblAttr->GetDstNameSpace();
     355             : 
     356         157 :       if (aRemoveFlag)
     357           5 :         realElement->UnsetAttr(dstNs, dstAttr, aNotify);
     358             :       else {
     359         152 :         bool attrPresent = true;
     360         304 :         nsAutoString value;
     361             :         // Check to see if the src attribute is xbl:text.  If so, then we need to obtain the
     362             :         // children of the real element and get the text nodes' values.
     363         152 :         if (aAttribute == nsGkAtoms::text && aNameSpaceID == kNameSpaceID_XBL) {
     364           0 :           nsContentUtils::GetNodeTextContent(aChangedElement, false, value);
     365           0 :           value.StripChar(char16_t('\n'));
     366           0 :           value.StripChar(char16_t('\r'));
     367           0 :           nsAutoString stripVal(value);
     368           0 :           stripVal.StripWhitespace();
     369           0 :           if (stripVal.IsEmpty())
     370           0 :             attrPresent = false;
     371             :         }
     372             :         else {
     373         152 :           attrPresent = aChangedElement->GetAttr(aNameSpaceID, aAttribute, value);
     374             :         }
     375             : 
     376         152 :         if (attrPresent)
     377         152 :           realElement->SetAttr(dstNs, dstAttr, value, aNotify);
     378             :       }
     379             : 
     380             :       // See if we're the <html> tag in XUL, and see if value is being
     381             :       // set or unset on us.  We may also be a tag that is having
     382             :       // xbl:text set on us.
     383             : 
     384         314 :       if ((dstAttr == nsGkAtoms::text && dstNs == kNameSpaceID_XBL) ||
     385         153 :           (realElement->NodeInfo()->Equals(nsGkAtoms::html,
     386           0 :                                            kNameSpaceID_XUL) &&
     387           0 :            dstAttr == nsGkAtoms::value)) {
     388             :         // Flush out all our kids.
     389           4 :         uint32_t childCount = realElement->GetChildCount();
     390           5 :         for (uint32_t i = 0; i < childCount; i++)
     391           1 :           realElement->RemoveChildAt(0, aNotify);
     392             : 
     393           4 :         if (!aRemoveFlag) {
     394             :           // Construct a new text node and insert it.
     395           8 :           nsAutoString value;
     396           4 :           aChangedElement->GetAttr(aNameSpaceID, aAttribute, value);
     397           4 :           if (!value.IsEmpty()) {
     398             :             RefPtr<nsTextNode> textContent =
     399          12 :               new nsTextNode(realElement->NodeInfo()->NodeInfoManager());
     400             : 
     401           4 :             textContent->SetText(value, true);
     402           4 :             realElement->AppendChildTo(textContent, true);
     403             :           }
     404             :         }
     405             :       }
     406             :     }
     407             : 
     408         157 :     xblAttr = xblAttr->GetNext();
     409             :   }
     410             : }
     411             : 
     412             : void
     413           1 : nsXBLPrototypeBinding::SetBaseTag(int32_t aNamespaceID, nsIAtom* aTag)
     414             : {
     415           1 :   mBaseNameSpaceID = aNamespaceID;
     416           1 :   mBaseTag = aTag;
     417           1 : }
     418             : 
     419             : nsIAtom*
     420         800 : nsXBLPrototypeBinding::GetBaseTag(int32_t* aNamespaceID)
     421             : {
     422         800 :   if (mBaseTag) {
     423          86 :     *aNamespaceID = mBaseNameSpaceID;
     424          86 :     return mBaseTag;
     425             :   }
     426             : 
     427         714 :   return nullptr;
     428             : }
     429             : 
     430             : bool
     431         319 : nsXBLPrototypeBinding::ImplementsInterface(REFNSIID aIID) const
     432             : {
     433             :   // Check our IID table.
     434         319 :   return !!mInterfaceTable.GetWeak(aIID);
     435             : }
     436             : 
     437             : // Internal helpers ///////////////////////////////////////////////////////////////////////
     438             : 
     439             : nsIContent*
     440         483 : nsXBLPrototypeBinding::GetImmediateChild(nsIAtom* aTag)
     441             : {
     442         483 :   for (nsIContent* child = mBinding->GetFirstChild();
     443         483 :        child;
     444           0 :        child = child->GetNextSibling()) {
     445         319 :     if (child->NodeInfo()->Equals(aTag, kNameSpaceID_XBL)) {
     446         319 :       return child;
     447             :     }
     448             :   }
     449             : 
     450         164 :   return nullptr;
     451             : }
     452             : 
     453             : nsresult
     454         523 : nsXBLPrototypeBinding::InitClass(const nsString& aClassName,
     455             :                                  JSContext * aContext,
     456             :                                  JS::Handle<JSObject*> aScriptObject,
     457             :                                  JS::MutableHandle<JSObject*> aClassObject,
     458             :                                  bool* aNew)
     459             : {
     460             :   return nsXBLBinding::DoInitJSClass(aContext, aScriptObject,
     461         523 :                                      aClassName, this, aClassObject, aNew);
     462             : }
     463             : 
     464             : nsIContent*
     465         532 : nsXBLPrototypeBinding::LocateInstance(nsIContent* aBoundElement,
     466             :                                       nsIContent* aTemplRoot,
     467             :                                       nsIContent* aCopyRoot,
     468             :                                       nsIContent* aTemplChild)
     469             : {
     470             :   // XXX We will get in trouble if the binding instantiation deviates from the template
     471             :   // in the prototype.
     472         532 :   if (aTemplChild == aTemplRoot || !aTemplChild)
     473           0 :     return nullptr;
     474             : 
     475         532 :   nsIContent* templParent = aTemplChild->GetParent();
     476             : 
     477             :   // We may be disconnected from our parent during cycle collection.
     478         532 :   if (!templParent)
     479           0 :     return nullptr;
     480             : 
     481             :   nsIContent *copyParent =
     482         532 :     templParent == aTemplRoot ? aCopyRoot :
     483         532 :                    LocateInstance(aBoundElement, aTemplRoot, aCopyRoot, templParent);
     484             : 
     485         532 :   if (!copyParent)
     486           0 :     return nullptr;
     487             : 
     488         532 :   return copyParent->GetChildAt(templParent->IndexOf(aTemplChild));
     489             : }
     490             : 
     491             : void
     492         150 : nsXBLPrototypeBinding::SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent)
     493             : {
     494         150 :   if (!mAttributeTable) {
     495          46 :     return;
     496             :   }
     497             : 
     498         208 :   for (auto iter1 = mAttributeTable->Iter(); !iter1.Done(); iter1.Next()) {
     499         104 :     InnerAttributeTable* xblAttributes = iter1.UserData();
     500         104 :     if (xblAttributes) {
     501         104 :       int32_t srcNamespace = iter1.Key();
     502             : 
     503         840 :       for (auto iter2 = xblAttributes->Iter(); !iter2.Done(); iter2.Next()) {
     504             :         // XXXbz this duplicates lots of AttributeChanged
     505         736 :         nsXBLAttributeEntry* entry = iter2.UserData();
     506         736 :         nsIAtom* src = entry->GetSrcAttribute();
     507        1472 :         nsAutoString value;
     508         736 :         bool attrPresent = true;
     509             : 
     510         736 :         if (src == nsGkAtoms::text && srcNamespace == kNameSpaceID_XBL) {
     511           0 :           nsContentUtils::GetNodeTextContent(aBoundElement, false, value);
     512           0 :           value.StripChar(char16_t('\n'));
     513           0 :           value.StripChar(char16_t('\r'));
     514           0 :           nsAutoString stripVal(value);
     515           0 :           stripVal.StripWhitespace();
     516             : 
     517           0 :           if (stripVal.IsEmpty()) {
     518           0 :             attrPresent = false;
     519           0 :           }
     520             :         } else {
     521         736 :           attrPresent = aBoundElement->GetAttr(srcNamespace, src, value);
     522             :         }
     523             : 
     524         736 :         if (attrPresent) {
     525         103 :           nsIContent* content = GetImmediateChild(nsGkAtoms::content);
     526             : 
     527         103 :           nsXBLAttributeEntry* curr = entry;
     528         485 :           while (curr) {
     529         191 :             nsIAtom* dst = curr->GetDstAttribute();
     530         191 :             int32_t dstNs = curr->GetDstNameSpace();
     531         191 :             nsIContent* element = curr->GetElement();
     532             : 
     533             :             nsIContent* realElement =
     534             :               LocateInstance(aBoundElement, content,
     535         191 :                              aAnonymousContent, element);
     536             : 
     537         191 :             if (realElement) {
     538         191 :               realElement->SetAttr(dstNs, dst, value, false);
     539             : 
     540             :               // XXXndeakin shouldn't this be done in lieu of SetAttr?
     541         382 :               if ((dst == nsGkAtoms::text && dstNs == kNameSpaceID_XBL) ||
     542         173 :                   (realElement->NodeInfo()->Equals(nsGkAtoms::html,
     543           0 :                                                    kNameSpaceID_XUL) &&
     544           0 :                    dst == nsGkAtoms::value && !value.IsEmpty())) {
     545             : 
     546             :                 RefPtr<nsTextNode> textContent =
     547          54 :                   new nsTextNode(realElement->NodeInfo()->NodeInfoManager());
     548             : 
     549          18 :                 textContent->SetText(value, false);
     550          18 :                 realElement->AppendChildTo(textContent, false);
     551             :               }
     552             :             }
     553             : 
     554         191 :             curr = curr->GetNext();
     555             :           }
     556             :         }
     557             :       }
     558             :     }
     559             :   }
     560             : }
     561             : 
     562             : nsIStyleRuleProcessor*
     563       12785 : nsXBLPrototypeBinding::GetRuleProcessor()
     564             : {
     565       12785 :   if (mResources) {
     566        4032 :     return mResources->GetRuleProcessor();
     567             :   }
     568             : 
     569        8753 :   return nullptr;
     570             : }
     571             : 
     572             : const ServoStyleSet*
     573           0 : nsXBLPrototypeBinding::GetServoStyleSet() const
     574             : {
     575           0 :   return mResources ? mResources->GetServoStyleSet() : nullptr;
     576             : }
     577             : 
     578             : void
     579         615 : nsXBLPrototypeBinding::EnsureAttributeTable()
     580             : {
     581         615 :   if (!mAttributeTable) {
     582             :     mAttributeTable =
     583          63 :         new nsClassHashtable<nsUint32HashKey, InnerAttributeTable>(2);
     584             :   }
     585         615 : }
     586             : 
     587             : void
     588         635 : nsXBLPrototypeBinding::AddToAttributeTable(int32_t aSourceNamespaceID, nsIAtom* aSourceTag,
     589             :                                            int32_t aDestNamespaceID, nsIAtom* aDestTag,
     590             :                                            nsIContent* aContent)
     591             : {
     592         635 :     InnerAttributeTable* attributesNS = mAttributeTable->Get(aSourceNamespaceID);
     593         635 :     if (!attributesNS) {
     594          63 :       attributesNS = new InnerAttributeTable(2);
     595          63 :       mAttributeTable->Put(aSourceNamespaceID, attributesNS);
     596             :     }
     597             : 
     598             :     nsXBLAttributeEntry* xblAttr =
     599         635 :       new nsXBLAttributeEntry(aSourceTag, aDestTag, aDestNamespaceID, aContent);
     600             : 
     601         635 :     nsXBLAttributeEntry* entry = attributesNS->Get(aSourceTag);
     602         635 :     if (!entry) {
     603         430 :       attributesNS->Put(aSourceTag, xblAttr);
     604             :     } else {
     605         322 :       while (entry->GetNext())
     606         322 :         entry = entry->GetNext();
     607         205 :       entry->SetNext(xblAttr);
     608             :     }
     609         635 : }
     610             : 
     611             : void
     612           7 : nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement)
     613             : {
     614             :   // Don't add entries for <children> elements, since those will get
     615             :   // removed from the DOM when we construct the insertion point table.
     616           7 :   if (!aElement->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
     617          14 :     nsAutoString inherits;
     618           7 :     aElement->GetAttr(kNameSpaceID_XBL, nsGkAtoms::inherits, inherits);
     619             : 
     620           7 :     if (!inherits.IsEmpty()) {
     621           6 :       EnsureAttributeTable();
     622             : 
     623             :       // The user specified at least one attribute.
     624           6 :       char* str = ToNewCString(inherits);
     625             :       char* newStr;
     626             :       // XXX We should use a strtok function that tokenizes PRUnichars
     627             :       // so that we don't have to convert from Unicode to ASCII and then back
     628             : 
     629           6 :       char* token = nsCRT::strtok( str, ", ", &newStr );
     630          58 :       while( token != nullptr ) {
     631             :         // Build an atom out of this attribute.
     632          52 :         nsCOMPtr<nsIAtom> atom;
     633          26 :         int32_t atomNsID = kNameSpaceID_None;
     634          52 :         nsCOMPtr<nsIAtom> attribute;
     635          26 :         int32_t attributeNsID = kNameSpaceID_None;
     636             : 
     637             :         // Figure out if this token contains a :.
     638          52 :         nsAutoString attrTok; attrTok.AssignWithConversion(token);
     639          26 :         int32_t index = attrTok.Find("=", true);
     640             :         nsresult rv;
     641          26 :         if (index != -1) {
     642             :           // This attribute maps to something different.
     643          14 :           nsAutoString left, right;
     644           7 :           attrTok.Left(left, index);
     645           7 :           attrTok.Right(right, attrTok.Length()-index-1);
     646             : 
     647           7 :           rv = nsContentUtils::SplitQName(aElement, left, &attributeNsID,
     648          14 :                                           getter_AddRefs(attribute));
     649           7 :           if (NS_FAILED(rv))
     650           0 :             return;
     651             : 
     652           7 :           rv = nsContentUtils::SplitQName(aElement, right, &atomNsID,
     653          14 :                                           getter_AddRefs(atom));
     654           7 :           if (NS_FAILED(rv))
     655           0 :             return;
     656             :         }
     657             :         else {
     658          38 :           nsAutoString tok;
     659          19 :           tok.AssignWithConversion(token);
     660          19 :           rv = nsContentUtils::SplitQName(aElement, tok, &atomNsID,
     661          38 :                                           getter_AddRefs(atom));
     662          19 :           if (NS_FAILED(rv))
     663           0 :             return;
     664          19 :           attribute = atom;
     665          19 :           attributeNsID = atomNsID;
     666             :         }
     667             : 
     668          26 :         AddToAttributeTable(atomNsID, atom, attributeNsID, attribute, aElement);
     669             : 
     670             :         // Now remove the inherits attribute from the element so that it doesn't
     671             :         // show up on clones of the element.  It is used
     672             :         // by the template only, and we don't need it anymore.
     673             :         // XXXdwh Don't do this for XUL elements, since it faults them into heavyweight
     674             :         // elements. Should nuke from the prototype instead.
     675             :         // aElement->UnsetAttr(kNameSpaceID_XBL, nsGkAtoms::inherits, false);
     676             : 
     677          26 :         token = nsCRT::strtok( newStr, ", ", &newStr );
     678             :       }
     679             : 
     680           6 :       free(str);
     681             :     }
     682             :   }
     683             : 
     684             :   // Recur into our children.
     685          13 :   for (nsIContent* child = aElement->GetFirstChild();
     686          13 :        child;
     687           6 :        child = child->GetNextSibling()) {
     688           6 :     ConstructAttributeTable(child);
     689             :   }
     690             : }
     691             : 
     692             : nsresult
     693           0 : nsXBLPrototypeBinding::ConstructInterfaceTable(const nsAString& aImpls)
     694             : {
     695           0 :   if (!aImpls.IsEmpty()) {
     696             :     // Obtain the interface info manager that can tell us the IID
     697             :     // for a given interface name.
     698             :     nsCOMPtr<nsIInterfaceInfoManager>
     699           0 :       infoManager(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
     700           0 :     if (!infoManager)
     701           0 :       return NS_ERROR_FAILURE;
     702             : 
     703             :     // The user specified at least one attribute.
     704           0 :     NS_ConvertUTF16toUTF8 utf8impl(aImpls);
     705           0 :     char* str = utf8impl.BeginWriting();
     706             :     char* newStr;
     707             :     // XXX We should use a strtok function that tokenizes PRUnichars
     708             :     // so that we don't have to convert from Unicode to ASCII and then back
     709             : 
     710           0 :     char* token = nsCRT::strtok( str, ", ", &newStr );
     711           0 :     while( token != nullptr ) {
     712             :       // get the InterfaceInfo for the name
     713           0 :       nsCOMPtr<nsIInterfaceInfo> iinfo;
     714           0 :       infoManager->GetInfoForName(token, getter_AddRefs(iinfo));
     715             : 
     716           0 :       if (iinfo) {
     717             :         // obtain an IID.
     718           0 :         const nsIID* iid = nullptr;
     719           0 :         iinfo->GetIIDShared(&iid);
     720             : 
     721           0 :         if (iid) {
     722             :           // We found a valid iid.  Add it to our table.
     723           0 :           mInterfaceTable.Put(*iid, mBinding);
     724             : 
     725             :           // this block adds the parent interfaces of each interface
     726             :           // defined in the xbl definition (implements="nsI...")
     727           0 :           nsCOMPtr<nsIInterfaceInfo> parentInfo;
     728             :           // if it has a parent, add it to the table
     729           0 :           while (NS_SUCCEEDED(iinfo->GetParent(getter_AddRefs(parentInfo))) && parentInfo) {
     730             :             // get the iid
     731           0 :             parentInfo->GetIIDShared(&iid);
     732             : 
     733             :             // don't add nsISupports to the table
     734           0 :             if (!iid || iid->Equals(NS_GET_IID(nsISupports)))
     735           0 :               break;
     736             : 
     737             :             // add the iid to the table
     738           0 :             mInterfaceTable.Put(*iid, mBinding);
     739             : 
     740             :             // look for the next parent
     741           0 :             iinfo = parentInfo;
     742             :           }
     743             :         }
     744             :       }
     745             : 
     746           0 :       token = nsCRT::strtok( newStr, ", ", &newStr );
     747             :     }
     748             :   }
     749             : 
     750           0 :   return NS_OK;
     751             : }
     752             : 
     753             : nsresult
     754           0 : nsXBLPrototypeBinding::AddResourceListener(nsIContent* aBoundElement)
     755             : {
     756           0 :   if (!mResources)
     757           0 :     return NS_ERROR_FAILURE; // Makes no sense to add a listener when the binding
     758             :                              // has no resources.
     759             : 
     760           0 :   mResources->AddResourceListener(aBoundElement);
     761           0 :   return NS_OK;
     762             : }
     763             : 
     764             : void
     765          36 : nsXBLPrototypeBinding::CreateKeyHandlers()
     766             : {
     767          36 :   nsXBLPrototypeHandler* curr = mPrototypeHandler;
     768         374 :   while (curr) {
     769         338 :     nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
     770         506 :     if (eventAtom == nsGkAtoms::keyup ||
     771         329 :         eventAtom == nsGkAtoms::keydown ||
     772         160 :         eventAtom == nsGkAtoms::keypress) {
     773          36 :       uint8_t phase = curr->GetPhase();
     774          36 :       uint8_t type = curr->GetType();
     775             : 
     776          36 :       int32_t count = mKeyHandlers.Count();
     777             :       int32_t i;
     778          36 :       nsXBLKeyEventHandler* handler = nullptr;
     779          37 :       for (i = 0; i < count; ++i) {
     780          27 :         handler = mKeyHandlers[i];
     781          27 :         if (handler->Matches(eventAtom, phase, type))
     782          26 :           break;
     783             :       }
     784             : 
     785          36 :       if (i == count) {
     786             :         RefPtr<nsXBLKeyEventHandler> newHandler =
     787          30 :           new nsXBLKeyEventHandler(eventAtom, phase, type);
     788          10 :         mKeyHandlers.AppendObject(newHandler);
     789          10 :         handler = newHandler;
     790             :       }
     791             : 
     792          36 :       if (handler)
     793          36 :         handler->AddProtoHandler(curr);
     794             :     }
     795             : 
     796         169 :     curr = curr->GetNextHandler();
     797             :   }
     798          36 : }
     799             : 
     800             : class XBLPrototypeSetupCleanup
     801             : {
     802             : public:
     803         142 :   XBLPrototypeSetupCleanup(nsXBLDocumentInfo* aDocInfo, const nsACString& aID)
     804         142 :   : mDocInfo(aDocInfo), mID(aID) {}
     805             : 
     806         142 :   ~XBLPrototypeSetupCleanup()
     807         142 :   {
     808         142 :     if (mDocInfo) {
     809           0 :       mDocInfo->RemovePrototypeBinding(mID);
     810             :     }
     811         142 :   }
     812             : 
     813         142 :   void Disconnect()
     814             :   {
     815         142 :     mDocInfo = nullptr;
     816         142 :   }
     817             : 
     818             :   nsXBLDocumentInfo* mDocInfo;
     819             :   nsAutoCString mID;
     820             : };
     821             : 
     822             : nsresult
     823         142 : nsXBLPrototypeBinding::Read(nsIObjectInputStream* aStream,
     824             :                             nsXBLDocumentInfo* aDocInfo,
     825             :                             nsIDocument* aDocument,
     826             :                             uint8_t aFlags)
     827             : {
     828         142 :   mInheritStyle = (aFlags & XBLBinding_Serialize_InheritStyle) ? true : false;
     829         142 :   mChromeOnlyContent =
     830         142 :     (aFlags & XBLBinding_Serialize_ChromeOnlyContent) ? true : false;
     831         142 :   mBindToUntrustedContent =
     832         142 :     (aFlags & XBLBinding_Serialize_BindToUntrustedContent) ? true : false;
     833             : 
     834             :   // nsXBLContentSink::ConstructBinding doesn't create a binding with an empty
     835             :   // id, so we don't here either.
     836         284 :   nsAutoCString id;
     837         142 :   nsresult rv = aStream->ReadCString(id);
     838             : 
     839         142 :   NS_ENSURE_SUCCESS(rv, rv);
     840         142 :   NS_ENSURE_TRUE(!id.IsEmpty(), NS_ERROR_FAILURE);
     841             : 
     842         284 :   nsAutoCString baseBindingURI;
     843         142 :   rv = aStream->ReadCString(baseBindingURI);
     844         142 :   NS_ENSURE_SUCCESS(rv, rv);
     845         142 :   mCheckedBaseProto = true;
     846             : 
     847         142 :   if (!baseBindingURI.IsEmpty()) {
     848         102 :     rv = NS_NewURI(getter_AddRefs(mBaseBindingURI), baseBindingURI);
     849         102 :     NS_ENSURE_SUCCESS(rv, rv);
     850             :   }
     851             : 
     852         142 :   rv = ReadNamespace(aStream, mBaseNameSpaceID);
     853         142 :   NS_ENSURE_SUCCESS(rv, rv);
     854             : 
     855         284 :   nsAutoString baseTag;
     856         142 :   rv = aStream->ReadString(baseTag);
     857         142 :   NS_ENSURE_SUCCESS(rv, rv);
     858         142 :   if (!baseTag.IsEmpty()) {
     859          29 :     mBaseTag = NS_Atomize(baseTag);
     860             :   }
     861             : 
     862         426 :   mBinding = aDocument->CreateElem(NS_LITERAL_STRING("binding"), nullptr,
     863         426 :                                    kNameSpaceID_XBL);
     864             : 
     865         284 :   nsCOMPtr<nsIContent> child;
     866         142 :   rv = ReadContentNode(aStream, aDocument, aDocument->NodeInfoManager(), getter_AddRefs(child));
     867         142 :   NS_ENSURE_SUCCESS(rv, rv);
     868             : 
     869         142 :   Element* rootElement = aDocument->GetRootElement();
     870         142 :   if (rootElement)
     871         142 :     rootElement->AppendChildTo(mBinding, false);
     872             : 
     873         142 :   if (child) {
     874          79 :     mBinding->AppendChildTo(child, false);
     875             :   }
     876             : 
     877             :   uint32_t interfaceCount;
     878         142 :   rv = aStream->Read32(&interfaceCount);
     879         142 :   NS_ENSURE_SUCCESS(rv, rv);
     880             : 
     881         264 :   for (; interfaceCount > 0; interfaceCount--) {
     882             :     nsIID iid;
     883          61 :     rv = aStream->ReadID(&iid);
     884          61 :     NS_ENSURE_SUCCESS(rv, rv);
     885          61 :     mInterfaceTable.Put(iid, mBinding);
     886             :   }
     887             : 
     888             :   // We're not directly using this AutoJSAPI here, but callees use it via
     889             :   // AutoJSContext.
     890         284 :   AutoJSAPI jsapi;
     891         142 :   if (!jsapi.Init(xpc::CompilationScope())) {
     892           0 :     return NS_ERROR_UNEXPECTED;
     893             :   }
     894             : 
     895         142 :   bool isFirstBinding = aFlags & XBLBinding_Serialize_IsFirstBinding;
     896         142 :   rv = Init(id, aDocInfo, nullptr, isFirstBinding);
     897         142 :   NS_ENSURE_SUCCESS(rv, rv);
     898             : 
     899             :   // We need to set the prototype binding before reading the nsXBLProtoImpl,
     900             :   // as it may be retrieved within.
     901         142 :   rv = aDocInfo->SetPrototypeBinding(id, this);
     902         142 :   NS_ENSURE_SUCCESS(rv, rv);
     903             : 
     904         284 :   XBLPrototypeSetupCleanup cleanup(aDocInfo, id);
     905             : 
     906         284 :   nsAutoCString className;
     907         142 :   rv = aStream->ReadCString(className);
     908         142 :   NS_ENSURE_SUCCESS(rv, rv);
     909             : 
     910         142 :   if (!className.IsEmpty()) {
     911             :     nsXBLProtoImpl* impl; // NS_NewXBLProtoImpl will set mImplementation for us
     912          83 :     NS_NewXBLProtoImpl(this, NS_ConvertUTF8toUTF16(className).get(), &impl);
     913             : 
     914             :     // This needs to happen after SetPrototypeBinding as calls are made to
     915             :     // retrieve the mapped bindings from within here. However, if an error
     916             :     // occurs, the mapping should be removed again so that we don't keep an
     917             :     // invalid binding around.
     918          83 :     rv = mImplementation->Read(aStream, this);
     919          83 :     NS_ENSURE_SUCCESS(rv, rv);
     920             :   }
     921             : 
     922             :   // Next read in the handlers.
     923         142 :   nsXBLPrototypeHandler* previousHandler = nullptr;
     924             : 
     925             :   do {
     926             :     XBLBindingSerializeDetails type;
     927         422 :     rv = aStream->Read8(&type);
     928         422 :     NS_ENSURE_SUCCESS(rv, rv);
     929             : 
     930         422 :     if (type == XBLBinding_Serialize_NoMoreItems)
     931         142 :       break;
     932             : 
     933         280 :     NS_ASSERTION((type & XBLBinding_Serialize_Mask) == XBLBinding_Serialize_Handler,
     934             :                  "invalid handler type");
     935             : 
     936         280 :     nsXBLPrototypeHandler* handler = new nsXBLPrototypeHandler(this);
     937         280 :     rv = handler->Read(aStream);
     938         280 :     if (NS_FAILED(rv)) {
     939           0 :       delete handler;
     940           0 :       return rv;
     941             :     }
     942             : 
     943         280 :     if (previousHandler) {
     944         226 :       previousHandler->SetNextHandler(handler);
     945             :     }
     946             :     else {
     947          54 :       SetPrototypeHandlers(handler);
     948             :     }
     949         280 :     previousHandler = handler;
     950             :   } while (1);
     951             : 
     952         142 :   if (mBinding) {
     953             :     while (true) {
     954             :       XBLBindingSerializeDetails type;
     955         185 :       rv = aStream->Read8(&type);
     956         185 :       NS_ENSURE_SUCCESS(rv, rv);
     957             : 
     958         185 :       if (type != XBLBinding_Serialize_Attribute) {
     959         142 :         break;
     960             :       }
     961             : 
     962             :       int32_t attrNamespace;
     963          43 :       rv = ReadNamespace(aStream, attrNamespace);
     964          43 :       NS_ENSURE_SUCCESS(rv, rv);
     965             : 
     966          86 :       nsAutoString attrPrefix, attrName, attrValue;
     967          43 :       rv = aStream->ReadString(attrPrefix);
     968          43 :       NS_ENSURE_SUCCESS(rv, rv);
     969             : 
     970          43 :       rv = aStream->ReadString(attrName);
     971          43 :       NS_ENSURE_SUCCESS(rv, rv);
     972             : 
     973          43 :       rv = aStream->ReadString(attrValue);
     974          43 :       NS_ENSURE_SUCCESS(rv, rv);
     975             : 
     976          86 :       nsCOMPtr<nsIAtom> atomPrefix = NS_Atomize(attrPrefix);
     977          86 :       nsCOMPtr<nsIAtom> atomName = NS_Atomize(attrName);
     978          43 :       mBinding->SetAttr(attrNamespace, atomName, atomPrefix, attrValue, false);
     979          43 :     }
     980             :   }
     981             : 
     982             :   // Finally, read in the resources.
     983             :   while (true) {
     984             :     XBLBindingSerializeDetails type;
     985         181 :     rv = aStream->Read8(&type);
     986         181 :     NS_ENSURE_SUCCESS(rv, rv);
     987             : 
     988         181 :     if (type == XBLBinding_Serialize_NoMoreItems)
     989         142 :       break;
     990             : 
     991          39 :     NS_ASSERTION((type & XBLBinding_Serialize_Mask) == XBLBinding_Serialize_Stylesheet ||
     992             :                  (type & XBLBinding_Serialize_Mask) == XBLBinding_Serialize_Image, "invalid resource type");
     993             : 
     994          78 :     nsAutoString src;
     995          39 :     rv = aStream->ReadString(src);
     996          39 :     NS_ENSURE_SUCCESS(rv, rv);
     997             : 
     998          39 :     AddResource(type == XBLBinding_Serialize_Stylesheet ? nsGkAtoms::stylesheet :
     999          39 :                                                           nsGkAtoms::image, src);
    1000          39 :   }
    1001             : 
    1002         142 :   if (isFirstBinding) {
    1003          25 :     aDocInfo->SetFirstPrototypeBinding(this);
    1004             :   }
    1005             : 
    1006         142 :   cleanup.Disconnect();
    1007         142 :   return NS_OK;
    1008             : }
    1009             : 
    1010             : // static
    1011             : nsresult
    1012         142 : nsXBLPrototypeBinding::ReadNewBinding(nsIObjectInputStream* aStream,
    1013             :                                       nsXBLDocumentInfo* aDocInfo,
    1014             :                                       nsIDocument* aDocument,
    1015             :                                       uint8_t aFlags)
    1016             : {
    1017             :   // If the Read() succeeds, |binding| will end up being owned by aDocInfo's
    1018             :   // binding table. Otherwise, we must manually delete it.
    1019         142 :   nsXBLPrototypeBinding* binding = new nsXBLPrototypeBinding();
    1020         142 :   nsresult rv = binding->Read(aStream, aDocInfo, aDocument, aFlags);
    1021         142 :   if (NS_FAILED(rv)) {
    1022           0 :     delete binding;
    1023             :   }
    1024         142 :   return rv;
    1025             : }
    1026             : 
    1027             : nsresult
    1028           0 : nsXBLPrototypeBinding::Write(nsIObjectOutputStream* aStream)
    1029             : {
    1030             :   // This writes out the binding. Note that mCheckedBaseProto,
    1031             :   // mKeyHandlersRegistered and mKeyHandlers are not serialized as they are
    1032             :   // computed on demand.
    1033             : 
    1034             :   // We're not directly using this AutoJSAPI here, but callees use it via
    1035             :   // AutoJSContext.
    1036           0 :   AutoJSAPI jsapi;
    1037           0 :   if (!jsapi.Init(xpc::CompilationScope())) {
    1038           0 :     return NS_ERROR_UNEXPECTED;
    1039             :   }
    1040             : 
    1041           0 :   uint8_t flags = mInheritStyle ? XBLBinding_Serialize_InheritStyle : 0;
    1042             : 
    1043             :   // mAlternateBindingURI is only set on the first binding.
    1044           0 :   if (mAlternateBindingURI) {
    1045           0 :     flags |= XBLBinding_Serialize_IsFirstBinding;
    1046             :   }
    1047             : 
    1048           0 :   if (mChromeOnlyContent) {
    1049           0 :     flags |= XBLBinding_Serialize_ChromeOnlyContent;
    1050             :   }
    1051             : 
    1052           0 :   if (mBindToUntrustedContent) {
    1053           0 :     flags |= XBLBinding_Serialize_BindToUntrustedContent;
    1054             :   }
    1055             : 
    1056           0 :   nsresult rv = aStream->Write8(flags);
    1057           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1058             : 
    1059           0 :   nsAutoCString id;
    1060           0 :   mBindingURI->GetRef(id);
    1061           0 :   rv = aStream->WriteStringZ(id.get());
    1062           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1063             : 
    1064             :   // write out the extends and display attribute values
    1065           0 :   nsAutoCString extends;
    1066           0 :   ResolveBaseBinding();
    1067           0 :   if (mBaseBindingURI) {
    1068           0 :     rv = mBaseBindingURI->GetSpec(extends);
    1069           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1070             :   }
    1071             : 
    1072           0 :   rv = aStream->WriteStringZ(extends.get());
    1073           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1074             : 
    1075           0 :   rv = WriteNamespace(aStream, mBaseNameSpaceID);
    1076           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1077             : 
    1078           0 :   nsAutoString baseTag;
    1079           0 :   if (mBaseTag) {
    1080           0 :     mBaseTag->ToString(baseTag);
    1081             :   }
    1082           0 :   rv = aStream->WriteWStringZ(baseTag.get());
    1083           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1084             : 
    1085           0 :   nsIContent* content = GetImmediateChild(nsGkAtoms::content);
    1086           0 :   if (content) {
    1087           0 :     rv = WriteContentNode(aStream, content);
    1088           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1089             :   }
    1090             :   else {
    1091             :     // Write a marker to indicate that there is no content.
    1092           0 :     rv = aStream->Write8(XBLBinding_Serialize_NoContent);
    1093           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1094             :   }
    1095             : 
    1096             :   // Enumerate and write out the implemented interfaces.
    1097           0 :   rv = aStream->Write32(mInterfaceTable.Count());
    1098           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1099             : 
    1100           0 :   for (auto iter = mInterfaceTable.Iter(); !iter.Done(); iter.Next()) {
    1101             :     // We can just write out the ids. The cache will be invalidated when a
    1102             :     // different build is used, so we don't need to worry about ids changing.
    1103           0 :     aStream->WriteID(iter.Key());
    1104             :   }
    1105             : 
    1106             :   // Write out the implementation details.
    1107           0 :   if (mImplementation) {
    1108           0 :     rv = mImplementation->Write(aStream, this);
    1109           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1110             :   }
    1111             :   else {
    1112             :     // Write out an empty classname. This indicates that the binding does not
    1113             :     // define an implementation.
    1114           0 :     rv = aStream->WriteUtf8Z(EmptyString().get());
    1115           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1116             :   }
    1117             : 
    1118             :   // Write out the handlers.
    1119           0 :   nsXBLPrototypeHandler* handler = mPrototypeHandler;
    1120           0 :   while (handler) {
    1121           0 :     rv = handler->Write(aStream);
    1122           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1123             : 
    1124           0 :     handler = handler->GetNextHandler();
    1125             :   }
    1126             : 
    1127           0 :   aStream->Write8(XBLBinding_Serialize_NoMoreItems);
    1128           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1129             : 
    1130           0 :   if (mBinding) {
    1131           0 :     uint32_t attributes = mBinding->GetAttrCount();
    1132           0 :     nsAutoString attrValue;
    1133           0 :     for (uint32_t i = 0; i < attributes; ++i) {
    1134           0 :       BorrowedAttrInfo attrInfo = mBinding->GetAttrInfoAt(i);
    1135           0 :       const nsAttrName* name = attrInfo.mName;
    1136           0 :       nsDependentAtomString attrName(attrInfo.mName->LocalName());
    1137           0 :       attrInfo.mValue->ToString(attrValue);
    1138             : 
    1139           0 :       rv = aStream->Write8(XBLBinding_Serialize_Attribute);
    1140           0 :       NS_ENSURE_SUCCESS(rv, rv);
    1141             : 
    1142           0 :       rv = WriteNamespace(aStream, name->NamespaceID());
    1143           0 :       NS_ENSURE_SUCCESS(rv, rv);
    1144             : 
    1145           0 :       nsIAtom* prefix = name->GetPrefix();
    1146           0 :       nsAutoString prefixString;
    1147           0 :       if (prefix) {
    1148           0 :         prefix->ToString(prefixString);
    1149             :       }
    1150             : 
    1151           0 :       rv = aStream->WriteWStringZ(prefixString.get());
    1152           0 :       NS_ENSURE_SUCCESS(rv, rv);
    1153             : 
    1154           0 :       rv = aStream->WriteWStringZ(attrName.get());
    1155           0 :       NS_ENSURE_SUCCESS(rv, rv);
    1156             : 
    1157           0 :       rv = aStream->WriteWStringZ(attrValue.get());
    1158           0 :       NS_ENSURE_SUCCESS(rv, rv);
    1159             :     }
    1160             :   }
    1161             : 
    1162           0 :   aStream->Write8(XBLBinding_Serialize_NoMoreItems);
    1163           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1164             : 
    1165             :   // Write out the resources
    1166           0 :   if (mResources) {
    1167           0 :     rv = mResources->Write(aStream);
    1168           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1169             :   }
    1170             : 
    1171             :   // Write out an end mark at the end.
    1172           0 :   return aStream->Write8(XBLBinding_Serialize_NoMoreItems);
    1173             : }
    1174             : 
    1175             : nsresult
    1176         657 : nsXBLPrototypeBinding::ReadContentNode(nsIObjectInputStream* aStream,
    1177             :                                        nsIDocument* aDocument,
    1178             :                                        nsNodeInfoManager* aNim,
    1179             :                                        nsIContent** aContent)
    1180             : {
    1181         657 :   *aContent = nullptr;
    1182             : 
    1183             :   int32_t namespaceID;
    1184         657 :   nsresult rv = ReadNamespace(aStream, namespaceID);
    1185         657 :   NS_ENSURE_SUCCESS(rv, rv);
    1186             : 
    1187             :   // There is no content to read so just return.
    1188         657 :   if (namespaceID == XBLBinding_Serialize_NoContent)
    1189          63 :     return NS_OK;
    1190             : 
    1191        1188 :   nsCOMPtr<nsIContent> content;
    1192             : 
    1193             :   // If this is a text type, just read the string and return.
    1194        1155 :   if (namespaceID == XBLBinding_Serialize_TextNode ||
    1195        1122 :       namespaceID == XBLBinding_Serialize_CDATANode ||
    1196         561 :       namespaceID == XBLBinding_Serialize_CommentNode) {
    1197          41 :     switch (namespaceID) {
    1198             :       case XBLBinding_Serialize_TextNode:
    1199          33 :         content = new nsTextNode(aNim);
    1200          33 :         break;
    1201             :       case XBLBinding_Serialize_CDATANode:
    1202           0 :         content = new CDATASection(aNim);
    1203           0 :         break;
    1204             :       case XBLBinding_Serialize_CommentNode:
    1205           8 :         content = new Comment(aNim);
    1206           8 :         break;
    1207             :       default:
    1208           0 :         break;
    1209             :     }
    1210             : 
    1211          82 :     nsAutoString text;
    1212          41 :     rv = aStream->ReadString(text);
    1213          41 :     NS_ENSURE_SUCCESS(rv, rv);
    1214             : 
    1215          41 :     content->SetText(text, false);
    1216          41 :     content.swap(*aContent);
    1217          41 :     return NS_OK;
    1218             :   }
    1219             : 
    1220             :   // Otherwise, it's an element, so read its tag, attributes and children.
    1221        1106 :   nsAutoString prefix, tag;
    1222         553 :   rv = aStream->ReadString(prefix);
    1223         553 :   NS_ENSURE_SUCCESS(rv, rv);
    1224             : 
    1225        1106 :   nsCOMPtr<nsIAtom> prefixAtom;
    1226         553 :   if (!prefix.IsEmpty())
    1227         403 :     prefixAtom = NS_Atomize(prefix);
    1228             : 
    1229         553 :   rv = aStream->ReadString(tag);
    1230         553 :   NS_ENSURE_SUCCESS(rv, rv);
    1231             : 
    1232        1106 :   nsCOMPtr<nsIAtom> tagAtom = NS_Atomize(tag);
    1233             :   RefPtr<NodeInfo> nodeInfo =
    1234        1106 :     aNim->GetNodeInfo(tagAtom, prefixAtom, namespaceID, nsIDOMNode::ELEMENT_NODE);
    1235             : 
    1236             :   uint32_t attrCount;
    1237         553 :   rv = aStream->Read32(&attrCount);
    1238         553 :   NS_ENSURE_SUCCESS(rv, rv);
    1239             : 
    1240             :   // Create XUL prototype elements, or regular elements for other namespaces.
    1241             :   // This needs to match the code in nsXBLContentSink::CreateElement.
    1242             : #ifdef MOZ_XUL
    1243         553 :   if (namespaceID == kNameSpaceID_XUL) {
    1244         393 :     nsIURI* documentURI = aDocument->GetDocumentURI();
    1245             : 
    1246         786 :     RefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement();
    1247             : 
    1248         393 :     prototype->mNodeInfo = nodeInfo;
    1249             : 
    1250         393 :     nsXULPrototypeAttribute* attrs = nullptr;
    1251         393 :     if (attrCount > 0) {
    1252         756 :       attrs = new nsXULPrototypeAttribute[attrCount];
    1253             :     }
    1254             : 
    1255         393 :     prototype->mAttributes = attrs;
    1256         393 :     prototype->mNumAttributes = attrCount;
    1257             : 
    1258        1503 :     for (uint32_t i = 0; i < attrCount; i++) {
    1259        1110 :       rv = ReadNamespace(aStream, namespaceID);
    1260        1110 :       NS_ENSURE_SUCCESS(rv, rv);
    1261             : 
    1262        2220 :       nsAutoString prefix, name, val;
    1263        1110 :       rv = aStream->ReadString(prefix);
    1264        1110 :       NS_ENSURE_SUCCESS(rv, rv);
    1265        1110 :       rv = aStream->ReadString(name);
    1266        1110 :       NS_ENSURE_SUCCESS(rv, rv);
    1267        1110 :       rv = aStream->ReadString(val);
    1268        1110 :       NS_ENSURE_SUCCESS(rv, rv);
    1269             : 
    1270        2220 :       nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(name);
    1271        1110 :       if (namespaceID == kNameSpaceID_None) {
    1272         906 :         attrs[i].mName.SetTo(nameAtom);
    1273             :       }
    1274             :       else {
    1275         408 :         nsCOMPtr<nsIAtom> prefixAtom;
    1276         204 :         if (!prefix.IsEmpty())
    1277         204 :           prefixAtom = NS_Atomize(prefix);
    1278             : 
    1279             :         RefPtr<NodeInfo> ni =
    1280         408 :           aNim->GetNodeInfo(nameAtom, prefixAtom,
    1281         408 :                             namespaceID, nsIDOMNode::ATTRIBUTE_NODE);
    1282         204 :         attrs[i].mName.SetTo(ni);
    1283             :       }
    1284             : 
    1285        1110 :       rv = prototype->SetAttrAt(i, val, documentURI);
    1286        1110 :       NS_ENSURE_SUCCESS(rv, rv);
    1287             :     }
    1288             : 
    1289         786 :     nsCOMPtr<Element> result;
    1290             :     nsresult rv =
    1291         393 :       nsXULElement::Create(prototype, aDocument, false, false, getter_AddRefs(result));
    1292         393 :     NS_ENSURE_SUCCESS(rv, rv);
    1293         393 :     content = result;
    1294             :   }
    1295             :   else {
    1296             : #endif
    1297         320 :     nsCOMPtr<Element> element;
    1298         160 :     NS_NewElement(getter_AddRefs(element), nodeInfo.forget(), NOT_FROM_PARSER);
    1299         160 :     content = element;
    1300             : 
    1301         262 :     for (uint32_t i = 0; i < attrCount; i++) {
    1302         102 :       rv = ReadNamespace(aStream, namespaceID);
    1303         102 :       NS_ENSURE_SUCCESS(rv, rv);
    1304             : 
    1305         204 :       nsAutoString prefix, name, val;
    1306         102 :       rv = aStream->ReadString(prefix);
    1307         102 :       NS_ENSURE_SUCCESS(rv, rv);
    1308         102 :       rv = aStream->ReadString(name);
    1309         102 :       NS_ENSURE_SUCCESS(rv, rv);
    1310         102 :       rv = aStream->ReadString(val);
    1311         102 :       NS_ENSURE_SUCCESS(rv, rv);
    1312             : 
    1313         204 :       nsCOMPtr<nsIAtom> prefixAtom;
    1314         102 :       if (!prefix.IsEmpty())
    1315           6 :         prefixAtom = NS_Atomize(prefix);
    1316             : 
    1317         204 :       nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(name);
    1318         102 :       content->SetAttr(namespaceID, nameAtom, prefixAtom, val, false);
    1319             :     }
    1320             : 
    1321             : #ifdef MOZ_XUL
    1322             :   }
    1323             : #endif
    1324             : 
    1325             :   // Now read the attribute forwarding entries (xbl:inherits)
    1326             : 
    1327             :   int32_t srcNamespaceID, destNamespaceID;
    1328         553 :   rv = ReadNamespace(aStream, srcNamespaceID);
    1329         553 :   NS_ENSURE_SUCCESS(rv, rv);
    1330             : 
    1331        1771 :   while (srcNamespaceID != XBLBinding_Serialize_NoMoreAttributes) {
    1332        1218 :     nsAutoString srcAttribute, destAttribute;
    1333         609 :     rv = aStream->ReadString(srcAttribute);
    1334         609 :     NS_ENSURE_SUCCESS(rv, rv);
    1335         609 :     rv = ReadNamespace(aStream, destNamespaceID);
    1336         609 :     NS_ENSURE_SUCCESS(rv, rv);
    1337         609 :     rv = aStream->ReadString(destAttribute);
    1338         609 :     NS_ENSURE_SUCCESS(rv, rv);
    1339             : 
    1340        1218 :     nsCOMPtr<nsIAtom> srcAtom = NS_Atomize(srcAttribute);
    1341        1218 :     nsCOMPtr<nsIAtom> destAtom = NS_Atomize(destAttribute);
    1342             : 
    1343         609 :     EnsureAttributeTable();
    1344         609 :     AddToAttributeTable(srcNamespaceID, srcAtom, destNamespaceID, destAtom, content);
    1345             : 
    1346         609 :     rv = ReadNamespace(aStream, srcNamespaceID);
    1347         609 :     NS_ENSURE_SUCCESS(rv, rv);
    1348             :   }
    1349             : 
    1350             :   // Finally, read in the child nodes.
    1351             :   uint32_t childCount;
    1352         553 :   rv = aStream->Read32(&childCount);
    1353         553 :   NS_ENSURE_SUCCESS(rv, rv);
    1354             : 
    1355        1068 :   for (uint32_t i = 0; i < childCount; i++) {
    1356        1030 :     nsCOMPtr<nsIContent> child;
    1357         515 :     ReadContentNode(aStream, aDocument, aNim, getter_AddRefs(child));
    1358             : 
    1359             :     // Child may be null if this was a comment for example and can just be ignored.
    1360         515 :     if (child) {
    1361         515 :       content->AppendChildTo(child, false);
    1362             :     }
    1363             :   }
    1364             : 
    1365         553 :   content.swap(*aContent);
    1366         553 :   return NS_OK;
    1367             : }
    1368             : 
    1369             : nsresult
    1370           0 : nsXBLPrototypeBinding::WriteContentNode(nsIObjectOutputStream* aStream,
    1371             :                                         nsIContent* aNode)
    1372             : {
    1373             :   nsresult rv;
    1374             : 
    1375           0 :   if (!aNode->IsElement()) {
    1376             :     // Text is writen out as a single byte for the type, followed by the text.
    1377           0 :     uint8_t type = XBLBinding_Serialize_NoContent;
    1378           0 :     switch (aNode->NodeType()) {
    1379             :       case nsIDOMNode::TEXT_NODE:
    1380           0 :         type = XBLBinding_Serialize_TextNode;
    1381           0 :         break;
    1382             :       case nsIDOMNode::CDATA_SECTION_NODE:
    1383           0 :         type = XBLBinding_Serialize_CDATANode;
    1384           0 :         break;
    1385             :       case nsIDOMNode::COMMENT_NODE:
    1386           0 :         type = XBLBinding_Serialize_CommentNode;
    1387           0 :         break;
    1388             :       default:
    1389           0 :         break;
    1390             :     }
    1391             : 
    1392           0 :     rv = aStream->Write8(type);
    1393           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1394             : 
    1395           0 :     nsAutoString content;
    1396           0 :     aNode->GetText()->AppendTo(content);
    1397           0 :     return aStream->WriteWStringZ(content.get());
    1398             :   }
    1399             : 
    1400             :   // Otherwise, this is an element.
    1401             : 
    1402             :   // Write the namespace id followed by the tag name
    1403           0 :   rv = WriteNamespace(aStream, aNode->GetNameSpaceID());
    1404           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1405             : 
    1406           0 :   nsAutoString prefixStr;
    1407           0 :   aNode->NodeInfo()->GetPrefix(prefixStr);
    1408           0 :   rv = aStream->WriteWStringZ(prefixStr.get());
    1409           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1410             : 
    1411           0 :   rv = aStream->WriteWStringZ(nsDependentAtomString(aNode->NodeInfo()->NameAtom()).get());
    1412           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1413             : 
    1414             :   // Write attributes
    1415           0 :   uint32_t count = aNode->GetAttrCount();
    1416           0 :   rv = aStream->Write32(count);
    1417           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1418             : 
    1419             :   uint32_t i;
    1420           0 :   for (i = 0; i < count; i++) {
    1421             :     // Write out the namespace id, the namespace prefix, the local tag name,
    1422             :     // and the value, in that order.
    1423             : 
    1424           0 :     const BorrowedAttrInfo attrInfo = aNode->GetAttrInfoAt(i);
    1425           0 :     const nsAttrName* name = attrInfo.mName;
    1426             : 
    1427             :     // XXXndeakin don't write out xbl:inherits?
    1428           0 :     int32_t namespaceID = name->NamespaceID();
    1429           0 :     rv = WriteNamespace(aStream, namespaceID);
    1430           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1431             : 
    1432           0 :     nsAutoString prefixStr;
    1433           0 :     nsIAtom* prefix = name->GetPrefix();
    1434           0 :     if (prefix)
    1435           0 :       prefix->ToString(prefixStr);
    1436           0 :     rv = aStream->WriteWStringZ(prefixStr.get());
    1437           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1438             : 
    1439           0 :     rv = aStream->WriteWStringZ(nsDependentAtomString(name->LocalName()).get());
    1440           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1441             : 
    1442           0 :     nsAutoString val;
    1443           0 :     attrInfo.mValue->ToString(val);
    1444           0 :     rv = aStream->WriteWStringZ(val.get());
    1445           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1446             :   }
    1447             : 
    1448             :   // Write out the attribute fowarding information
    1449           0 :   if (mAttributeTable) {
    1450           0 :     for (auto iter1 = mAttributeTable->Iter(); !iter1.Done(); iter1.Next()) {
    1451           0 :       int32_t srcNamespace = iter1.Key();
    1452           0 :       InnerAttributeTable* xblAttributes = iter1.UserData();
    1453             : 
    1454           0 :       for (auto iter2 = xblAttributes->Iter(); !iter2.Done(); iter2.Next()) {
    1455           0 :         nsXBLAttributeEntry* entry = iter2.UserData();
    1456             : 
    1457           0 :         do {
    1458           0 :           if (entry->GetElement() == aNode) {
    1459           0 :             WriteNamespace(aStream, srcNamespace);
    1460           0 :             aStream->WriteWStringZ(
    1461           0 :               nsDependentAtomString(entry->GetSrcAttribute()).get());
    1462           0 :             WriteNamespace(aStream, entry->GetDstNameSpace());
    1463           0 :             aStream->WriteWStringZ(
    1464           0 :               nsDependentAtomString(entry->GetDstAttribute()).get());
    1465             :           }
    1466             : 
    1467           0 :           entry = entry->GetNext();
    1468           0 :         } while (entry);
    1469             :       }
    1470             :     }
    1471             :   }
    1472           0 :   rv = aStream->Write8(XBLBinding_Serialize_NoMoreAttributes);
    1473           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1474             : 
    1475             :   // Finally, write out the child nodes.
    1476           0 :   count = aNode->GetChildCount();
    1477           0 :   rv = aStream->Write32(count);
    1478           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1479             : 
    1480           0 :   for (i = 0; i < count; i++) {
    1481           0 :     rv = WriteContentNode(aStream, aNode->GetChildAt(i));
    1482           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1483             :   }
    1484             : 
    1485           0 :   return NS_OK;
    1486             : }
    1487             : 
    1488             : nsresult
    1489        3825 : nsXBLPrototypeBinding::ReadNamespace(nsIObjectInputStream* aStream,
    1490             :                                      int32_t& aNameSpaceID)
    1491             : {
    1492             :   uint8_t namespaceID;
    1493        3825 :   nsresult rv = aStream->Read8(&namespaceID);
    1494        3825 :   NS_ENSURE_SUCCESS(rv, rv);
    1495             : 
    1496        3825 :   if (namespaceID == XBLBinding_Serialize_CustomNamespace) {
    1497           0 :     nsAutoString namesp;
    1498           0 :     rv = aStream->ReadString(namesp);
    1499           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1500             : 
    1501           0 :     nsContentUtils::NameSpaceManager()->RegisterNameSpace(namesp, aNameSpaceID);
    1502             :   }
    1503             :   else {
    1504        3825 :     aNameSpaceID = namespaceID;
    1505             :   }
    1506             : 
    1507        3825 :   return NS_OK;
    1508             : }
    1509             : 
    1510             : nsresult
    1511           0 : nsXBLPrototypeBinding::WriteNamespace(nsIObjectOutputStream* aStream,
    1512             :                                       int32_t aNameSpaceID)
    1513             : {
    1514             :   // Namespaces are stored as a single byte id for well-known namespaces.
    1515             :   // This saves time and space as other namespaces aren't very common in
    1516             :   // XBL. If another namespace is used however, the namespace id will be
    1517             :   // XBLBinding_Serialize_CustomNamespace and the string namespace written
    1518             :   // out directly afterwards.
    1519             :   nsresult rv;
    1520             : 
    1521           0 :   if (aNameSpaceID <= kNameSpaceID_LastBuiltin) {
    1522           0 :     rv = aStream->Write8((int8_t)aNameSpaceID);
    1523           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1524             :   }
    1525             :   else {
    1526           0 :     rv = aStream->Write8(XBLBinding_Serialize_CustomNamespace);
    1527           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1528             : 
    1529           0 :     nsAutoString namesp;
    1530           0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, namesp);
    1531           0 :     aStream->WriteWStringZ(namesp.get());
    1532             :   }
    1533             : 
    1534           0 :   return NS_OK;
    1535             : }
    1536             : 
    1537             : 
    1538           1 : bool CheckTagNameWhiteList(int32_t aNameSpaceID, nsIAtom *aTagName)
    1539             : {
    1540             :   static nsIContent::AttrValuesArray kValidXULTagNames[] =  {
    1541             :     &nsGkAtoms::autorepeatbutton, &nsGkAtoms::box, &nsGkAtoms::browser,
    1542             :     &nsGkAtoms::button, &nsGkAtoms::hbox, &nsGkAtoms::image, &nsGkAtoms::menu,
    1543             :     &nsGkAtoms::menubar, &nsGkAtoms::menuitem, &nsGkAtoms::menupopup,
    1544             :     &nsGkAtoms::row, &nsGkAtoms::slider, &nsGkAtoms::spacer,
    1545             :     &nsGkAtoms::splitter, &nsGkAtoms::text, &nsGkAtoms::tree, nullptr};
    1546             : 
    1547             :   uint32_t i;
    1548           1 :   if (aNameSpaceID == kNameSpaceID_XUL) {
    1549           4 :     for (i = 0; kValidXULTagNames[i]; ++i) {
    1550           4 :       if (aTagName == *(kValidXULTagNames[i])) {
    1551           1 :         return true;
    1552             :       }
    1553             :     }
    1554             :   }
    1555           0 :   else if (aNameSpaceID == kNameSpaceID_SVG &&
    1556           0 :            aTagName == nsGkAtoms::generic_) {
    1557           0 :     return true;
    1558             :   }
    1559             : 
    1560           0 :   return false;
    1561             : }
    1562             : 
    1563             : nsresult
    1564         633 : nsXBLPrototypeBinding::ResolveBaseBinding()
    1565             : {
    1566         633 :   if (mCheckedBaseProto)
    1567         630 :     return NS_OK;
    1568           3 :   mCheckedBaseProto = true;
    1569             : 
    1570           6 :   nsCOMPtr<nsIDocument> doc = mXBLDocInfoWeak->GetDocument();
    1571             : 
    1572             :   // Check for the presence of 'extends' and 'display' attributes
    1573           6 :   nsAutoString display, extends;
    1574           3 :   mBinding->GetAttr(kNameSpaceID_None, nsGkAtoms::extends, extends);
    1575           3 :   if (extends.IsEmpty())
    1576           1 :     return NS_OK;
    1577             : 
    1578           2 :   mBinding->GetAttr(kNameSpaceID_None, nsGkAtoms::display, display);
    1579           2 :   bool hasDisplay = !display.IsEmpty();
    1580             : 
    1581           4 :   nsAutoString value(extends);
    1582             : 
    1583             :   // Now slice 'em up to see what we've got.
    1584           4 :   nsAutoString prefix;
    1585             :   int32_t offset;
    1586           2 :   if (hasDisplay) {
    1587           0 :     offset = display.FindChar(':');
    1588           0 :     if (-1 != offset) {
    1589           0 :       display.Left(prefix, offset);
    1590           0 :       display.Cut(0, offset+1);
    1591             :     }
    1592             :   }
    1593             :   else {
    1594           2 :     offset = extends.FindChar(':');
    1595           2 :     if (-1 != offset) {
    1596           2 :       extends.Left(prefix, offset);
    1597           2 :       extends.Cut(0, offset+1);
    1598           2 :       display = extends;
    1599             :     }
    1600             :   }
    1601             : 
    1602           4 :   nsAutoString nameSpace;
    1603             : 
    1604           2 :   if (!prefix.IsEmpty()) {
    1605           2 :     mBinding->LookupNamespaceURI(prefix, nameSpace);
    1606           2 :     if (!nameSpace.IsEmpty()) {
    1607             :       int32_t nameSpaceID =
    1608           1 :         nsContentUtils::NameSpaceManager()->GetNameSpaceID(nameSpace,
    1609           2 :                                                            nsContentUtils::IsChromeDoc(doc));
    1610             : 
    1611           2 :       nsCOMPtr<nsIAtom> tagName = NS_Atomize(display);
    1612             :       // Check the white list
    1613           1 :       if (!CheckTagNameWhiteList(nameSpaceID, tagName)) {
    1614           0 :         const char16_t* params[] = { display.get() };
    1615           0 :         nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
    1616           0 :                                         NS_LITERAL_CSTRING("XBL"), nullptr,
    1617             :                                         nsContentUtils::eXBL_PROPERTIES,
    1618             :                                        "InvalidExtendsBinding",
    1619           0 :                                         params, ArrayLength(params),
    1620           0 :                                         doc->GetDocumentURI());
    1621           0 :         NS_ASSERTION(!nsXBLService::IsChromeOrResourceURI(doc->GetDocumentURI()),
    1622             :                      "Invalid extends value");
    1623           0 :         return NS_ERROR_ILLEGAL_VALUE;
    1624             :       }
    1625             : 
    1626           1 :       SetBaseTag(nameSpaceID, tagName);
    1627             :     }
    1628             :   }
    1629             : 
    1630           2 :   if (hasDisplay || nameSpace.IsEmpty()) {
    1631           1 :     mBinding->UnsetAttr(kNameSpaceID_None, nsGkAtoms::extends, false);
    1632           1 :     mBinding->UnsetAttr(kNameSpaceID_None, nsGkAtoms::display, false);
    1633             : 
    1634           2 :     return NS_NewURI(getter_AddRefs(mBaseBindingURI), value,
    1635             :                      doc->GetDocumentCharacterSet(),
    1636           1 :                      doc->GetDocBaseURI());
    1637             :   }
    1638             : 
    1639           1 :   return NS_OK;
    1640             : }
    1641             : 
    1642             : void
    1643          39 : nsXBLPrototypeBinding::EnsureResources()
    1644             : {
    1645          39 :   if (!mResources) {
    1646          30 :     mResources = new nsXBLPrototypeResources(this);
    1647             :   }
    1648          39 : }
    1649             : 
    1650             : void
    1651           0 : nsXBLPrototypeBinding::AppendStyleSheet(StyleSheet* aSheet)
    1652             : {
    1653           0 :   EnsureResources();
    1654           0 :   mResources->AppendStyleSheet(aSheet);
    1655           0 : }
    1656             : 
    1657             : void
    1658           0 : nsXBLPrototypeBinding::RemoveStyleSheet(StyleSheet* aSheet)
    1659             : {
    1660           0 :   if (!mResources) {
    1661           0 :     MOZ_ASSERT(false, "Trying to remove a sheet that does not exist.");
    1662             :     return;
    1663             :   }
    1664             : 
    1665           0 :   mResources->RemoveStyleSheet(aSheet);
    1666           0 : }
    1667             : void
    1668           0 : nsXBLPrototypeBinding::InsertStyleSheetAt(size_t aIndex, StyleSheet* aSheet)
    1669             : {
    1670           0 :   EnsureResources();
    1671           0 :   mResources->InsertStyleSheetAt(aIndex, aSheet);
    1672           0 : }
    1673             : 
    1674             : StyleSheet*
    1675           0 : nsXBLPrototypeBinding::StyleSheetAt(size_t aIndex) const
    1676             : {
    1677           0 :   MOZ_ASSERT(mResources);
    1678           0 :   return mResources->StyleSheetAt(aIndex);
    1679             : }
    1680             : 
    1681             : size_t
    1682           0 : nsXBLPrototypeBinding::SheetCount() const
    1683             : {
    1684           0 :   return mResources ? mResources->SheetCount() : 0;
    1685             : }
    1686             : 
    1687             : bool
    1688         439 : nsXBLPrototypeBinding::HasStyleSheets() const
    1689             : {
    1690         439 :   return mResources && mResources->HasStyleSheets();
    1691             : }
    1692             : 
    1693             : void
    1694           0 : nsXBLPrototypeBinding::AppendStyleSheetsTo(
    1695             :                                       nsTArray<StyleSheet*>& aResult) const
    1696             : {
    1697           0 :   if (mResources) {
    1698           0 :     mResources->AppendStyleSheetsTo(aResult);
    1699             :   }
    1700           0 : }

Generated by: LCOV version 1.13