123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "mozilla/ArrayUtils.h"
- #include "nsXBLContentSink.h"
- #include "nsIDocument.h"
- #include "nsBindingManager.h"
- #include "nsIDOMNode.h"
- #include "nsGkAtoms.h"
- #include "nsNameSpaceManager.h"
- #include "nsIURI.h"
- #include "nsTextFragment.h"
- #ifdef MOZ_XUL
- #include "nsXULElement.h"
- #endif
- #include "nsXBLProtoImplProperty.h"
- #include "nsXBLProtoImplMethod.h"
- #include "nsXBLProtoImplField.h"
- #include "nsXBLPrototypeBinding.h"
- #include "nsContentUtils.h"
- #include "nsIConsoleService.h"
- #include "nsIScriptError.h"
- #include "nsNodeInfoManager.h"
- #include "nsIPrincipal.h"
- #include "mozilla/dom/Element.h"
- using namespace mozilla;
- using namespace mozilla::dom;
- nsresult
- NS_NewXBLContentSink(nsIXMLContentSink** aResult,
- nsIDocument* aDoc,
- nsIURI* aURI,
- nsISupports* aContainer)
- {
- NS_ENSURE_ARG_POINTER(aResult);
- RefPtr<nsXBLContentSink> it = new nsXBLContentSink();
- nsresult rv = it->Init(aDoc, aURI, aContainer);
- NS_ENSURE_SUCCESS(rv, rv);
- it.forget(aResult);
- return NS_OK;
- }
- nsXBLContentSink::nsXBLContentSink()
- : mState(eXBL_InDocument),
- mSecondaryState(eXBL_None),
- mDocInfo(nullptr),
- mIsChromeOrResource(false),
- mFoundFirstBinding(false),
- mBinding(nullptr),
- mHandler(nullptr),
- mImplementation(nullptr),
- mImplMember(nullptr),
- mImplField(nullptr),
- mProperty(nullptr),
- mMethod(nullptr),
- mField(nullptr)
- {
- mPrettyPrintXML = false;
- }
- nsXBLContentSink::~nsXBLContentSink()
- {
- }
- nsresult
- nsXBLContentSink::Init(nsIDocument* aDoc,
- nsIURI* aURI,
- nsISupports* aContainer)
- {
- nsresult rv;
- rv = nsXMLContentSink::Init(aDoc, aURI, aContainer, nullptr);
- return rv;
- }
- void
- nsXBLContentSink::MaybeStartLayout(bool aIgnorePendingSheets)
- {
- return;
- }
- nsresult
- nsXBLContentSink::FlushText(bool aReleaseTextNode)
- {
- if (mTextLength != 0) {
- const nsASingleFragmentString& text = Substring(mText, mText+mTextLength);
- if (mState == eXBL_InHandlers) {
- NS_ASSERTION(mBinding, "Must have binding here");
- // Get the text and add it to the event handler.
- if (mSecondaryState == eXBL_InHandler)
- mHandler->AppendHandlerText(text);
- mTextLength = 0;
- return NS_OK;
- }
- else if (mState == eXBL_InImplementation) {
- NS_ASSERTION(mBinding, "Must have binding here");
- if (mSecondaryState == eXBL_InConstructor ||
- mSecondaryState == eXBL_InDestructor) {
- // Construct a method for the constructor/destructor.
- nsXBLProtoImplMethod* method;
- if (mSecondaryState == eXBL_InConstructor)
- method = mBinding->GetConstructor();
- else
- method = mBinding->GetDestructor();
- // Get the text and add it to the constructor/destructor.
- method->AppendBodyText(text);
- }
- else if (mSecondaryState == eXBL_InGetter ||
- mSecondaryState == eXBL_InSetter) {
- // Get the text and add it to the getter/setter
- if (mSecondaryState == eXBL_InGetter)
- mProperty->AppendGetterText(text);
- else
- mProperty->AppendSetterText(text);
- }
- else if (mSecondaryState == eXBL_InBody) {
- // Get the text and add it to the method
- if (mMethod)
- mMethod->AppendBodyText(text);
- }
- else if (mSecondaryState == eXBL_InField) {
- // Get the text and add it to the method
- if (mField)
- mField->AppendFieldText(text);
- }
- mTextLength = 0;
- return NS_OK;
- }
- nsIContent* content = GetCurrentContent();
- if (content &&
- (content->NodeInfo()->NamespaceEquals(kNameSpaceID_XBL) ||
- (content->IsXULElement() &&
- !content->IsAnyOfXULElements(nsGkAtoms::label,
- nsGkAtoms::description)))) {
- bool isWS = true;
- if (mTextLength > 0) {
- const char16_t* cp = mText;
- const char16_t* end = mText + mTextLength;
- while (cp < end) {
- char16_t ch = *cp++;
- if (!dom::IsSpaceCharacter(ch)) {
- isWS = false;
- break;
- }
- }
- }
- if (isWS && mTextLength > 0) {
- mTextLength = 0;
- // Make sure to drop the textnode, if any
- return nsXMLContentSink::FlushText(aReleaseTextNode);
- }
- }
- }
- return nsXMLContentSink::FlushText(aReleaseTextNode);
- }
- NS_IMETHODIMP
- nsXBLContentSink::ReportError(const char16_t* aErrorText,
- const char16_t* aSourceText,
- nsIScriptError *aError,
- bool *_retval)
- {
- NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
- // XXX FIXME This function overrides and calls on
- // nsXMLContentSink::ReportError, and probably should die. See bug 347826.
- // XXX We should make sure the binding has no effect, but that it also
- // gets destroyed properly without leaking. Perhaps we should even
- // ensure that the content that was bound is displayed with no
- // binding.
- #ifdef DEBUG
- // Report the error to stderr.
- fprintf(stderr,
- "\n%s\n%s\n\n",
- NS_LossyConvertUTF16toASCII(aErrorText).get(),
- NS_LossyConvertUTF16toASCII(aSourceText).get());
- #endif
- // Most of what this does won't be too useful, but whatever...
- // nsXMLContentSink::ReportError will handle the console logging.
- return nsXMLContentSink::ReportError(aErrorText,
- aSourceText,
- aError,
- _retval);
- }
- nsresult
- nsXBLContentSink::ReportUnexpectedElement(nsIAtom* aElementName,
- uint32_t aLineNumber)
- {
- // XXX we should really somehow stop the parse and drop the binding
- // instead of just letting the XML sink build the content model like
- // we do...
- mState = eXBL_Error;
- nsAutoString elementName;
- aElementName->ToString(elementName);
- const char16_t* params[] = { elementName.get() };
- return nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
- NS_LITERAL_CSTRING("XBL Content Sink"),
- mDocument,
- nsContentUtils::eXBL_PROPERTIES,
- "UnexpectedElement",
- params, ArrayLength(params),
- nullptr,
- EmptyString() /* source line */,
- aLineNumber);
- }
- void
- nsXBLContentSink::AddMember(nsXBLProtoImplMember* aMember)
- {
- // Add this member to our chain.
- if (mImplMember)
- mImplMember->SetNext(aMember); // Already have a chain. Just append to the end.
- else
- mImplementation->SetMemberList(aMember); // We're the first member in the chain.
- mImplMember = aMember; // Adjust our pointer to point to the new last member in the chain.
- }
- void
- nsXBLContentSink::AddField(nsXBLProtoImplField* aField)
- {
- // Add this field to our chain.
- if (mImplField)
- mImplField->SetNext(aField); // Already have a chain. Just append to the end.
- else
- mImplementation->SetFieldList(aField); // We're the first member in the chain.
- mImplField = aField; // Adjust our pointer to point to the new last field in the chain.
- }
- NS_IMETHODIMP
- nsXBLContentSink::HandleStartElement(const char16_t *aName,
- const char16_t **aAtts,
- uint32_t aAttsCount,
- uint32_t aLineNumber)
- {
- nsresult rv = nsXMLContentSink::HandleStartElement(aName, aAtts, aAttsCount,
- aLineNumber);
- if (NS_FAILED(rv))
- return rv;
- if (mState == eXBL_InBinding && !mBinding) {
- rv = ConstructBinding(aLineNumber);
- if (NS_FAILED(rv))
- return rv;
-
- // mBinding may still be null, if the binding had no id. If so,
- // we'll deal with that later in the sink.
- }
- return rv;
- }
- NS_IMETHODIMP
- nsXBLContentSink::HandleEndElement(const char16_t *aName)
- {
- FlushText();
- if (mState != eXBL_InDocument) {
- int32_t nameSpaceID;
- nsCOMPtr<nsIAtom> prefix, localName;
- nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
- getter_AddRefs(localName), &nameSpaceID);
- if (nameSpaceID == kNameSpaceID_XBL) {
- if (mState == eXBL_Error) {
- // Check whether we've opened this tag before; we may not have if
- // it was a real XBL tag before the error occurred.
- if (!GetCurrentContent()->NodeInfo()->Equals(localName,
- nameSpaceID)) {
- // OK, this tag was never opened as far as the XML sink is
- // concerned. Just drop the HandleEndElement
- return NS_OK;
- }
- }
- else if (mState == eXBL_InHandlers) {
- if (localName == nsGkAtoms::handlers) {
- mState = eXBL_InBinding;
- mHandler = nullptr;
- }
- else if (localName == nsGkAtoms::handler)
- mSecondaryState = eXBL_None;
- return NS_OK;
- }
- else if (mState == eXBL_InResources) {
- if (localName == nsGkAtoms::resources)
- mState = eXBL_InBinding;
- return NS_OK;
- }
- else if (mState == eXBL_InImplementation) {
- if (localName == nsGkAtoms::implementation)
- mState = eXBL_InBinding;
- else if (localName == nsGkAtoms::property) {
- mSecondaryState = eXBL_None;
- mProperty = nullptr;
- }
- else if (localName == nsGkAtoms::method) {
- mSecondaryState = eXBL_None;
- mMethod = nullptr;
- }
- else if (localName == nsGkAtoms::field) {
- mSecondaryState = eXBL_None;
- mField = nullptr;
- }
- else if (localName == nsGkAtoms::constructor ||
- localName == nsGkAtoms::destructor)
- mSecondaryState = eXBL_None;
- else if (localName == nsGkAtoms::getter ||
- localName == nsGkAtoms::setter)
- mSecondaryState = eXBL_InProperty;
- else if (localName == nsGkAtoms::parameter ||
- localName == nsGkAtoms::body)
- mSecondaryState = eXBL_InMethod;
- return NS_OK;
- }
- else if (mState == eXBL_InBindings &&
- localName == nsGkAtoms::bindings) {
- mState = eXBL_InDocument;
- }
-
- nsresult rv = nsXMLContentSink::HandleEndElement(aName);
- if (NS_FAILED(rv))
- return rv;
- if (mState == eXBL_InBinding && localName == nsGkAtoms::binding) {
- mState = eXBL_InBindings;
- if (mBinding) { // See comment in HandleStartElement()
- mBinding->Initialize();
- mBinding = nullptr; // Clear our current binding ref.
- }
- }
- return NS_OK;
- }
- }
- return nsXMLContentSink::HandleEndElement(aName);
- }
- NS_IMETHODIMP
- nsXBLContentSink::HandleCDataSection(const char16_t *aData,
- uint32_t aLength)
- {
- if (mState == eXBL_InHandlers || mState == eXBL_InImplementation)
- return AddText(aData, aLength);
- return nsXMLContentSink::HandleCDataSection(aData, aLength);
- }
- #define ENSURE_XBL_STATE(_cond) \
- PR_BEGIN_MACRO \
- if (!(_cond)) { ReportUnexpectedElement(aTagName, aLineNumber); return true; } \
- PR_END_MACRO
- bool
- nsXBLContentSink::OnOpenContainer(const char16_t **aAtts,
- uint32_t aAttsCount,
- int32_t aNameSpaceID,
- nsIAtom* aTagName,
- uint32_t aLineNumber)
- {
- if (mState == eXBL_Error) {
- return true;
- }
-
- if (aNameSpaceID != kNameSpaceID_XBL) {
- // Construct non-XBL nodes
- return true;
- }
- bool ret = true;
- if (aTagName == nsGkAtoms::bindings) {
- ENSURE_XBL_STATE(mState == eXBL_InDocument);
- NS_ASSERTION(mDocument, "Must have a document!");
- RefPtr<nsXBLDocumentInfo> info = new nsXBLDocumentInfo(mDocument);
- // We keep a weak ref. We're creating a cycle between doc/binding manager/doc info.
- mDocInfo = info;
- if (!mDocInfo) {
- mState = eXBL_Error;
- return true;
- }
- mDocument->BindingManager()->PutXBLDocumentInfo(mDocInfo);
- nsIURI *uri = mDocument->GetDocumentURI();
- bool isChrome = false;
- bool isRes = false;
- uri->SchemeIs("chrome", &isChrome);
- uri->SchemeIs("resource", &isRes);
- mIsChromeOrResource = isChrome || isRes;
- mState = eXBL_InBindings;
- }
- else if (aTagName == nsGkAtoms::binding) {
- ENSURE_XBL_STATE(mState == eXBL_InBindings);
- mState = eXBL_InBinding;
- }
- else if (aTagName == nsGkAtoms::handlers) {
- ENSURE_XBL_STATE(mState == eXBL_InBinding && mBinding);
- mState = eXBL_InHandlers;
- ret = false;
- }
- else if (aTagName == nsGkAtoms::handler) {
- ENSURE_XBL_STATE(mState == eXBL_InHandlers);
- mSecondaryState = eXBL_InHandler;
- ConstructHandler(aAtts, aLineNumber);
- ret = false;
- }
- else if (aTagName == nsGkAtoms::resources) {
- ENSURE_XBL_STATE(mState == eXBL_InBinding && mBinding);
- mState = eXBL_InResources;
- // Note that this mState will cause us to return false, so no need
- // to set ret to false.
- }
- else if (aTagName == nsGkAtoms::stylesheet || aTagName == nsGkAtoms::image) {
- ENSURE_XBL_STATE(mState == eXBL_InResources);
- NS_ASSERTION(mBinding, "Must have binding here");
- ConstructResource(aAtts, aTagName);
- }
- else if (aTagName == nsGkAtoms::implementation) {
- ENSURE_XBL_STATE(mState == eXBL_InBinding && mBinding);
- mState = eXBL_InImplementation;
- ConstructImplementation(aAtts);
- // Note that this mState will cause us to return false, so no need
- // to set ret to false.
- }
- else if (aTagName == nsGkAtoms::constructor) {
- ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
- mSecondaryState == eXBL_None);
- NS_ASSERTION(mBinding, "Must have binding here");
-
- mSecondaryState = eXBL_InConstructor;
- nsAutoString name;
- if (!mCurrentBindingID.IsEmpty()) {
- name.Assign(mCurrentBindingID);
- name.AppendLiteral("_XBL_Constructor");
- } else {
- name.AppendLiteral("XBL_Constructor");
- }
- nsXBLProtoImplAnonymousMethod* newMethod =
- new nsXBLProtoImplAnonymousMethod(name.get());
- newMethod->SetLineNumber(aLineNumber);
- mBinding->SetConstructor(newMethod);
- AddMember(newMethod);
- }
- else if (aTagName == nsGkAtoms::destructor) {
- ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
- mSecondaryState == eXBL_None);
- NS_ASSERTION(mBinding, "Must have binding here");
- mSecondaryState = eXBL_InDestructor;
- nsAutoString name;
- if (!mCurrentBindingID.IsEmpty()) {
- name.Assign(mCurrentBindingID);
- name.AppendLiteral("_XBL_Destructor");
- } else {
- name.AppendLiteral("XBL_Destructor");
- }
- nsXBLProtoImplAnonymousMethod* newMethod =
- new nsXBLProtoImplAnonymousMethod(name.get());
- newMethod->SetLineNumber(aLineNumber);
- mBinding->SetDestructor(newMethod);
- AddMember(newMethod);
- }
- else if (aTagName == nsGkAtoms::field) {
- ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
- mSecondaryState == eXBL_None);
- NS_ASSERTION(mBinding, "Must have binding here");
- mSecondaryState = eXBL_InField;
- ConstructField(aAtts, aLineNumber);
- }
- else if (aTagName == nsGkAtoms::property) {
- ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
- mSecondaryState == eXBL_None);
- NS_ASSERTION(mBinding, "Must have binding here");
- mSecondaryState = eXBL_InProperty;
- ConstructProperty(aAtts, aLineNumber);
- }
- else if (aTagName == nsGkAtoms::getter) {
- ENSURE_XBL_STATE(mSecondaryState == eXBL_InProperty && mProperty);
- NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
- mProperty->SetGetterLineNumber(aLineNumber);
- mSecondaryState = eXBL_InGetter;
- }
- else if (aTagName == nsGkAtoms::setter) {
- ENSURE_XBL_STATE(mSecondaryState == eXBL_InProperty && mProperty);
- NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
- mProperty->SetSetterLineNumber(aLineNumber);
- mSecondaryState = eXBL_InSetter;
- }
- else if (aTagName == nsGkAtoms::method) {
- ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
- mSecondaryState == eXBL_None);
- NS_ASSERTION(mBinding, "Must have binding here");
- mSecondaryState = eXBL_InMethod;
- ConstructMethod(aAtts);
- }
- else if (aTagName == nsGkAtoms::parameter) {
- ENSURE_XBL_STATE(mSecondaryState == eXBL_InMethod && mMethod);
- NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
- ConstructParameter(aAtts);
- }
- else if (aTagName == nsGkAtoms::body) {
- ENSURE_XBL_STATE(mSecondaryState == eXBL_InMethod && mMethod);
- NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
- // stash away the line number
- mMethod->SetLineNumber(aLineNumber);
- mSecondaryState = eXBL_InBody;
- }
- return ret && mState != eXBL_InResources && mState != eXBL_InImplementation;
- }
- #undef ENSURE_XBL_STATE
- nsresult
- nsXBLContentSink::ConstructBinding(uint32_t aLineNumber)
- {
- nsCOMPtr<nsIContent> binding = GetCurrentContent();
- binding->GetAttr(kNameSpaceID_None, nsGkAtoms::id, mCurrentBindingID);
- NS_ConvertUTF16toUTF8 cid(mCurrentBindingID);
- nsresult rv = NS_OK;
- // Don't create a binding with no id. nsXBLPrototypeBinding::Read also
- // performs this check.
- if (!cid.IsEmpty()) {
- mBinding = new nsXBLPrototypeBinding();
- rv = mBinding->Init(cid, mDocInfo, binding, !mFoundFirstBinding);
- if (NS_SUCCEEDED(rv) &&
- NS_SUCCEEDED(mDocInfo->SetPrototypeBinding(cid, mBinding))) {
- if (!mFoundFirstBinding) {
- mFoundFirstBinding = true;
- mDocInfo->SetFirstPrototypeBinding(mBinding);
- }
- binding->UnsetAttr(kNameSpaceID_None, nsGkAtoms::id, false);
- } else {
- delete mBinding;
- mBinding = nullptr;
- }
- } else {
- nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
- NS_LITERAL_CSTRING("XBL Content Sink"), nullptr,
- nsContentUtils::eXBL_PROPERTIES,
- "MissingIdAttr", nullptr, 0,
- mDocumentURI,
- EmptyString(),
- aLineNumber);
- }
- return rv;
- }
- static bool
- FindValue(const char16_t **aAtts, nsIAtom *aAtom, const char16_t **aResult)
- {
- nsCOMPtr<nsIAtom> prefix, localName;
- for (; *aAtts; aAtts += 2) {
- int32_t nameSpaceID;
- nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
- getter_AddRefs(localName), &nameSpaceID);
- // Is this attribute one of the ones we care about?
- if (nameSpaceID == kNameSpaceID_None && localName == aAtom) {
- *aResult = aAtts[1];
- return true;
- }
- }
- return false;
- }
- void
- nsXBLContentSink::ConstructHandler(const char16_t **aAtts, uint32_t aLineNumber)
- {
- const char16_t* event = nullptr;
- const char16_t* modifiers = nullptr;
- const char16_t* button = nullptr;
- const char16_t* clickcount = nullptr;
- const char16_t* keycode = nullptr;
- const char16_t* charcode = nullptr;
- const char16_t* phase = nullptr;
- const char16_t* command = nullptr;
- const char16_t* action = nullptr;
- const char16_t* group = nullptr;
- const char16_t* preventdefault = nullptr;
- const char16_t* allowuntrusted = nullptr;
- nsCOMPtr<nsIAtom> prefix, localName;
- for (; *aAtts; aAtts += 2) {
- int32_t nameSpaceID;
- nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
- getter_AddRefs(localName), &nameSpaceID);
- if (nameSpaceID != kNameSpaceID_None) {
- continue;
- }
- // Is this attribute one of the ones we care about?
- if (localName == nsGkAtoms::event)
- event = aAtts[1];
- else if (localName == nsGkAtoms::modifiers)
- modifiers = aAtts[1];
- else if (localName == nsGkAtoms::button)
- button = aAtts[1];
- else if (localName == nsGkAtoms::clickcount)
- clickcount = aAtts[1];
- else if (localName == nsGkAtoms::keycode)
- keycode = aAtts[1];
- else if (localName == nsGkAtoms::key || localName == nsGkAtoms::charcode)
- charcode = aAtts[1];
- else if (localName == nsGkAtoms::phase)
- phase = aAtts[1];
- else if (localName == nsGkAtoms::command)
- command = aAtts[1];
- else if (localName == nsGkAtoms::action)
- action = aAtts[1];
- else if (localName == nsGkAtoms::group)
- group = aAtts[1];
- else if (localName == nsGkAtoms::preventdefault)
- preventdefault = aAtts[1];
- else if (localName == nsGkAtoms::allowuntrusted)
- allowuntrusted = aAtts[1];
- }
- if (command && !mIsChromeOrResource) {
- // Make sure the XBL doc is chrome or resource if we have a command
- // shorthand syntax.
- mState = eXBL_Error;
- nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
- NS_LITERAL_CSTRING("XBL Content Sink"),
- mDocument,
- nsContentUtils::eXBL_PROPERTIES,
- "CommandNotInChrome", nullptr, 0,
- nullptr,
- EmptyString() /* source line */,
- aLineNumber);
- return; // Don't even make this handler.
- }
- // All of our pointers are now filled in. Construct our handler with all of
- // these parameters.
- nsXBLPrototypeHandler* newHandler;
- newHandler = new nsXBLPrototypeHandler(event, phase, action, command,
- keycode, charcode, modifiers, button,
- clickcount, group, preventdefault,
- allowuntrusted, mBinding, aLineNumber);
- // Add this handler to our chain of handlers.
- if (mHandler) {
- // Already have a chain. Just append to the end.
- mHandler->SetNextHandler(newHandler);
- } else {
- // We're the first handler in the chain.
- mBinding->SetPrototypeHandlers(newHandler);
- }
- // Adjust our mHandler pointer to point to the new last handler in the
- // chain.
- mHandler = newHandler;
- }
- void
- nsXBLContentSink::ConstructResource(const char16_t **aAtts,
- nsIAtom* aResourceType)
- {
- if (!mBinding)
- return;
- const char16_t* src = nullptr;
- if (FindValue(aAtts, nsGkAtoms::src, &src)) {
- mBinding->AddResource(aResourceType, nsDependentString(src));
- }
- }
- void
- nsXBLContentSink::ConstructImplementation(const char16_t **aAtts)
- {
- mImplementation = nullptr;
- mImplMember = nullptr;
- mImplField = nullptr;
-
- if (!mBinding)
- return;
- const char16_t* name = nullptr;
- nsCOMPtr<nsIAtom> prefix, localName;
- for (; *aAtts; aAtts += 2) {
- int32_t nameSpaceID;
- nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
- getter_AddRefs(localName), &nameSpaceID);
- if (nameSpaceID != kNameSpaceID_None) {
- continue;
- }
- // Is this attribute one of the ones we care about?
- if (localName == nsGkAtoms::name) {
- name = aAtts[1];
- }
- else if (localName == nsGkAtoms::implements) {
- // Only allow implementation of interfaces via XBL if the principal of
- // our XBL document is the system principal.
- if (nsContentUtils::IsSystemPrincipal(mDocument->NodePrincipal())) {
- mBinding->ConstructInterfaceTable(nsDependentString(aAtts[1]));
- }
- }
- }
- NS_NewXBLProtoImpl(mBinding, name, &mImplementation);
- }
- void
- nsXBLContentSink::ConstructField(const char16_t **aAtts, uint32_t aLineNumber)
- {
- const char16_t* name = nullptr;
- const char16_t* readonly = nullptr;
- nsCOMPtr<nsIAtom> prefix, localName;
- for (; *aAtts; aAtts += 2) {
- int32_t nameSpaceID;
- nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
- getter_AddRefs(localName), &nameSpaceID);
- if (nameSpaceID != kNameSpaceID_None) {
- continue;
- }
- // Is this attribute one of the ones we care about?
- if (localName == nsGkAtoms::name) {
- name = aAtts[1];
- }
- else if (localName == nsGkAtoms::readonly) {
- readonly = aAtts[1];
- }
- }
- if (name) {
- // All of our pointers are now filled in. Construct our field with all of
- // these parameters.
- mField = new nsXBLProtoImplField(name, readonly);
- mField->SetLineNumber(aLineNumber);
- AddField(mField);
- }
- }
- void
- nsXBLContentSink::ConstructProperty(const char16_t **aAtts, uint32_t aLineNumber)
- {
- const char16_t* name = nullptr;
- const char16_t* readonly = nullptr;
- const char16_t* onget = nullptr;
- const char16_t* onset = nullptr;
- bool exposeToUntrustedContent = false;
- nsCOMPtr<nsIAtom> prefix, localName;
- for (; *aAtts; aAtts += 2) {
- int32_t nameSpaceID;
- nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
- getter_AddRefs(localName), &nameSpaceID);
- if (nameSpaceID != kNameSpaceID_None) {
- continue;
- }
- // Is this attribute one of the ones we care about?
- if (localName == nsGkAtoms::name) {
- name = aAtts[1];
- }
- else if (localName == nsGkAtoms::readonly) {
- readonly = aAtts[1];
- }
- else if (localName == nsGkAtoms::onget) {
- onget = aAtts[1];
- }
- else if (localName == nsGkAtoms::onset) {
- onset = aAtts[1];
- }
- else if (localName == nsGkAtoms::exposeToUntrustedContent &&
- nsDependentString(aAtts[1]).EqualsLiteral("true"))
- {
- exposeToUntrustedContent = true;
- }
- }
- if (name) {
- // All of our pointers are now filled in. Construct our property with all of
- // these parameters.
- mProperty = new nsXBLProtoImplProperty(name, onget, onset, readonly, aLineNumber);
- if (exposeToUntrustedContent) {
- mProperty->SetExposeToUntrustedContent(true);
- }
- AddMember(mProperty);
- }
- }
- void
- nsXBLContentSink::ConstructMethod(const char16_t **aAtts)
- {
- mMethod = nullptr;
- const char16_t* name = nullptr;
- const char16_t* expose = nullptr;
- if (FindValue(aAtts, nsGkAtoms::name, &name)) {
- mMethod = new nsXBLProtoImplMethod(name);
- if (FindValue(aAtts, nsGkAtoms::exposeToUntrustedContent, &expose) &&
- nsDependentString(expose).EqualsLiteral("true"))
- {
- mMethod->SetExposeToUntrustedContent(true);
- }
- }
- if (mMethod) {
- AddMember(mMethod);
- }
- }
- void
- nsXBLContentSink::ConstructParameter(const char16_t **aAtts)
- {
- if (!mMethod)
- return;
- const char16_t* name = nullptr;
- if (FindValue(aAtts, nsGkAtoms::name, &name)) {
- mMethod->AddParameter(nsDependentString(name));
- }
- }
- nsresult
- nsXBLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
- mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
- nsIContent** aResult, bool* aAppendContent,
- FromParser aFromParser)
- {
- #ifdef MOZ_XUL
- if (!aNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
- #endif
- return nsXMLContentSink::CreateElement(aAtts, aAttsCount, aNodeInfo,
- aLineNumber, aResult,
- aAppendContent, aFromParser);
- #ifdef MOZ_XUL
- }
- // Note that this needs to match the code in nsXBLPrototypeBinding::ReadContentNode.
- *aAppendContent = true;
- RefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement();
- prototype->mNodeInfo = aNodeInfo;
- AddAttributesToXULPrototype(aAtts, aAttsCount, prototype);
- Element* result;
- nsresult rv = nsXULElement::Create(prototype, mDocument, false, false, &result);
- *aResult = result;
- return rv;
- #endif
- }
- nsresult
- nsXBLContentSink::AddAttributes(const char16_t** aAtts,
- nsIContent* aContent)
- {
- if (aContent->IsXULElement())
- return NS_OK; // Nothing to do, since the proto already has the attrs.
- return nsXMLContentSink::AddAttributes(aAtts, aContent);
- }
- #ifdef MOZ_XUL
- nsresult
- nsXBLContentSink::AddAttributesToXULPrototype(const char16_t **aAtts,
- uint32_t aAttsCount,
- nsXULPrototypeElement* aElement)
- {
- // Add tag attributes to the element
- nsresult rv;
- // Create storage for the attributes
- nsXULPrototypeAttribute* attrs = nullptr;
- if (aAttsCount > 0) {
- attrs = new nsXULPrototypeAttribute[aAttsCount];
- }
- aElement->mAttributes = attrs;
- aElement->mNumAttributes = aAttsCount;
- // Copy the attributes into the prototype
- nsCOMPtr<nsIAtom> prefix, localName;
- uint32_t i;
- for (i = 0; i < aAttsCount; ++i) {
- int32_t nameSpaceID;
- nsContentUtils::SplitExpatName(aAtts[i * 2], getter_AddRefs(prefix),
- getter_AddRefs(localName), &nameSpaceID);
- if (nameSpaceID == kNameSpaceID_None) {
- attrs[i].mName.SetTo(localName);
- }
- else {
- RefPtr<NodeInfo> ni;
- ni = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
- nsIDOMNode::ATTRIBUTE_NODE);
- attrs[i].mName.SetTo(ni);
- }
-
- rv = aElement->SetAttrAt(i, nsDependentString(aAtts[i * 2 + 1]),
- mDocumentURI);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
- #endif
|