1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/xbl/nsXBLPrototypeBinding.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1700 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/ArrayUtils.h" 1.10 + 1.11 +#include "nsCOMPtr.h" 1.12 +#include "nsIAtom.h" 1.13 +#include "nsIInputStream.h" 1.14 +#include "nsNameSpaceManager.h" 1.15 +#include "nsIURI.h" 1.16 +#include "nsIURL.h" 1.17 +#include "nsIChannel.h" 1.18 +#include "nsXPIDLString.h" 1.19 +#include "nsReadableUtils.h" 1.20 +#include "nsNetUtil.h" 1.21 +#include "plstr.h" 1.22 +#include "nsContentCreatorFunctions.h" 1.23 +#include "nsIDocument.h" 1.24 +#include "nsIXMLContentSink.h" 1.25 +#include "nsContentCID.h" 1.26 +#include "mozilla/dom/XMLDocument.h" 1.27 +#include "nsXBLService.h" 1.28 +#include "nsXBLBinding.h" 1.29 +#include "nsXBLPrototypeBinding.h" 1.30 +#include "nsXBLContentSink.h" 1.31 +#include "xptinfo.h" 1.32 +#include "nsIInterfaceInfoManager.h" 1.33 +#include "nsIDocumentObserver.h" 1.34 +#include "nsGkAtoms.h" 1.35 +#include "nsXBLProtoImpl.h" 1.36 +#include "nsCRT.h" 1.37 +#include "nsContentUtils.h" 1.38 +#include "nsTextFragment.h" 1.39 +#include "nsTextNode.h" 1.40 +#include "nsIInterfaceInfo.h" 1.41 +#include "nsIScriptError.h" 1.42 + 1.43 +#include "nsIStyleRuleProcessor.h" 1.44 +#include "nsXBLResourceLoader.h" 1.45 +#include "mozilla/dom/CDATASection.h" 1.46 +#include "mozilla/dom/Comment.h" 1.47 +#include "mozilla/dom/Element.h" 1.48 + 1.49 +#ifdef MOZ_XUL 1.50 +#include "nsXULElement.h" 1.51 +#endif 1.52 + 1.53 +using namespace mozilla; 1.54 +using namespace mozilla::dom; 1.55 + 1.56 +// Helper Classes ===================================================================== 1.57 + 1.58 +// nsXBLAttributeEntry and helpers. This class is used to efficiently handle 1.59 +// attribute changes in anonymous content. 1.60 + 1.61 +class nsXBLAttributeEntry { 1.62 +public: 1.63 + nsXBLAttributeEntry(nsIAtom* aSrcAtom, nsIAtom* aDstAtom, 1.64 + int32_t aDstNameSpace, nsIContent* aContent) 1.65 + : mElement(aContent), 1.66 + mSrcAttribute(aSrcAtom), 1.67 + mDstAttribute(aDstAtom), 1.68 + mDstNameSpace(aDstNameSpace), 1.69 + mNext(nullptr) { } 1.70 + 1.71 + ~nsXBLAttributeEntry() { 1.72 + NS_CONTENT_DELETE_LIST_MEMBER(nsXBLAttributeEntry, this, mNext); 1.73 + } 1.74 + 1.75 + nsIAtom* GetSrcAttribute() { return mSrcAttribute; } 1.76 + nsIAtom* GetDstAttribute() { return mDstAttribute; } 1.77 + int32_t GetDstNameSpace() { return mDstNameSpace; } 1.78 + 1.79 + nsIContent* GetElement() { return mElement; } 1.80 + 1.81 + nsXBLAttributeEntry* GetNext() { return mNext; } 1.82 + void SetNext(nsXBLAttributeEntry* aEntry) { mNext = aEntry; } 1.83 + 1.84 +protected: 1.85 + nsIContent* mElement; 1.86 + 1.87 + nsCOMPtr<nsIAtom> mSrcAttribute; 1.88 + nsCOMPtr<nsIAtom> mDstAttribute; 1.89 + int32_t mDstNameSpace; 1.90 + nsXBLAttributeEntry* mNext; 1.91 +}; 1.92 + 1.93 +// ============================================================================= 1.94 + 1.95 +// Implementation ///////////////////////////////////////////////////////////////// 1.96 + 1.97 +// Constructors/Destructors 1.98 +nsXBLPrototypeBinding::nsXBLPrototypeBinding() 1.99 +: mImplementation(nullptr), 1.100 + mBaseBinding(nullptr), 1.101 + mInheritStyle(true), 1.102 + mCheckedBaseProto(false), 1.103 + mKeyHandlersRegistered(false), 1.104 + mChromeOnlyContent(false), 1.105 + mResources(nullptr), 1.106 + mBaseNameSpaceID(kNameSpaceID_None) 1.107 +{ 1.108 + MOZ_COUNT_CTOR(nsXBLPrototypeBinding); 1.109 +} 1.110 + 1.111 +nsresult 1.112 +nsXBLPrototypeBinding::Init(const nsACString& aID, 1.113 + nsXBLDocumentInfo* aInfo, 1.114 + nsIContent* aElement, 1.115 + bool aFirstBinding) 1.116 +{ 1.117 + nsresult rv = aInfo->DocumentURI()->Clone(getter_AddRefs(mBindingURI)); 1.118 + NS_ENSURE_SUCCESS(rv, rv); 1.119 + 1.120 + // The binding URI might be an immutable URI (e.g. for about: URIs). In that case, 1.121 + // we'll fail in SetRef below, but that doesn't matter much for now. 1.122 + if (aFirstBinding) { 1.123 + rv = mBindingURI->Clone(getter_AddRefs(mAlternateBindingURI)); 1.124 + NS_ENSURE_SUCCESS(rv, rv); 1.125 + } 1.126 + mBindingURI->SetRef(aID); 1.127 + 1.128 + mXBLDocInfoWeak = aInfo; 1.129 + 1.130 + // aElement will be null when reading from the cache, but the element will 1.131 + // still be set later. 1.132 + if (aElement) { 1.133 + SetBindingElement(aElement); 1.134 + } 1.135 + return NS_OK; 1.136 +} 1.137 + 1.138 +bool nsXBLPrototypeBinding::CompareBindingURI(nsIURI* aURI) const 1.139 +{ 1.140 + bool equal = false; 1.141 + mBindingURI->Equals(aURI, &equal); 1.142 + if (!equal && mAlternateBindingURI) { 1.143 + mAlternateBindingURI->Equals(aURI, &equal); 1.144 + } 1.145 + return equal; 1.146 +} 1.147 + 1.148 +void 1.149 +nsXBLPrototypeBinding::Traverse(nsCycleCollectionTraversalCallback &cb) const 1.150 +{ 1.151 + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "proto mBinding"); 1.152 + cb.NoteXPCOMChild(mBinding); 1.153 + if (mResources) { 1.154 + mResources->Traverse(cb); 1.155 + } 1.156 + ImplCycleCollectionTraverse(cb, mInterfaceTable, "proto mInterfaceTable"); 1.157 +} 1.158 + 1.159 +void 1.160 +nsXBLPrototypeBinding::UnlinkJSObjects() 1.161 +{ 1.162 + if (mImplementation) 1.163 + mImplementation->UnlinkJSObjects(); 1.164 +} 1.165 + 1.166 +void 1.167 +nsXBLPrototypeBinding::Trace(const TraceCallbacks& aCallbacks, void *aClosure) const 1.168 +{ 1.169 + if (mImplementation) 1.170 + mImplementation->Trace(aCallbacks, aClosure); 1.171 +} 1.172 + 1.173 +void 1.174 +nsXBLPrototypeBinding::Initialize() 1.175 +{ 1.176 + nsIContent* content = GetImmediateChild(nsGkAtoms::content); 1.177 + if (content) { 1.178 + ConstructAttributeTable(content); 1.179 + } 1.180 +} 1.181 + 1.182 +nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void) 1.183 +{ 1.184 + delete mImplementation; 1.185 + MOZ_COUNT_DTOR(nsXBLPrototypeBinding); 1.186 +} 1.187 + 1.188 +void 1.189 +nsXBLPrototypeBinding::SetBasePrototype(nsXBLPrototypeBinding* aBinding) 1.190 +{ 1.191 + if (mBaseBinding == aBinding) 1.192 + return; 1.193 + 1.194 + if (mBaseBinding) { 1.195 + NS_ERROR("Base XBL prototype binding is already defined!"); 1.196 + return; 1.197 + } 1.198 + 1.199 + mBaseBinding = aBinding; 1.200 +} 1.201 + 1.202 +void 1.203 +nsXBLPrototypeBinding::SetBindingElement(nsIContent* aElement) 1.204 +{ 1.205 + mBinding = aElement; 1.206 + if (mBinding->AttrValueIs(kNameSpaceID_None, nsGkAtoms::inheritstyle, 1.207 + nsGkAtoms::_false, eCaseMatters)) 1.208 + mInheritStyle = false; 1.209 + 1.210 + mChromeOnlyContent = mBinding->AttrValueIs(kNameSpaceID_None, 1.211 + nsGkAtoms::chromeOnlyContent, 1.212 + nsGkAtoms::_true, eCaseMatters); 1.213 +} 1.214 + 1.215 +bool 1.216 +nsXBLPrototypeBinding::GetAllowScripts() const 1.217 +{ 1.218 + return mXBLDocInfoWeak->GetScriptAccess(); 1.219 +} 1.220 + 1.221 +bool 1.222 +nsXBLPrototypeBinding::LoadResources() 1.223 +{ 1.224 + if (mResources) { 1.225 + bool result; 1.226 + mResources->LoadResources(&result); 1.227 + return result; 1.228 + } 1.229 + 1.230 + return true; 1.231 +} 1.232 + 1.233 +nsresult 1.234 +nsXBLPrototypeBinding::AddResource(nsIAtom* aResourceType, const nsAString& aSrc) 1.235 +{ 1.236 + if (!mResources) { 1.237 + mResources = new nsXBLPrototypeResources(this); 1.238 + } 1.239 + 1.240 + mResources->AddResource(aResourceType, aSrc); 1.241 + return NS_OK; 1.242 +} 1.243 + 1.244 +nsresult 1.245 +nsXBLPrototypeBinding::FlushSkinSheets() 1.246 +{ 1.247 + if (mResources) 1.248 + return mResources->FlushSkinSheets(); 1.249 + return NS_OK; 1.250 +} 1.251 + 1.252 +nsresult 1.253 +nsXBLPrototypeBinding::BindingAttached(nsIContent* aBoundElement) 1.254 +{ 1.255 + if (mImplementation && mImplementation->CompiledMembers() && 1.256 + mImplementation->mConstructor) 1.257 + return mImplementation->mConstructor->Execute(aBoundElement); 1.258 + return NS_OK; 1.259 +} 1.260 + 1.261 +nsresult 1.262 +nsXBLPrototypeBinding::BindingDetached(nsIContent* aBoundElement) 1.263 +{ 1.264 + if (mImplementation && mImplementation->CompiledMembers() && 1.265 + mImplementation->mDestructor) 1.266 + return mImplementation->mDestructor->Execute(aBoundElement); 1.267 + return NS_OK; 1.268 +} 1.269 + 1.270 +nsXBLProtoImplAnonymousMethod* 1.271 +nsXBLPrototypeBinding::GetConstructor() 1.272 +{ 1.273 + if (mImplementation) 1.274 + return mImplementation->mConstructor; 1.275 + 1.276 + return nullptr; 1.277 +} 1.278 + 1.279 +nsXBLProtoImplAnonymousMethod* 1.280 +nsXBLPrototypeBinding::GetDestructor() 1.281 +{ 1.282 + if (mImplementation) 1.283 + return mImplementation->mDestructor; 1.284 + 1.285 + return nullptr; 1.286 +} 1.287 + 1.288 +nsresult 1.289 +nsXBLPrototypeBinding::SetConstructor(nsXBLProtoImplAnonymousMethod* aMethod) 1.290 +{ 1.291 + if (!mImplementation) 1.292 + return NS_ERROR_FAILURE; 1.293 + mImplementation->mConstructor = aMethod; 1.294 + return NS_OK; 1.295 +} 1.296 + 1.297 +nsresult 1.298 +nsXBLPrototypeBinding::SetDestructor(nsXBLProtoImplAnonymousMethod* aMethod) 1.299 +{ 1.300 + if (!mImplementation) 1.301 + return NS_ERROR_FAILURE; 1.302 + mImplementation->mDestructor = aMethod; 1.303 + return NS_OK; 1.304 +} 1.305 + 1.306 +nsresult 1.307 +nsXBLPrototypeBinding::InstallImplementation(nsXBLBinding* aBinding) 1.308 +{ 1.309 + if (mImplementation) 1.310 + return mImplementation->InstallImplementation(this, aBinding); 1.311 + return NS_OK; 1.312 +} 1.313 + 1.314 +// XXXbz this duplicates lots of SetAttrs 1.315 +void 1.316 +nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, 1.317 + int32_t aNameSpaceID, 1.318 + bool aRemoveFlag, 1.319 + nsIContent* aChangedElement, 1.320 + nsIContent* aAnonymousContent, 1.321 + bool aNotify) 1.322 +{ 1.323 + if (!mAttributeTable) 1.324 + return; 1.325 + 1.326 + InnerAttributeTable *attributesNS = mAttributeTable->Get(aNameSpaceID); 1.327 + if (!attributesNS) 1.328 + return; 1.329 + 1.330 + nsXBLAttributeEntry* xblAttr = attributesNS->Get(aAttribute); 1.331 + if (!xblAttr) 1.332 + return; 1.333 + 1.334 + // Iterate over the elements in the array. 1.335 + nsCOMPtr<nsIContent> content = GetImmediateChild(nsGkAtoms::content); 1.336 + while (xblAttr) { 1.337 + nsIContent* element = xblAttr->GetElement(); 1.338 + 1.339 + nsCOMPtr<nsIContent> realElement = LocateInstance(aChangedElement, content, 1.340 + aAnonymousContent, 1.341 + element); 1.342 + 1.343 + if (realElement) { 1.344 + // Hold a strong reference here so that the atom doesn't go away during 1.345 + // UnsetAttr. 1.346 + nsCOMPtr<nsIAtom> dstAttr = xblAttr->GetDstAttribute(); 1.347 + int32_t dstNs = xblAttr->GetDstNameSpace(); 1.348 + 1.349 + if (aRemoveFlag) 1.350 + realElement->UnsetAttr(dstNs, dstAttr, aNotify); 1.351 + else { 1.352 + bool attrPresent = true; 1.353 + nsAutoString value; 1.354 + // Check to see if the src attribute is xbl:text. If so, then we need to obtain the 1.355 + // children of the real element and get the text nodes' values. 1.356 + if (aAttribute == nsGkAtoms::text && aNameSpaceID == kNameSpaceID_XBL) { 1.357 + if (!nsContentUtils::GetNodeTextContent(aChangedElement, false, value)) { 1.358 + NS_RUNTIMEABORT("OOM"); 1.359 + } 1.360 + value.StripChar(char16_t('\n')); 1.361 + value.StripChar(char16_t('\r')); 1.362 + nsAutoString stripVal(value); 1.363 + stripVal.StripWhitespace(); 1.364 + if (stripVal.IsEmpty()) 1.365 + attrPresent = false; 1.366 + } 1.367 + else { 1.368 + attrPresent = aChangedElement->GetAttr(aNameSpaceID, aAttribute, value); 1.369 + } 1.370 + 1.371 + if (attrPresent) 1.372 + realElement->SetAttr(dstNs, dstAttr, value, aNotify); 1.373 + } 1.374 + 1.375 + // See if we're the <html> tag in XUL, and see if value is being 1.376 + // set or unset on us. We may also be a tag that is having 1.377 + // xbl:text set on us. 1.378 + 1.379 + if ((dstAttr == nsGkAtoms::text && dstNs == kNameSpaceID_XBL) || 1.380 + (realElement->NodeInfo()->Equals(nsGkAtoms::html, 1.381 + kNameSpaceID_XUL) && 1.382 + dstAttr == nsGkAtoms::value)) { 1.383 + // Flush out all our kids. 1.384 + uint32_t childCount = realElement->GetChildCount(); 1.385 + for (uint32_t i = 0; i < childCount; i++) 1.386 + realElement->RemoveChildAt(0, aNotify); 1.387 + 1.388 + if (!aRemoveFlag) { 1.389 + // Construct a new text node and insert it. 1.390 + nsAutoString value; 1.391 + aChangedElement->GetAttr(aNameSpaceID, aAttribute, value); 1.392 + if (!value.IsEmpty()) { 1.393 + nsRefPtr<nsTextNode> textContent = 1.394 + new nsTextNode(realElement->NodeInfo()->NodeInfoManager()); 1.395 + 1.396 + textContent->SetText(value, true); 1.397 + realElement->AppendChildTo(textContent, true); 1.398 + } 1.399 + } 1.400 + } 1.401 + } 1.402 + 1.403 + xblAttr = xblAttr->GetNext(); 1.404 + } 1.405 +} 1.406 + 1.407 +void 1.408 +nsXBLPrototypeBinding::SetBaseTag(int32_t aNamespaceID, nsIAtom* aTag) 1.409 +{ 1.410 + mBaseNameSpaceID = aNamespaceID; 1.411 + mBaseTag = aTag; 1.412 +} 1.413 + 1.414 +nsIAtom* 1.415 +nsXBLPrototypeBinding::GetBaseTag(int32_t* aNamespaceID) 1.416 +{ 1.417 + if (mBaseTag) { 1.418 + *aNamespaceID = mBaseNameSpaceID; 1.419 + return mBaseTag; 1.420 + } 1.421 + 1.422 + return nullptr; 1.423 +} 1.424 + 1.425 +bool 1.426 +nsXBLPrototypeBinding::ImplementsInterface(REFNSIID aIID) const 1.427 +{ 1.428 + // Check our IID table. 1.429 + return !!mInterfaceTable.GetWeak(aIID); 1.430 +} 1.431 + 1.432 +// Internal helpers /////////////////////////////////////////////////////////////////////// 1.433 + 1.434 +nsIContent* 1.435 +nsXBLPrototypeBinding::GetImmediateChild(nsIAtom* aTag) 1.436 +{ 1.437 + for (nsIContent* child = mBinding->GetFirstChild(); 1.438 + child; 1.439 + child = child->GetNextSibling()) { 1.440 + if (child->NodeInfo()->Equals(aTag, kNameSpaceID_XBL)) { 1.441 + return child; 1.442 + } 1.443 + } 1.444 + 1.445 + return nullptr; 1.446 +} 1.447 + 1.448 +nsresult 1.449 +nsXBLPrototypeBinding::InitClass(const nsCString& aClassName, 1.450 + JSContext * aContext, 1.451 + JS::Handle<JSObject*> aScriptObject, 1.452 + JS::MutableHandle<JSObject*> aClassObject, 1.453 + bool* aNew) 1.454 +{ 1.455 + return nsXBLBinding::DoInitJSClass(aContext, aScriptObject, 1.456 + aClassName, this, aClassObject, aNew); 1.457 +} 1.458 + 1.459 +nsIContent* 1.460 +nsXBLPrototypeBinding::LocateInstance(nsIContent* aBoundElement, 1.461 + nsIContent* aTemplRoot, 1.462 + nsIContent* aCopyRoot, 1.463 + nsIContent* aTemplChild) 1.464 +{ 1.465 + // XXX We will get in trouble if the binding instantiation deviates from the template 1.466 + // in the prototype. 1.467 + if (aTemplChild == aTemplRoot || !aTemplChild) 1.468 + return nullptr; 1.469 + 1.470 + nsIContent* templParent = aTemplChild->GetParent(); 1.471 + 1.472 + // We may be disconnected from our parent during cycle collection. 1.473 + if (!templParent) 1.474 + return nullptr; 1.475 + 1.476 + nsIContent *copyParent = 1.477 + templParent == aTemplRoot ? aCopyRoot : 1.478 + LocateInstance(aBoundElement, aTemplRoot, aCopyRoot, templParent); 1.479 + 1.480 + if (!copyParent) 1.481 + return nullptr; 1.482 + 1.483 + return copyParent->GetChildAt(templParent->IndexOf(aTemplChild)); 1.484 +} 1.485 + 1.486 +struct nsXBLAttrChangeData 1.487 +{ 1.488 + nsXBLPrototypeBinding* mProto; 1.489 + nsIContent* mBoundElement; 1.490 + nsIContent* mContent; 1.491 + int32_t mSrcNamespace; 1.492 + 1.493 + nsXBLAttrChangeData(nsXBLPrototypeBinding* aProto, 1.494 + nsIContent* aElt, nsIContent* aContent) 1.495 + :mProto(aProto), mBoundElement(aElt), mContent(aContent) {} 1.496 +}; 1.497 + 1.498 +// XXXbz this duplicates lots of AttributeChanged 1.499 +static PLDHashOperator 1.500 +SetAttrs(nsISupports* aKey, nsXBLAttributeEntry* aEntry, void* aClosure) 1.501 +{ 1.502 + nsXBLAttrChangeData* changeData = static_cast<nsXBLAttrChangeData*>(aClosure); 1.503 + 1.504 + nsIAtom* src = aEntry->GetSrcAttribute(); 1.505 + int32_t srcNs = changeData->mSrcNamespace; 1.506 + nsAutoString value; 1.507 + bool attrPresent = true; 1.508 + 1.509 + if (src == nsGkAtoms::text && srcNs == kNameSpaceID_XBL) { 1.510 + if (!nsContentUtils::GetNodeTextContent(changeData->mBoundElement, false, 1.511 + value)) { 1.512 + NS_RUNTIMEABORT("OOM"); 1.513 + } 1.514 + value.StripChar(char16_t('\n')); 1.515 + value.StripChar(char16_t('\r')); 1.516 + nsAutoString stripVal(value); 1.517 + stripVal.StripWhitespace(); 1.518 + 1.519 + if (stripVal.IsEmpty()) 1.520 + attrPresent = false; 1.521 + } 1.522 + else { 1.523 + attrPresent = changeData->mBoundElement->GetAttr(srcNs, src, value); 1.524 + } 1.525 + 1.526 + if (attrPresent) { 1.527 + nsIContent* content = 1.528 + changeData->mProto->GetImmediateChild(nsGkAtoms::content); 1.529 + 1.530 + nsXBLAttributeEntry* curr = aEntry; 1.531 + while (curr) { 1.532 + nsIAtom* dst = curr->GetDstAttribute(); 1.533 + int32_t dstNs = curr->GetDstNameSpace(); 1.534 + nsIContent* element = curr->GetElement(); 1.535 + 1.536 + nsIContent *realElement = 1.537 + changeData->mProto->LocateInstance(changeData->mBoundElement, content, 1.538 + changeData->mContent, element); 1.539 + 1.540 + if (realElement) { 1.541 + realElement->SetAttr(dstNs, dst, value, false); 1.542 + 1.543 + // XXXndeakin shouldn't this be done in lieu of SetAttr? 1.544 + if ((dst == nsGkAtoms::text && dstNs == kNameSpaceID_XBL) || 1.545 + (realElement->NodeInfo()->Equals(nsGkAtoms::html, 1.546 + kNameSpaceID_XUL) && 1.547 + dst == nsGkAtoms::value && !value.IsEmpty())) { 1.548 + 1.549 + nsRefPtr<nsTextNode> textContent = 1.550 + new nsTextNode(realElement->NodeInfo()->NodeInfoManager()); 1.551 + 1.552 + textContent->SetText(value, false); 1.553 + realElement->AppendChildTo(textContent, false); 1.554 + } 1.555 + } 1.556 + 1.557 + curr = curr->GetNext(); 1.558 + } 1.559 + } 1.560 + 1.561 + return PL_DHASH_NEXT; 1.562 +} 1.563 + 1.564 +static PLDHashOperator 1.565 +SetAttrsNS(const uint32_t &aNamespace, 1.566 + nsXBLPrototypeBinding::InnerAttributeTable* aXBLAttributes, 1.567 + void* aClosure) 1.568 +{ 1.569 + if (aXBLAttributes && aClosure) { 1.570 + nsXBLAttrChangeData* changeData = static_cast<nsXBLAttrChangeData*>(aClosure); 1.571 + changeData->mSrcNamespace = aNamespace; 1.572 + aXBLAttributes->EnumerateRead(SetAttrs, aClosure); 1.573 + } 1.574 + return PL_DHASH_NEXT; 1.575 +} 1.576 + 1.577 +void 1.578 +nsXBLPrototypeBinding::SetInitialAttributes(nsIContent* aBoundElement, nsIContent* aAnonymousContent) 1.579 +{ 1.580 + if (mAttributeTable) { 1.581 + nsXBLAttrChangeData data(this, aBoundElement, aAnonymousContent); 1.582 + mAttributeTable->EnumerateRead(SetAttrsNS, &data); 1.583 + } 1.584 +} 1.585 + 1.586 +nsIStyleRuleProcessor* 1.587 +nsXBLPrototypeBinding::GetRuleProcessor() 1.588 +{ 1.589 + if (mResources) { 1.590 + return mResources->mRuleProcessor; 1.591 + } 1.592 + 1.593 + return nullptr; 1.594 +} 1.595 + 1.596 +nsXBLPrototypeResources::sheet_array_type* 1.597 +nsXBLPrototypeBinding::GetOrCreateStyleSheets() 1.598 +{ 1.599 + if (!mResources) { 1.600 + mResources = new nsXBLPrototypeResources(this); 1.601 + } 1.602 + 1.603 + return &mResources->mStyleSheetList; 1.604 +} 1.605 + 1.606 +nsXBLPrototypeResources::sheet_array_type* 1.607 +nsXBLPrototypeBinding::GetStyleSheets() 1.608 +{ 1.609 + if (mResources) { 1.610 + return &mResources->mStyleSheetList; 1.611 + } 1.612 + 1.613 + return nullptr; 1.614 +} 1.615 + 1.616 +void 1.617 +nsXBLPrototypeBinding::EnsureAttributeTable() 1.618 +{ 1.619 + if (!mAttributeTable) { 1.620 + mAttributeTable = new nsClassHashtable<nsUint32HashKey, InnerAttributeTable>(4); 1.621 + } 1.622 +} 1.623 + 1.624 +void 1.625 +nsXBLPrototypeBinding::AddToAttributeTable(int32_t aSourceNamespaceID, nsIAtom* aSourceTag, 1.626 + int32_t aDestNamespaceID, nsIAtom* aDestTag, 1.627 + nsIContent* aContent) 1.628 +{ 1.629 + InnerAttributeTable* attributesNS = mAttributeTable->Get(aSourceNamespaceID); 1.630 + if (!attributesNS) { 1.631 + attributesNS = new InnerAttributeTable(4); 1.632 + mAttributeTable->Put(aSourceNamespaceID, attributesNS); 1.633 + } 1.634 + 1.635 + nsXBLAttributeEntry* xblAttr = 1.636 + new nsXBLAttributeEntry(aSourceTag, aDestTag, aDestNamespaceID, aContent); 1.637 + 1.638 + nsXBLAttributeEntry* entry = attributesNS->Get(aSourceTag); 1.639 + if (!entry) { 1.640 + attributesNS->Put(aSourceTag, xblAttr); 1.641 + } else { 1.642 + while (entry->GetNext()) 1.643 + entry = entry->GetNext(); 1.644 + entry->SetNext(xblAttr); 1.645 + } 1.646 +} 1.647 + 1.648 +void 1.649 +nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement) 1.650 +{ 1.651 + // Don't add entries for <children> elements, since those will get 1.652 + // removed from the DOM when we construct the insertion point table. 1.653 + if (!aElement->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { 1.654 + nsAutoString inherits; 1.655 + aElement->GetAttr(kNameSpaceID_XBL, nsGkAtoms::inherits, inherits); 1.656 + 1.657 + if (!inherits.IsEmpty()) { 1.658 + EnsureAttributeTable(); 1.659 + 1.660 + // The user specified at least one attribute. 1.661 + char* str = ToNewCString(inherits); 1.662 + char* newStr; 1.663 + // XXX We should use a strtok function that tokenizes PRUnichars 1.664 + // so that we don't have to convert from Unicode to ASCII and then back 1.665 + 1.666 + char* token = nsCRT::strtok( str, ", ", &newStr ); 1.667 + while( token != nullptr ) { 1.668 + // Build an atom out of this attribute. 1.669 + nsCOMPtr<nsIAtom> atom; 1.670 + int32_t atomNsID = kNameSpaceID_None; 1.671 + nsCOMPtr<nsIAtom> attribute; 1.672 + int32_t attributeNsID = kNameSpaceID_None; 1.673 + 1.674 + // Figure out if this token contains a :. 1.675 + nsAutoString attrTok; attrTok.AssignWithConversion(token); 1.676 + int32_t index = attrTok.Find("=", true); 1.677 + nsresult rv; 1.678 + if (index != -1) { 1.679 + // This attribute maps to something different. 1.680 + nsAutoString left, right; 1.681 + attrTok.Left(left, index); 1.682 + attrTok.Right(right, attrTok.Length()-index-1); 1.683 + 1.684 + rv = nsContentUtils::SplitQName(aElement, left, &attributeNsID, 1.685 + getter_AddRefs(attribute)); 1.686 + if (NS_FAILED(rv)) 1.687 + return; 1.688 + 1.689 + rv = nsContentUtils::SplitQName(aElement, right, &atomNsID, 1.690 + getter_AddRefs(atom)); 1.691 + if (NS_FAILED(rv)) 1.692 + return; 1.693 + } 1.694 + else { 1.695 + nsAutoString tok; 1.696 + tok.AssignWithConversion(token); 1.697 + rv = nsContentUtils::SplitQName(aElement, tok, &atomNsID, 1.698 + getter_AddRefs(atom)); 1.699 + if (NS_FAILED(rv)) 1.700 + return; 1.701 + attribute = atom; 1.702 + attributeNsID = atomNsID; 1.703 + } 1.704 + 1.705 + AddToAttributeTable(atomNsID, atom, attributeNsID, attribute, aElement); 1.706 + 1.707 + // Now remove the inherits attribute from the element so that it doesn't 1.708 + // show up on clones of the element. It is used 1.709 + // by the template only, and we don't need it anymore. 1.710 + // XXXdwh Don't do this for XUL elements, since it faults them into heavyweight 1.711 + // elements. Should nuke from the prototype instead. 1.712 + // aElement->UnsetAttr(kNameSpaceID_XBL, nsGkAtoms::inherits, false); 1.713 + 1.714 + token = nsCRT::strtok( newStr, ", ", &newStr ); 1.715 + } 1.716 + 1.717 + nsMemory::Free(str); 1.718 + } 1.719 + } 1.720 + 1.721 + // Recur into our children. 1.722 + for (nsIContent* child = aElement->GetFirstChild(); 1.723 + child; 1.724 + child = child->GetNextSibling()) { 1.725 + ConstructAttributeTable(child); 1.726 + } 1.727 +} 1.728 + 1.729 +nsresult 1.730 +nsXBLPrototypeBinding::ConstructInterfaceTable(const nsAString& aImpls) 1.731 +{ 1.732 + if (!aImpls.IsEmpty()) { 1.733 + // Obtain the interface info manager that can tell us the IID 1.734 + // for a given interface name. 1.735 + nsCOMPtr<nsIInterfaceInfoManager> 1.736 + infoManager(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); 1.737 + if (!infoManager) 1.738 + return NS_ERROR_FAILURE; 1.739 + 1.740 + // The user specified at least one attribute. 1.741 + NS_ConvertUTF16toUTF8 utf8impl(aImpls); 1.742 + char* str = utf8impl.BeginWriting(); 1.743 + char* newStr; 1.744 + // XXX We should use a strtok function that tokenizes PRUnichars 1.745 + // so that we don't have to convert from Unicode to ASCII and then back 1.746 + 1.747 + char* token = nsCRT::strtok( str, ", ", &newStr ); 1.748 + while( token != nullptr ) { 1.749 + // get the InterfaceInfo for the name 1.750 + nsCOMPtr<nsIInterfaceInfo> iinfo; 1.751 + infoManager->GetInfoForName(token, getter_AddRefs(iinfo)); 1.752 + 1.753 + if (iinfo) { 1.754 + // obtain an IID. 1.755 + const nsIID* iid = nullptr; 1.756 + iinfo->GetIIDShared(&iid); 1.757 + 1.758 + if (iid) { 1.759 + // We found a valid iid. Add it to our table. 1.760 + mInterfaceTable.Put(*iid, mBinding); 1.761 + 1.762 + // this block adds the parent interfaces of each interface 1.763 + // defined in the xbl definition (implements="nsI...") 1.764 + nsCOMPtr<nsIInterfaceInfo> parentInfo; 1.765 + // if it has a parent, add it to the table 1.766 + while (NS_SUCCEEDED(iinfo->GetParent(getter_AddRefs(parentInfo))) && parentInfo) { 1.767 + // get the iid 1.768 + parentInfo->GetIIDShared(&iid); 1.769 + 1.770 + // don't add nsISupports to the table 1.771 + if (!iid || iid->Equals(NS_GET_IID(nsISupports))) 1.772 + break; 1.773 + 1.774 + // add the iid to the table 1.775 + mInterfaceTable.Put(*iid, mBinding); 1.776 + 1.777 + // look for the next parent 1.778 + iinfo = parentInfo; 1.779 + } 1.780 + } 1.781 + } 1.782 + 1.783 + token = nsCRT::strtok( newStr, ", ", &newStr ); 1.784 + } 1.785 + } 1.786 + 1.787 + return NS_OK; 1.788 +} 1.789 + 1.790 +nsresult 1.791 +nsXBLPrototypeBinding::AddResourceListener(nsIContent* aBoundElement) 1.792 +{ 1.793 + if (!mResources) 1.794 + return NS_ERROR_FAILURE; // Makes no sense to add a listener when the binding 1.795 + // has no resources. 1.796 + 1.797 + mResources->AddResourceListener(aBoundElement); 1.798 + return NS_OK; 1.799 +} 1.800 + 1.801 +void 1.802 +nsXBLPrototypeBinding::CreateKeyHandlers() 1.803 +{ 1.804 + nsXBLPrototypeHandler* curr = mPrototypeHandler; 1.805 + while (curr) { 1.806 + nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName(); 1.807 + if (eventAtom == nsGkAtoms::keyup || 1.808 + eventAtom == nsGkAtoms::keydown || 1.809 + eventAtom == nsGkAtoms::keypress) { 1.810 + uint8_t phase = curr->GetPhase(); 1.811 + uint8_t type = curr->GetType(); 1.812 + 1.813 + int32_t count = mKeyHandlers.Count(); 1.814 + int32_t i; 1.815 + nsXBLKeyEventHandler* handler = nullptr; 1.816 + for (i = 0; i < count; ++i) { 1.817 + handler = mKeyHandlers[i]; 1.818 + if (handler->Matches(eventAtom, phase, type)) 1.819 + break; 1.820 + } 1.821 + 1.822 + if (i == count) { 1.823 + nsRefPtr<nsXBLKeyEventHandler> newHandler; 1.824 + NS_NewXBLKeyEventHandler(eventAtom, phase, type, 1.825 + getter_AddRefs(newHandler)); 1.826 + if (newHandler) 1.827 + mKeyHandlers.AppendObject(newHandler); 1.828 + handler = newHandler; 1.829 + } 1.830 + 1.831 + if (handler) 1.832 + handler->AddProtoHandler(curr); 1.833 + } 1.834 + 1.835 + curr = curr->GetNextHandler(); 1.836 + } 1.837 +} 1.838 + 1.839 +class XBLPrototypeSetupCleanup 1.840 +{ 1.841 +public: 1.842 + XBLPrototypeSetupCleanup(nsXBLDocumentInfo* aDocInfo, const nsACString& aID) 1.843 + : mDocInfo(aDocInfo), mID(aID) {} 1.844 + 1.845 + ~XBLPrototypeSetupCleanup() 1.846 + { 1.847 + if (mDocInfo) { 1.848 + mDocInfo->RemovePrototypeBinding(mID); 1.849 + } 1.850 + } 1.851 + 1.852 + void Disconnect() 1.853 + { 1.854 + mDocInfo = nullptr; 1.855 + } 1.856 + 1.857 + nsXBLDocumentInfo* mDocInfo; 1.858 + nsAutoCString mID; 1.859 +}; 1.860 + 1.861 +nsresult 1.862 +nsXBLPrototypeBinding::Read(nsIObjectInputStream* aStream, 1.863 + nsXBLDocumentInfo* aDocInfo, 1.864 + nsIDocument* aDocument, 1.865 + uint8_t aFlags) 1.866 +{ 1.867 + mInheritStyle = (aFlags & XBLBinding_Serialize_InheritStyle) ? true : false; 1.868 + mChromeOnlyContent = 1.869 + (aFlags & XBLBinding_Serialize_ChromeOnlyContent) ? true : false; 1.870 + 1.871 + // nsXBLContentSink::ConstructBinding doesn't create a binding with an empty 1.872 + // id, so we don't here either. 1.873 + nsAutoCString id; 1.874 + nsresult rv = aStream->ReadCString(id); 1.875 + 1.876 + NS_ENSURE_SUCCESS(rv, rv); 1.877 + NS_ENSURE_TRUE(!id.IsEmpty(), NS_ERROR_FAILURE); 1.878 + 1.879 + nsAutoCString baseBindingURI; 1.880 + rv = aStream->ReadCString(baseBindingURI); 1.881 + NS_ENSURE_SUCCESS(rv, rv); 1.882 + mCheckedBaseProto = true; 1.883 + 1.884 + if (!baseBindingURI.IsEmpty()) { 1.885 + rv = NS_NewURI(getter_AddRefs(mBaseBindingURI), baseBindingURI); 1.886 + NS_ENSURE_SUCCESS(rv, rv); 1.887 + } 1.888 + 1.889 + rv = ReadNamespace(aStream, mBaseNameSpaceID); 1.890 + NS_ENSURE_SUCCESS(rv, rv); 1.891 + 1.892 + nsAutoString baseTag; 1.893 + rv = aStream->ReadString(baseTag); 1.894 + NS_ENSURE_SUCCESS(rv, rv); 1.895 + if (!baseTag.IsEmpty()) { 1.896 + mBaseTag = do_GetAtom(baseTag); 1.897 + } 1.898 + 1.899 + aDocument->CreateElem(NS_LITERAL_STRING("binding"), nullptr, kNameSpaceID_XBL, 1.900 + getter_AddRefs(mBinding)); 1.901 + 1.902 + nsCOMPtr<nsIContent> child; 1.903 + rv = ReadContentNode(aStream, aDocument, aDocument->NodeInfoManager(), getter_AddRefs(child)); 1.904 + NS_ENSURE_SUCCESS(rv, rv); 1.905 + 1.906 + Element* rootElement = aDocument->GetRootElement(); 1.907 + if (rootElement) 1.908 + rootElement->AppendChildTo(mBinding, false); 1.909 + 1.910 + if (child) { 1.911 + mBinding->AppendChildTo(child, false); 1.912 + } 1.913 + 1.914 + uint32_t interfaceCount; 1.915 + rv = aStream->Read32(&interfaceCount); 1.916 + NS_ENSURE_SUCCESS(rv, rv); 1.917 + 1.918 + for (; interfaceCount > 0; interfaceCount--) { 1.919 + nsIID iid; 1.920 + aStream->ReadID(&iid); 1.921 + mInterfaceTable.Put(iid, mBinding); 1.922 + } 1.923 + 1.924 + AutoSafeJSContext cx; 1.925 + JS::Rooted<JSObject*> compilationGlobal(cx, xpc::GetCompilationScope()); 1.926 + NS_ENSURE_TRUE(compilationGlobal, NS_ERROR_UNEXPECTED); 1.927 + JSAutoCompartment ac(cx, compilationGlobal); 1.928 + 1.929 + bool isFirstBinding = aFlags & XBLBinding_Serialize_IsFirstBinding; 1.930 + rv = Init(id, aDocInfo, nullptr, isFirstBinding); 1.931 + NS_ENSURE_SUCCESS(rv, rv); 1.932 + 1.933 + // We need to set the prototype binding before reading the nsXBLProtoImpl, 1.934 + // as it may be retrieved within. 1.935 + rv = aDocInfo->SetPrototypeBinding(id, this); 1.936 + NS_ENSURE_SUCCESS(rv, rv); 1.937 + 1.938 + XBLPrototypeSetupCleanup cleanup(aDocInfo, id); 1.939 + 1.940 + nsAutoCString className; 1.941 + rv = aStream->ReadCString(className); 1.942 + NS_ENSURE_SUCCESS(rv, rv); 1.943 + 1.944 + if (!className.IsEmpty()) { 1.945 + nsXBLProtoImpl* impl; // NS_NewXBLProtoImpl will set mImplementation for us 1.946 + NS_NewXBLProtoImpl(this, NS_ConvertUTF8toUTF16(className).get(), &impl); 1.947 + 1.948 + // This needs to happen after SetPrototypeBinding as calls are made to 1.949 + // retrieve the mapped bindings from within here. However, if an error 1.950 + // occurs, the mapping should be removed again so that we don't keep an 1.951 + // invalid binding around. 1.952 + rv = mImplementation->Read(aStream, this); 1.953 + NS_ENSURE_SUCCESS(rv, rv); 1.954 + } 1.955 + 1.956 + // Next read in the handlers. 1.957 + nsXBLPrototypeHandler* previousHandler = nullptr; 1.958 + 1.959 + do { 1.960 + XBLBindingSerializeDetails type; 1.961 + rv = aStream->Read8(&type); 1.962 + NS_ENSURE_SUCCESS(rv, rv); 1.963 + 1.964 + if (type == XBLBinding_Serialize_NoMoreItems) 1.965 + break; 1.966 + 1.967 + NS_ASSERTION((type & XBLBinding_Serialize_Mask) == XBLBinding_Serialize_Handler, 1.968 + "invalid handler type"); 1.969 + 1.970 + nsXBLPrototypeHandler* handler = new nsXBLPrototypeHandler(this); 1.971 + rv = handler->Read(aStream); 1.972 + if (NS_FAILED(rv)) { 1.973 + delete handler; 1.974 + return rv; 1.975 + } 1.976 + 1.977 + if (previousHandler) { 1.978 + previousHandler->SetNextHandler(handler); 1.979 + } 1.980 + else { 1.981 + SetPrototypeHandlers(handler); 1.982 + } 1.983 + previousHandler = handler; 1.984 + } while (1); 1.985 + 1.986 + if (mBinding) { 1.987 + while (true) { 1.988 + XBLBindingSerializeDetails type; 1.989 + rv = aStream->Read8(&type); 1.990 + NS_ENSURE_SUCCESS(rv, rv); 1.991 + 1.992 + if (type != XBLBinding_Serialize_Attribute) { 1.993 + break; 1.994 + } 1.995 + 1.996 + int32_t attrNamespace; 1.997 + rv = ReadNamespace(aStream, attrNamespace); 1.998 + NS_ENSURE_SUCCESS(rv, rv); 1.999 + 1.1000 + nsAutoString attrPrefix, attrName, attrValue; 1.1001 + rv = aStream->ReadString(attrPrefix); 1.1002 + NS_ENSURE_SUCCESS(rv, rv); 1.1003 + 1.1004 + rv = aStream->ReadString(attrName); 1.1005 + NS_ENSURE_SUCCESS(rv, rv); 1.1006 + 1.1007 + rv = aStream->ReadString(attrValue); 1.1008 + NS_ENSURE_SUCCESS(rv, rv); 1.1009 + 1.1010 + nsCOMPtr<nsIAtom> atomPrefix = do_GetAtom(attrPrefix); 1.1011 + nsCOMPtr<nsIAtom> atomName = do_GetAtom(attrName); 1.1012 + mBinding->SetAttr(attrNamespace, atomName, atomPrefix, attrValue, false); 1.1013 + } 1.1014 + } 1.1015 + 1.1016 + // Finally, read in the resources. 1.1017 + while (true) { 1.1018 + XBLBindingSerializeDetails type; 1.1019 + rv = aStream->Read8(&type); 1.1020 + NS_ENSURE_SUCCESS(rv, rv); 1.1021 + 1.1022 + if (type == XBLBinding_Serialize_NoMoreItems) 1.1023 + break; 1.1024 + 1.1025 + NS_ASSERTION((type & XBLBinding_Serialize_Mask) == XBLBinding_Serialize_Stylesheet || 1.1026 + (type & XBLBinding_Serialize_Mask) == XBLBinding_Serialize_Image, "invalid resource type"); 1.1027 + 1.1028 + nsAutoString src; 1.1029 + rv = aStream->ReadString(src); 1.1030 + NS_ENSURE_SUCCESS(rv, rv); 1.1031 + 1.1032 + AddResource(type == XBLBinding_Serialize_Stylesheet ? nsGkAtoms::stylesheet : 1.1033 + nsGkAtoms::image, src); 1.1034 + } 1.1035 + 1.1036 + if (isFirstBinding) { 1.1037 + aDocInfo->SetFirstPrototypeBinding(this); 1.1038 + } 1.1039 + 1.1040 + cleanup.Disconnect(); 1.1041 + return NS_OK; 1.1042 +} 1.1043 + 1.1044 +// static 1.1045 +nsresult 1.1046 +nsXBLPrototypeBinding::ReadNewBinding(nsIObjectInputStream* aStream, 1.1047 + nsXBLDocumentInfo* aDocInfo, 1.1048 + nsIDocument* aDocument, 1.1049 + uint8_t aFlags) 1.1050 +{ 1.1051 + // If the Read() succeeds, |binding| will end up being owned by aDocInfo's 1.1052 + // binding table. Otherwise, we must manually delete it. 1.1053 + nsXBLPrototypeBinding* binding = new nsXBLPrototypeBinding(); 1.1054 + nsresult rv = binding->Read(aStream, aDocInfo, aDocument, aFlags); 1.1055 + if (NS_FAILED(rv)) { 1.1056 + delete binding; 1.1057 + } 1.1058 + return rv; 1.1059 +} 1.1060 + 1.1061 +static PLDHashOperator 1.1062 +WriteInterfaceID(const nsIID& aKey, nsIContent* aData, void* aClosure) 1.1063 +{ 1.1064 + // We can just write out the ids. The cache will be invalidated when a 1.1065 + // different build is used, so we don't need to worry about ids changing. 1.1066 + static_cast<nsIObjectOutputStream *>(aClosure)->WriteID(aKey); 1.1067 + return PL_DHASH_NEXT; 1.1068 +} 1.1069 + 1.1070 +nsresult 1.1071 +nsXBLPrototypeBinding::Write(nsIObjectOutputStream* aStream) 1.1072 +{ 1.1073 + // This writes out the binding. Note that mCheckedBaseProto, 1.1074 + // mKeyHandlersRegistered and mKeyHandlers are not serialized as they are 1.1075 + // computed on demand. 1.1076 + 1.1077 + AutoSafeJSContext cx; 1.1078 + JS::Rooted<JSObject*> compilationGlobal(cx, xpc::GetCompilationScope()); 1.1079 + NS_ENSURE_TRUE(compilationGlobal, NS_ERROR_UNEXPECTED); 1.1080 + JSAutoCompartment ac(cx, compilationGlobal); 1.1081 + 1.1082 + uint8_t flags = mInheritStyle ? XBLBinding_Serialize_InheritStyle : 0; 1.1083 + 1.1084 + // mAlternateBindingURI is only set on the first binding. 1.1085 + if (mAlternateBindingURI) { 1.1086 + flags |= XBLBinding_Serialize_IsFirstBinding; 1.1087 + } 1.1088 + 1.1089 + if (mChromeOnlyContent) { 1.1090 + flags |= XBLBinding_Serialize_ChromeOnlyContent; 1.1091 + } 1.1092 + 1.1093 + nsresult rv = aStream->Write8(flags); 1.1094 + NS_ENSURE_SUCCESS(rv, rv); 1.1095 + 1.1096 + nsAutoCString id; 1.1097 + mBindingURI->GetRef(id); 1.1098 + rv = aStream->WriteStringZ(id.get()); 1.1099 + NS_ENSURE_SUCCESS(rv, rv); 1.1100 + 1.1101 + // write out the extends and display attribute values 1.1102 + nsAutoCString extends; 1.1103 + ResolveBaseBinding(); 1.1104 + if (mBaseBindingURI) 1.1105 + mBaseBindingURI->GetSpec(extends); 1.1106 + 1.1107 + rv = aStream->WriteStringZ(extends.get()); 1.1108 + NS_ENSURE_SUCCESS(rv, rv); 1.1109 + 1.1110 + rv = WriteNamespace(aStream, mBaseNameSpaceID); 1.1111 + NS_ENSURE_SUCCESS(rv, rv); 1.1112 + 1.1113 + nsAutoString baseTag; 1.1114 + if (mBaseTag) { 1.1115 + mBaseTag->ToString(baseTag); 1.1116 + } 1.1117 + rv = aStream->WriteWStringZ(baseTag.get()); 1.1118 + NS_ENSURE_SUCCESS(rv, rv); 1.1119 + 1.1120 + nsIContent* content = GetImmediateChild(nsGkAtoms::content); 1.1121 + if (content) { 1.1122 + rv = WriteContentNode(aStream, content); 1.1123 + NS_ENSURE_SUCCESS(rv, rv); 1.1124 + } 1.1125 + else { 1.1126 + // Write a marker to indicate that there is no content. 1.1127 + rv = aStream->Write8(XBLBinding_Serialize_NoContent); 1.1128 + NS_ENSURE_SUCCESS(rv, rv); 1.1129 + } 1.1130 + 1.1131 + // Enumerate and write out the implemented interfaces. 1.1132 + rv = aStream->Write32(mInterfaceTable.Count()); 1.1133 + NS_ENSURE_SUCCESS(rv, rv); 1.1134 + 1.1135 + mInterfaceTable.EnumerateRead(WriteInterfaceID, aStream); 1.1136 + 1.1137 + // Write out the implementation details. 1.1138 + if (mImplementation) { 1.1139 + rv = mImplementation->Write(aStream, this); 1.1140 + NS_ENSURE_SUCCESS(rv, rv); 1.1141 + } 1.1142 + else { 1.1143 + // Write out an empty classname. This indicates that the binding does not 1.1144 + // define an implementation. 1.1145 + rv = aStream->WriteWStringZ(EmptyString().get()); 1.1146 + NS_ENSURE_SUCCESS(rv, rv); 1.1147 + } 1.1148 + 1.1149 + // Write out the handlers. 1.1150 + nsXBLPrototypeHandler* handler = mPrototypeHandler; 1.1151 + while (handler) { 1.1152 + rv = handler->Write(aStream); 1.1153 + NS_ENSURE_SUCCESS(rv, rv); 1.1154 + 1.1155 + handler = handler->GetNextHandler(); 1.1156 + } 1.1157 + 1.1158 + aStream->Write8(XBLBinding_Serialize_NoMoreItems); 1.1159 + NS_ENSURE_SUCCESS(rv, rv); 1.1160 + 1.1161 + if (mBinding) { 1.1162 + uint32_t attributes = mBinding->GetAttrCount(); 1.1163 + nsAutoString attrValue; 1.1164 + for (uint32_t i = 0; i < attributes; ++i) { 1.1165 + const nsAttrName* attr = mBinding->GetAttrNameAt(i); 1.1166 + nsDependentAtomString attrName = attr->LocalName(); 1.1167 + mBinding->GetAttr(attr->NamespaceID(), attr->LocalName(), attrValue); 1.1168 + rv = aStream->Write8(XBLBinding_Serialize_Attribute); 1.1169 + NS_ENSURE_SUCCESS(rv, rv); 1.1170 + 1.1171 + rv = WriteNamespace(aStream, attr->NamespaceID()); 1.1172 + NS_ENSURE_SUCCESS(rv, rv); 1.1173 + 1.1174 + nsIAtom* prefix = attr->GetPrefix(); 1.1175 + nsAutoString prefixString; 1.1176 + if (prefix) { 1.1177 + prefix->ToString(prefixString); 1.1178 + } 1.1179 + 1.1180 + rv = aStream->WriteWStringZ(prefixString.get()); 1.1181 + NS_ENSURE_SUCCESS(rv, rv); 1.1182 + 1.1183 + rv = aStream->WriteWStringZ(attrName.get()); 1.1184 + NS_ENSURE_SUCCESS(rv, rv); 1.1185 + 1.1186 + rv = aStream->WriteWStringZ(attrValue.get()); 1.1187 + NS_ENSURE_SUCCESS(rv, rv); 1.1188 + } 1.1189 + } 1.1190 + 1.1191 + aStream->Write8(XBLBinding_Serialize_NoMoreItems); 1.1192 + NS_ENSURE_SUCCESS(rv, rv); 1.1193 + 1.1194 + // Write out the resources 1.1195 + if (mResources) { 1.1196 + rv = mResources->Write(aStream); 1.1197 + NS_ENSURE_SUCCESS(rv, rv); 1.1198 + } 1.1199 + 1.1200 + // Write out an end mark at the end. 1.1201 + return aStream->Write8(XBLBinding_Serialize_NoMoreItems); 1.1202 +} 1.1203 + 1.1204 +nsresult 1.1205 +nsXBLPrototypeBinding::ReadContentNode(nsIObjectInputStream* aStream, 1.1206 + nsIDocument* aDocument, 1.1207 + nsNodeInfoManager* aNim, 1.1208 + nsIContent** aContent) 1.1209 +{ 1.1210 + *aContent = nullptr; 1.1211 + 1.1212 + int32_t namespaceID; 1.1213 + nsresult rv = ReadNamespace(aStream, namespaceID); 1.1214 + NS_ENSURE_SUCCESS(rv, rv); 1.1215 + 1.1216 + // There is no content to read so just return. 1.1217 + if (namespaceID == XBLBinding_Serialize_NoContent) 1.1218 + return NS_OK; 1.1219 + 1.1220 + nsCOMPtr<nsIContent> content; 1.1221 + 1.1222 + // If this is a text type, just read the string and return. 1.1223 + if (namespaceID == XBLBinding_Serialize_TextNode || 1.1224 + namespaceID == XBLBinding_Serialize_CDATANode || 1.1225 + namespaceID == XBLBinding_Serialize_CommentNode) { 1.1226 + switch (namespaceID) { 1.1227 + case XBLBinding_Serialize_TextNode: 1.1228 + content = new nsTextNode(aNim); 1.1229 + break; 1.1230 + case XBLBinding_Serialize_CDATANode: 1.1231 + content = new CDATASection(aNim); 1.1232 + break; 1.1233 + case XBLBinding_Serialize_CommentNode: 1.1234 + content = new Comment(aNim); 1.1235 + break; 1.1236 + default: 1.1237 + break; 1.1238 + } 1.1239 + 1.1240 + nsAutoString text; 1.1241 + rv = aStream->ReadString(text); 1.1242 + NS_ENSURE_SUCCESS(rv, rv); 1.1243 + 1.1244 + content->SetText(text, false); 1.1245 + content.swap(*aContent); 1.1246 + return NS_OK; 1.1247 + } 1.1248 + 1.1249 + // Otherwise, it's an element, so read its tag, attributes and children. 1.1250 + nsAutoString prefix, tag; 1.1251 + rv = aStream->ReadString(prefix); 1.1252 + NS_ENSURE_SUCCESS(rv, rv); 1.1253 + 1.1254 + nsCOMPtr<nsIAtom> prefixAtom; 1.1255 + if (!prefix.IsEmpty()) 1.1256 + prefixAtom = do_GetAtom(prefix); 1.1257 + 1.1258 + rv = aStream->ReadString(tag); 1.1259 + NS_ENSURE_SUCCESS(rv, rv); 1.1260 + 1.1261 + nsCOMPtr<nsIAtom> tagAtom = do_GetAtom(tag); 1.1262 + nsCOMPtr<nsINodeInfo> nodeInfo = 1.1263 + aNim->GetNodeInfo(tagAtom, prefixAtom, namespaceID, nsIDOMNode::ELEMENT_NODE); 1.1264 + 1.1265 + uint32_t attrCount; 1.1266 + rv = aStream->Read32(&attrCount); 1.1267 + NS_ENSURE_SUCCESS(rv, rv); 1.1268 + 1.1269 + // Create XUL prototype elements, or regular elements for other namespaces. 1.1270 + // This needs to match the code in nsXBLContentSink::CreateElement. 1.1271 +#ifdef MOZ_XUL 1.1272 + if (namespaceID == kNameSpaceID_XUL) { 1.1273 + nsIURI* documentURI = aDocument->GetDocumentURI(); 1.1274 + 1.1275 + nsRefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement(); 1.1276 + NS_ENSURE_TRUE(prototype, NS_ERROR_OUT_OF_MEMORY); 1.1277 + 1.1278 + prototype->mNodeInfo = nodeInfo; 1.1279 + 1.1280 + nsXULPrototypeAttribute* attrs = nullptr; 1.1281 + if (attrCount > 0) { 1.1282 + attrs = new nsXULPrototypeAttribute[attrCount]; 1.1283 + } 1.1284 + 1.1285 + prototype->mAttributes = attrs; 1.1286 + prototype->mNumAttributes = attrCount; 1.1287 + 1.1288 + for (uint32_t i = 0; i < attrCount; i++) { 1.1289 + rv = ReadNamespace(aStream, namespaceID); 1.1290 + NS_ENSURE_SUCCESS(rv, rv); 1.1291 + 1.1292 + nsAutoString prefix, name, val; 1.1293 + rv = aStream->ReadString(prefix); 1.1294 + NS_ENSURE_SUCCESS(rv, rv); 1.1295 + rv = aStream->ReadString(name); 1.1296 + NS_ENSURE_SUCCESS(rv, rv); 1.1297 + rv = aStream->ReadString(val); 1.1298 + NS_ENSURE_SUCCESS(rv, rv); 1.1299 + 1.1300 + nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(name); 1.1301 + if (namespaceID == kNameSpaceID_None) { 1.1302 + attrs[i].mName.SetTo(nameAtom); 1.1303 + } 1.1304 + else { 1.1305 + nsCOMPtr<nsIAtom> prefixAtom; 1.1306 + if (!prefix.IsEmpty()) 1.1307 + prefixAtom = do_GetAtom(prefix); 1.1308 + 1.1309 + nsCOMPtr<nsINodeInfo> ni = 1.1310 + aNim->GetNodeInfo(nameAtom, prefixAtom, 1.1311 + namespaceID, nsIDOMNode::ATTRIBUTE_NODE); 1.1312 + attrs[i].mName.SetTo(ni); 1.1313 + } 1.1314 + 1.1315 + rv = prototype->SetAttrAt(i, val, documentURI); 1.1316 + NS_ENSURE_SUCCESS(rv, rv); 1.1317 + } 1.1318 + 1.1319 + nsCOMPtr<Element> result; 1.1320 + nsresult rv = 1.1321 + nsXULElement::Create(prototype, aDocument, false, false, getter_AddRefs(result)); 1.1322 + NS_ENSURE_SUCCESS(rv, rv); 1.1323 + content = result; 1.1324 + } 1.1325 + else { 1.1326 +#endif 1.1327 + nsCOMPtr<Element> element; 1.1328 + NS_NewElement(getter_AddRefs(element), nodeInfo.forget(), NOT_FROM_PARSER); 1.1329 + content = element; 1.1330 + 1.1331 + for (uint32_t i = 0; i < attrCount; i++) { 1.1332 + rv = ReadNamespace(aStream, namespaceID); 1.1333 + NS_ENSURE_SUCCESS(rv, rv); 1.1334 + 1.1335 + nsAutoString prefix, name, val; 1.1336 + rv = aStream->ReadString(prefix); 1.1337 + NS_ENSURE_SUCCESS(rv, rv); 1.1338 + rv = aStream->ReadString(name); 1.1339 + NS_ENSURE_SUCCESS(rv, rv); 1.1340 + rv = aStream->ReadString(val); 1.1341 + NS_ENSURE_SUCCESS(rv, rv); 1.1342 + 1.1343 + nsCOMPtr<nsIAtom> prefixAtom; 1.1344 + if (!prefix.IsEmpty()) 1.1345 + prefixAtom = do_GetAtom(prefix); 1.1346 + 1.1347 + nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(name); 1.1348 + content->SetAttr(namespaceID, nameAtom, prefixAtom, val, false); 1.1349 + } 1.1350 + 1.1351 +#ifdef MOZ_XUL 1.1352 + } 1.1353 +#endif 1.1354 + 1.1355 + // Now read the attribute forwarding entries (xbl:inherits) 1.1356 + 1.1357 + int32_t srcNamespaceID, destNamespaceID; 1.1358 + rv = ReadNamespace(aStream, srcNamespaceID); 1.1359 + NS_ENSURE_SUCCESS(rv, rv); 1.1360 + 1.1361 + while (srcNamespaceID != XBLBinding_Serialize_NoMoreAttributes) { 1.1362 + nsAutoString srcAttribute, destAttribute; 1.1363 + rv = aStream->ReadString(srcAttribute); 1.1364 + NS_ENSURE_SUCCESS(rv, rv); 1.1365 + rv = ReadNamespace(aStream, destNamespaceID); 1.1366 + NS_ENSURE_SUCCESS(rv, rv); 1.1367 + rv = aStream->ReadString(destAttribute); 1.1368 + NS_ENSURE_SUCCESS(rv, rv); 1.1369 + 1.1370 + nsCOMPtr<nsIAtom> srcAtom = do_GetAtom(srcAttribute); 1.1371 + nsCOMPtr<nsIAtom> destAtom = do_GetAtom(destAttribute); 1.1372 + 1.1373 + EnsureAttributeTable(); 1.1374 + AddToAttributeTable(srcNamespaceID, srcAtom, destNamespaceID, destAtom, content); 1.1375 + 1.1376 + rv = ReadNamespace(aStream, srcNamespaceID); 1.1377 + NS_ENSURE_SUCCESS(rv, rv); 1.1378 + } 1.1379 + 1.1380 + // Finally, read in the child nodes. 1.1381 + uint32_t childCount; 1.1382 + rv = aStream->Read32(&childCount); 1.1383 + NS_ENSURE_SUCCESS(rv, rv); 1.1384 + 1.1385 + for (uint32_t i = 0; i < childCount; i++) { 1.1386 + nsCOMPtr<nsIContent> child; 1.1387 + ReadContentNode(aStream, aDocument, aNim, getter_AddRefs(child)); 1.1388 + 1.1389 + // Child may be null if this was a comment for example and can just be ignored. 1.1390 + if (child) { 1.1391 + content->AppendChildTo(child, false); 1.1392 + } 1.1393 + } 1.1394 + 1.1395 + content.swap(*aContent); 1.1396 + return NS_OK; 1.1397 +} 1.1398 + 1.1399 +// This structure holds information about a forwarded attribute that needs to be 1.1400 +// written out. This is used because we need several fields passed within the 1.1401 +// enumeration closure. 1.1402 +struct WriteAttributeData 1.1403 +{ 1.1404 + nsXBLPrototypeBinding* binding; 1.1405 + nsIObjectOutputStream* stream; 1.1406 + nsIContent* content; 1.1407 + int32_t srcNamespace; 1.1408 + 1.1409 + WriteAttributeData(nsXBLPrototypeBinding* aBinding, 1.1410 + nsIObjectOutputStream* aStream, 1.1411 + nsIContent* aContent) 1.1412 + : binding(aBinding), stream(aStream), content(aContent) 1.1413 + { } 1.1414 +}; 1.1415 + 1.1416 +static PLDHashOperator 1.1417 +WriteAttribute(nsISupports* aKey, nsXBLAttributeEntry* aEntry, void* aClosure) 1.1418 +{ 1.1419 + WriteAttributeData* data = static_cast<WriteAttributeData *>(aClosure); 1.1420 + nsIObjectOutputStream* stream = data->stream; 1.1421 + const int32_t srcNamespace = data->srcNamespace; 1.1422 + 1.1423 + do { 1.1424 + if (aEntry->GetElement() == data->content) { 1.1425 + data->binding->WriteNamespace(stream, srcNamespace); 1.1426 + stream->WriteWStringZ(nsDependentAtomString(aEntry->GetSrcAttribute()).get()); 1.1427 + data->binding->WriteNamespace(stream, aEntry->GetDstNameSpace()); 1.1428 + stream->WriteWStringZ(nsDependentAtomString(aEntry->GetDstAttribute()).get()); 1.1429 + } 1.1430 + 1.1431 + aEntry = aEntry->GetNext(); 1.1432 + } while (aEntry); 1.1433 + 1.1434 + return PL_DHASH_NEXT; 1.1435 +} 1.1436 + 1.1437 +// WriteAttributeNS is the callback to enumerate over the attribute 1.1438 +// forwarding entries. Since these are stored in a hash of hashes, 1.1439 +// we need to iterate over the inner hashes, calling WriteAttribute 1.1440 +// to do the actual work. 1.1441 +static PLDHashOperator 1.1442 +WriteAttributeNS(const uint32_t &aNamespace, 1.1443 + nsXBLPrototypeBinding::InnerAttributeTable* aXBLAttributes, 1.1444 + void* aClosure) 1.1445 +{ 1.1446 + WriteAttributeData* data = static_cast<WriteAttributeData *>(aClosure); 1.1447 + data->srcNamespace = aNamespace; 1.1448 + aXBLAttributes->EnumerateRead(WriteAttribute, data); 1.1449 + 1.1450 + return PL_DHASH_NEXT; 1.1451 +} 1.1452 + 1.1453 +nsresult 1.1454 +nsXBLPrototypeBinding::WriteContentNode(nsIObjectOutputStream* aStream, 1.1455 + nsIContent* aNode) 1.1456 +{ 1.1457 + nsresult rv; 1.1458 + 1.1459 + if (!aNode->IsElement()) { 1.1460 + // Text is writen out as a single byte for the type, followed by the text. 1.1461 + uint8_t type = XBLBinding_Serialize_NoContent; 1.1462 + switch (aNode->NodeType()) { 1.1463 + case nsIDOMNode::TEXT_NODE: 1.1464 + type = XBLBinding_Serialize_TextNode; 1.1465 + break; 1.1466 + case nsIDOMNode::CDATA_SECTION_NODE: 1.1467 + type = XBLBinding_Serialize_CDATANode; 1.1468 + break; 1.1469 + case nsIDOMNode::COMMENT_NODE: 1.1470 + type = XBLBinding_Serialize_CommentNode; 1.1471 + break; 1.1472 + default: 1.1473 + break; 1.1474 + } 1.1475 + 1.1476 + rv = aStream->Write8(type); 1.1477 + NS_ENSURE_SUCCESS(rv, rv); 1.1478 + 1.1479 + nsAutoString content; 1.1480 + aNode->GetText()->AppendTo(content); 1.1481 + return aStream->WriteWStringZ(content.get()); 1.1482 + } 1.1483 + 1.1484 + // Otherwise, this is an element. 1.1485 + 1.1486 + // Write the namespace id followed by the tag name 1.1487 + rv = WriteNamespace(aStream, aNode->GetNameSpaceID()); 1.1488 + NS_ENSURE_SUCCESS(rv, rv); 1.1489 + 1.1490 + nsAutoString prefixStr; 1.1491 + aNode->NodeInfo()->GetPrefix(prefixStr); 1.1492 + rv = aStream->WriteWStringZ(prefixStr.get()); 1.1493 + NS_ENSURE_SUCCESS(rv, rv); 1.1494 + 1.1495 + rv = aStream->WriteWStringZ(nsDependentAtomString(aNode->Tag()).get()); 1.1496 + NS_ENSURE_SUCCESS(rv, rv); 1.1497 + 1.1498 + // Write attributes 1.1499 + uint32_t count = aNode->GetAttrCount(); 1.1500 + rv = aStream->Write32(count); 1.1501 + NS_ENSURE_SUCCESS(rv, rv); 1.1502 + 1.1503 + uint32_t i; 1.1504 + for (i = 0; i < count; i++) { 1.1505 + // Write out the namespace id, the namespace prefix, the local tag name, 1.1506 + // and the value, in that order. 1.1507 + 1.1508 + const nsAttrName* attr = aNode->GetAttrNameAt(i); 1.1509 + 1.1510 + // XXXndeakin don't write out xbl:inherits? 1.1511 + int32_t namespaceID = attr->NamespaceID(); 1.1512 + rv = WriteNamespace(aStream, namespaceID); 1.1513 + NS_ENSURE_SUCCESS(rv, rv); 1.1514 + 1.1515 + nsAutoString prefixStr; 1.1516 + nsIAtom* prefix = attr->GetPrefix(); 1.1517 + if (prefix) 1.1518 + prefix->ToString(prefixStr); 1.1519 + rv = aStream->WriteWStringZ(prefixStr.get()); 1.1520 + NS_ENSURE_SUCCESS(rv, rv); 1.1521 + 1.1522 + rv = aStream->WriteWStringZ(nsDependentAtomString(attr->LocalName()).get()); 1.1523 + NS_ENSURE_SUCCESS(rv, rv); 1.1524 + 1.1525 + nsAutoString val; 1.1526 + aNode->GetAttr(attr->NamespaceID(), attr->LocalName(), val); 1.1527 + rv = aStream->WriteWStringZ(val.get()); 1.1528 + NS_ENSURE_SUCCESS(rv, rv); 1.1529 + } 1.1530 + 1.1531 + // Write out the attribute fowarding information 1.1532 + if (mAttributeTable) { 1.1533 + WriteAttributeData data(this, aStream, aNode); 1.1534 + mAttributeTable->EnumerateRead(WriteAttributeNS, &data); 1.1535 + } 1.1536 + rv = aStream->Write8(XBLBinding_Serialize_NoMoreAttributes); 1.1537 + NS_ENSURE_SUCCESS(rv, rv); 1.1538 + 1.1539 + // Finally, write out the child nodes. 1.1540 + count = aNode->GetChildCount(); 1.1541 + rv = aStream->Write32(count); 1.1542 + NS_ENSURE_SUCCESS(rv, rv); 1.1543 + 1.1544 + for (i = 0; i < count; i++) { 1.1545 + rv = WriteContentNode(aStream, aNode->GetChildAt(i)); 1.1546 + NS_ENSURE_SUCCESS(rv, rv); 1.1547 + } 1.1548 + 1.1549 + return NS_OK; 1.1550 +} 1.1551 + 1.1552 +nsresult 1.1553 +nsXBLPrototypeBinding::ReadNamespace(nsIObjectInputStream* aStream, 1.1554 + int32_t& aNameSpaceID) 1.1555 +{ 1.1556 + uint8_t namespaceID; 1.1557 + nsresult rv = aStream->Read8(&namespaceID); 1.1558 + NS_ENSURE_SUCCESS(rv, rv); 1.1559 + 1.1560 + if (namespaceID == XBLBinding_Serialize_CustomNamespace) { 1.1561 + nsAutoString namesp; 1.1562 + rv = aStream->ReadString(namesp); 1.1563 + NS_ENSURE_SUCCESS(rv, rv); 1.1564 + 1.1565 + nsContentUtils::NameSpaceManager()->RegisterNameSpace(namesp, aNameSpaceID); 1.1566 + } 1.1567 + else { 1.1568 + aNameSpaceID = namespaceID; 1.1569 + } 1.1570 + 1.1571 + return NS_OK; 1.1572 +} 1.1573 + 1.1574 +nsresult 1.1575 +nsXBLPrototypeBinding::WriteNamespace(nsIObjectOutputStream* aStream, 1.1576 + int32_t aNameSpaceID) 1.1577 +{ 1.1578 + // Namespaces are stored as a single byte id for well-known namespaces. 1.1579 + // This saves time and space as other namespaces aren't very common in 1.1580 + // XBL. If another namespace is used however, the namespace id will be 1.1581 + // XBLBinding_Serialize_CustomNamespace and the string namespace written 1.1582 + // out directly afterwards. 1.1583 + nsresult rv; 1.1584 + 1.1585 + if (aNameSpaceID <= kNameSpaceID_LastBuiltin) { 1.1586 + rv = aStream->Write8((int8_t)aNameSpaceID); 1.1587 + NS_ENSURE_SUCCESS(rv, rv); 1.1588 + } 1.1589 + else { 1.1590 + rv = aStream->Write8(XBLBinding_Serialize_CustomNamespace); 1.1591 + NS_ENSURE_SUCCESS(rv, rv); 1.1592 + 1.1593 + nsAutoString namesp; 1.1594 + nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, namesp); 1.1595 + aStream->WriteWStringZ(namesp.get()); 1.1596 + } 1.1597 + 1.1598 + return NS_OK; 1.1599 +} 1.1600 + 1.1601 + 1.1602 +bool CheckTagNameWhiteList(int32_t aNameSpaceID, nsIAtom *aTagName) 1.1603 +{ 1.1604 + static nsIContent::AttrValuesArray kValidXULTagNames[] = { 1.1605 + &nsGkAtoms::autorepeatbutton, &nsGkAtoms::box, &nsGkAtoms::browser, 1.1606 + &nsGkAtoms::button, &nsGkAtoms::hbox, &nsGkAtoms::image, &nsGkAtoms::menu, 1.1607 + &nsGkAtoms::menubar, &nsGkAtoms::menuitem, &nsGkAtoms::menupopup, 1.1608 + &nsGkAtoms::row, &nsGkAtoms::slider, &nsGkAtoms::spacer, 1.1609 + &nsGkAtoms::splitter, &nsGkAtoms::text, &nsGkAtoms::tree, nullptr}; 1.1610 + 1.1611 + uint32_t i; 1.1612 + if (aNameSpaceID == kNameSpaceID_XUL) { 1.1613 + for (i = 0; kValidXULTagNames[i]; ++i) { 1.1614 + if (aTagName == *(kValidXULTagNames[i])) { 1.1615 + return true; 1.1616 + } 1.1617 + } 1.1618 + } 1.1619 + else if (aNameSpaceID == kNameSpaceID_SVG && 1.1620 + aTagName == nsGkAtoms::generic_) { 1.1621 + return true; 1.1622 + } 1.1623 + 1.1624 + return false; 1.1625 +} 1.1626 + 1.1627 +nsresult 1.1628 +nsXBLPrototypeBinding::ResolveBaseBinding() 1.1629 +{ 1.1630 + if (mCheckedBaseProto) 1.1631 + return NS_OK; 1.1632 + mCheckedBaseProto = true; 1.1633 + 1.1634 + nsCOMPtr<nsIDocument> doc = mXBLDocInfoWeak->GetDocument(); 1.1635 + 1.1636 + // Check for the presence of 'extends' and 'display' attributes 1.1637 + nsAutoString display, extends; 1.1638 + mBinding->GetAttr(kNameSpaceID_None, nsGkAtoms::extends, extends); 1.1639 + if (extends.IsEmpty()) 1.1640 + return NS_OK; 1.1641 + 1.1642 + mBinding->GetAttr(kNameSpaceID_None, nsGkAtoms::display, display); 1.1643 + bool hasDisplay = !display.IsEmpty(); 1.1644 + 1.1645 + nsAutoString value(extends); 1.1646 + 1.1647 + // Now slice 'em up to see what we've got. 1.1648 + nsAutoString prefix; 1.1649 + int32_t offset; 1.1650 + if (hasDisplay) { 1.1651 + offset = display.FindChar(':'); 1.1652 + if (-1 != offset) { 1.1653 + display.Left(prefix, offset); 1.1654 + display.Cut(0, offset+1); 1.1655 + } 1.1656 + } 1.1657 + else { 1.1658 + offset = extends.FindChar(':'); 1.1659 + if (-1 != offset) { 1.1660 + extends.Left(prefix, offset); 1.1661 + extends.Cut(0, offset+1); 1.1662 + display = extends; 1.1663 + } 1.1664 + } 1.1665 + 1.1666 + nsAutoString nameSpace; 1.1667 + 1.1668 + if (!prefix.IsEmpty()) { 1.1669 + mBinding->LookupNamespaceURI(prefix, nameSpace); 1.1670 + if (!nameSpace.IsEmpty()) { 1.1671 + int32_t nameSpaceID = 1.1672 + nsContentUtils::NameSpaceManager()->GetNameSpaceID(nameSpace); 1.1673 + 1.1674 + nsCOMPtr<nsIAtom> tagName = do_GetAtom(display); 1.1675 + // Check the white list 1.1676 + if (!CheckTagNameWhiteList(nameSpaceID, tagName)) { 1.1677 + const char16_t* params[] = { display.get() }; 1.1678 + nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, 1.1679 + NS_LITERAL_CSTRING("XBL"), nullptr, 1.1680 + nsContentUtils::eXBL_PROPERTIES, 1.1681 + "InvalidExtendsBinding", 1.1682 + params, ArrayLength(params), 1.1683 + doc->GetDocumentURI()); 1.1684 + NS_ASSERTION(!nsXBLService::IsChromeOrResourceURI(doc->GetDocumentURI()), 1.1685 + "Invalid extends value"); 1.1686 + return NS_ERROR_ILLEGAL_VALUE; 1.1687 + } 1.1688 + 1.1689 + SetBaseTag(nameSpaceID, tagName); 1.1690 + } 1.1691 + } 1.1692 + 1.1693 + if (hasDisplay || nameSpace.IsEmpty()) { 1.1694 + mBinding->UnsetAttr(kNameSpaceID_None, nsGkAtoms::extends, false); 1.1695 + mBinding->UnsetAttr(kNameSpaceID_None, nsGkAtoms::display, false); 1.1696 + 1.1697 + return NS_NewURI(getter_AddRefs(mBaseBindingURI), value, 1.1698 + doc->GetDocumentCharacterSet().get(), 1.1699 + doc->GetDocBaseURI()); 1.1700 + } 1.1701 + 1.1702 + return NS_OK; 1.1703 +}