LCOV - code coverage report
Current view: directory - content/xbl/src - nsXBLContentSink.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 464 0 0.0 %
Date: 2012-06-02 Functions: 27 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   David Hyatt <hyatt@netscape.com> (Original Author)
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "mozilla/Util.h"
      40                 : 
      41                 : #include "nsXBLContentSink.h"
      42                 : #include "nsIDocument.h"
      43                 : #include "nsBindingManager.h"
      44                 : #include "nsIDOMNode.h"
      45                 : #include "nsIParser.h"
      46                 : #include "nsGkAtoms.h"
      47                 : #include "nsINameSpaceManager.h"
      48                 : #include "nsHTMLTokens.h"
      49                 : #include "nsIURI.h"
      50                 : #include "nsTextFragment.h"
      51                 : #ifdef MOZ_XUL
      52                 : #include "nsXULElement.h"
      53                 : #endif
      54                 : #include "nsXBLProtoImplProperty.h"
      55                 : #include "nsXBLProtoImplMethod.h"
      56                 : #include "nsXBLProtoImplField.h"
      57                 : #include "nsXBLPrototypeBinding.h"
      58                 : #include "nsContentUtils.h"
      59                 : #include "nsIConsoleService.h"
      60                 : #include "nsIScriptError.h"
      61                 : #include "nsNodeInfoManager.h"
      62                 : #include "nsINodeInfo.h"
      63                 : #include "nsIPrincipal.h"
      64                 : #include "mozilla/dom/Element.h"
      65                 : 
      66                 : using namespace mozilla;
      67                 : using namespace mozilla::dom;
      68                 : 
      69                 : nsresult
      70               0 : NS_NewXBLContentSink(nsIXMLContentSink** aResult,
      71                 :                      nsIDocument* aDoc,
      72                 :                      nsIURI* aURI,
      73                 :                      nsISupports* aContainer)
      74                 : {
      75               0 :   NS_ENSURE_ARG_POINTER(aResult);
      76                 : 
      77               0 :   nsXBLContentSink* it = new nsXBLContentSink();
      78               0 :   NS_ENSURE_TRUE(it, NS_ERROR_OUT_OF_MEMORY);
      79                 : 
      80               0 :   nsCOMPtr<nsIXMLContentSink> kungFuDeathGrip = it;
      81               0 :   nsresult rv = it->Init(aDoc, aURI, aContainer);
      82               0 :   NS_ENSURE_SUCCESS(rv, rv);
      83                 : 
      84               0 :   return CallQueryInterface(it, aResult);
      85                 : }
      86                 : 
      87               0 : nsXBLContentSink::nsXBLContentSink()
      88                 :   : mState(eXBL_InDocument),
      89                 :     mSecondaryState(eXBL_None),
      90                 :     mDocInfo(nsnull),
      91                 :     mIsChromeOrResource(false),
      92                 :     mFoundFirstBinding(false),    
      93                 :     mBinding(nsnull),
      94                 :     mHandler(nsnull),
      95                 :     mImplementation(nsnull),
      96                 :     mImplMember(nsnull),
      97                 :     mImplField(nsnull),
      98                 :     mProperty(nsnull),
      99                 :     mMethod(nsnull),
     100               0 :     mField(nsnull)
     101                 : {
     102               0 :   mPrettyPrintXML = false;
     103               0 : }
     104                 : 
     105               0 : nsXBLContentSink::~nsXBLContentSink()
     106                 : {
     107               0 : }
     108                 : 
     109                 : nsresult
     110               0 : nsXBLContentSink::Init(nsIDocument* aDoc,
     111                 :                        nsIURI* aURI,
     112                 :                        nsISupports* aContainer)
     113                 : {
     114                 :   nsresult rv;
     115               0 :   rv = nsXMLContentSink::Init(aDoc, aURI, aContainer, nsnull);
     116               0 :   return rv;
     117                 : }
     118                 : 
     119                 : void
     120               0 : nsXBLContentSink::MaybeStartLayout(bool aIgnorePendingSheets)
     121                 : {
     122                 :   return;
     123                 : }
     124                 : 
     125                 : nsresult
     126               0 : nsXBLContentSink::FlushText(bool aReleaseTextNode)
     127                 : {
     128               0 :   if (mTextLength != 0) {
     129               0 :     const nsASingleFragmentString& text = Substring(mText, mText+mTextLength);
     130               0 :     if (mState == eXBL_InHandlers) {
     131               0 :       NS_ASSERTION(mBinding, "Must have binding here");
     132                 :       // Get the text and add it to the event handler.
     133               0 :       if (mSecondaryState == eXBL_InHandler)
     134               0 :         mHandler->AppendHandlerText(text);
     135               0 :       mTextLength = 0;
     136               0 :       return NS_OK;
     137                 :     }
     138               0 :     else if (mState == eXBL_InImplementation) {
     139               0 :       NS_ASSERTION(mBinding, "Must have binding here");
     140               0 :       if (mSecondaryState == eXBL_InConstructor ||
     141                 :           mSecondaryState == eXBL_InDestructor) {
     142                 :         // Construct a method for the constructor/destructor.
     143                 :         nsXBLProtoImplMethod* method;
     144               0 :         if (mSecondaryState == eXBL_InConstructor)
     145               0 :           method = mBinding->GetConstructor();
     146                 :         else
     147               0 :           method = mBinding->GetDestructor();
     148                 : 
     149                 :         // Get the text and add it to the constructor/destructor.
     150               0 :         method->AppendBodyText(text);
     151                 :       }
     152               0 :       else if (mSecondaryState == eXBL_InGetter ||
     153                 :                mSecondaryState == eXBL_InSetter) {
     154                 :         // Get the text and add it to the getter/setter
     155               0 :         if (mSecondaryState == eXBL_InGetter)
     156               0 :           mProperty->AppendGetterText(text);
     157                 :         else
     158               0 :           mProperty->AppendSetterText(text);
     159                 :       }
     160               0 :       else if (mSecondaryState == eXBL_InBody) {
     161                 :         // Get the text and add it to the method
     162               0 :         if (mMethod)
     163               0 :           mMethod->AppendBodyText(text);
     164                 :       }
     165               0 :       else if (mSecondaryState == eXBL_InField) {
     166                 :         // Get the text and add it to the method
     167               0 :         if (mField)
     168               0 :           mField->AppendFieldText(text);
     169                 :       }
     170               0 :       mTextLength = 0;
     171               0 :       return NS_OK;
     172                 :     }
     173                 : 
     174               0 :     nsIContent* content = GetCurrentContent();
     175               0 :     if (content &&
     176               0 :         (content->NodeInfo()->NamespaceEquals(kNameSpaceID_XBL) ||
     177               0 :          (content->NodeInfo()->NamespaceEquals(kNameSpaceID_XUL) &&
     178               0 :           content->Tag() != nsGkAtoms::label &&
     179               0 :           content->Tag() != nsGkAtoms::description))) {
     180                 : 
     181               0 :       bool isWS = true;
     182               0 :       if (mTextLength > 0) {
     183               0 :         const PRUnichar* cp = mText;
     184               0 :         const PRUnichar* end = mText + mTextLength;
     185               0 :         while (cp < end) {
     186               0 :           PRUnichar ch = *cp++;
     187               0 :           if (!XP_IS_SPACE(ch)) {
     188               0 :             isWS = false;
     189               0 :             break;
     190                 :           }
     191                 :         }
     192                 :       }
     193                 : 
     194               0 :       if (isWS && mTextLength > 0) {
     195               0 :         mTextLength = 0;
     196                 :         // Make sure to drop the textnode, if any
     197               0 :         return nsXMLContentSink::FlushText(aReleaseTextNode);
     198                 :       }
     199                 :     }
     200                 :   }
     201                 : 
     202               0 :   return nsXMLContentSink::FlushText(aReleaseTextNode);
     203                 : }
     204                 : 
     205                 : NS_IMETHODIMP
     206               0 : nsXBLContentSink::ReportError(const PRUnichar* aErrorText, 
     207                 :                               const PRUnichar* aSourceText,
     208                 :                               nsIScriptError *aError,
     209                 :                               bool *_retval)
     210                 : {
     211               0 :   NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
     212                 : 
     213                 :   // XXX FIXME This function overrides and calls on
     214                 :   // nsXMLContentSink::ReportError, and probably should die.  See bug 347826.
     215                 : 
     216                 :   // XXX We should make sure the binding has no effect, but that it also
     217                 :   // gets destroyed properly without leaking.  Perhaps we should even
     218                 :   // ensure that the content that was bound is displayed with no
     219                 :   // binding.
     220                 : 
     221                 : #ifdef DEBUG
     222                 :   // Report the error to stderr.
     223                 :   fprintf(stderr,
     224                 :           "\n%s\n%s\n\n",
     225               0 :           NS_LossyConvertUTF16toASCII(aErrorText).get(),
     226               0 :           NS_LossyConvertUTF16toASCII(aSourceText).get());
     227                 : #endif
     228                 : 
     229                 :   // Most of what this does won't be too useful, but whatever...
     230                 :   // nsXMLContentSink::ReportError will handle the console logging.
     231                 :   return nsXMLContentSink::ReportError(aErrorText, 
     232                 :                                        aSourceText, 
     233                 :                                        aError,
     234               0 :                                        _retval);
     235                 : }
     236                 : 
     237                 : nsresult
     238               0 : nsXBLContentSink::ReportUnexpectedElement(nsIAtom* aElementName,
     239                 :                                           PRUint32 aLineNumber)
     240                 : {
     241                 :   // XXX we should really somehow stop the parse and drop the binding
     242                 :   // instead of just letting the XML sink build the content model like
     243                 :   // we do...
     244               0 :   mState = eXBL_Error;
     245               0 :   nsAutoString elementName;
     246               0 :   aElementName->ToString(elementName);
     247                 : 
     248               0 :   const PRUnichar* params[] = { elementName.get() };
     249                 : 
     250                 :   return nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
     251                 :                                          "XBL Content Sink",
     252                 :                                          mDocument,
     253                 :                                          nsContentUtils::eXBL_PROPERTIES,
     254                 :                                          "UnexpectedElement",
     255                 :                                          params, ArrayLength(params),
     256                 :                                          nsnull,
     257               0 :                                          EmptyString() /* source line */,
     258               0 :                                          aLineNumber);
     259                 : }
     260                 : 
     261                 : void
     262               0 : nsXBLContentSink::AddMember(nsXBLProtoImplMember* aMember)
     263                 : {
     264                 :   // Add this member to our chain.
     265               0 :   if (mImplMember)
     266               0 :     mImplMember->SetNext(aMember); // Already have a chain. Just append to the end.
     267                 :   else
     268               0 :     mImplementation->SetMemberList(aMember); // We're the first member in the chain.
     269                 : 
     270               0 :   mImplMember = aMember; // Adjust our pointer to point to the new last member in the chain.
     271               0 : }
     272                 : 
     273                 : void
     274               0 : nsXBLContentSink::AddField(nsXBLProtoImplField* aField)
     275                 : {
     276                 :   // Add this field to our chain.
     277               0 :   if (mImplField)
     278               0 :     mImplField->SetNext(aField); // Already have a chain. Just append to the end.
     279                 :   else
     280               0 :     mImplementation->SetFieldList(aField); // We're the first member in the chain.
     281                 : 
     282               0 :   mImplField = aField; // Adjust our pointer to point to the new last field in the chain.
     283               0 : }
     284                 : 
     285                 : NS_IMETHODIMP 
     286               0 : nsXBLContentSink::HandleStartElement(const PRUnichar *aName, 
     287                 :                                      const PRUnichar **aAtts, 
     288                 :                                      PRUint32 aAttsCount, 
     289                 :                                      PRInt32 aIndex, 
     290                 :                                      PRUint32 aLineNumber)
     291                 : {
     292               0 :   nsresult rv = nsXMLContentSink::HandleStartElement(aName,aAtts,aAttsCount,aIndex,aLineNumber);
     293               0 :   if (NS_FAILED(rv))
     294               0 :     return rv;
     295                 : 
     296               0 :   if (mState == eXBL_InBinding && !mBinding) {
     297               0 :     rv = ConstructBinding(aLineNumber);
     298               0 :     if (NS_FAILED(rv))
     299               0 :       return rv;
     300                 :     
     301                 :     // mBinding may still be null, if the binding had no id.  If so,
     302                 :     // we'll deal with that later in the sink.
     303                 :   }
     304                 : 
     305               0 :   return rv;
     306                 : }
     307                 : 
     308                 : NS_IMETHODIMP 
     309               0 : nsXBLContentSink::HandleEndElement(const PRUnichar *aName)
     310                 : {
     311               0 :   FlushText();
     312                 : 
     313               0 :   if (mState != eXBL_InDocument) {
     314                 :     PRInt32 nameSpaceID;
     315               0 :     nsCOMPtr<nsIAtom> prefix, localName;
     316               0 :     nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
     317               0 :                                    getter_AddRefs(localName), &nameSpaceID);
     318                 : 
     319               0 :     if (nameSpaceID == kNameSpaceID_XBL) {
     320               0 :       if (mState == eXBL_Error) {
     321                 :         // Check whether we've opened this tag before; we may not have if
     322                 :         // it was a real XBL tag before the error occurred.
     323               0 :         if (!GetCurrentContent()->NodeInfo()->Equals(localName,
     324               0 :                                                      nameSpaceID)) {
     325                 :           // OK, this tag was never opened as far as the XML sink is
     326                 :           // concerned.  Just drop the HandleEndElement
     327               0 :           return NS_OK;
     328                 :         }
     329                 :       }
     330               0 :       else if (mState == eXBL_InHandlers) {
     331               0 :         if (localName == nsGkAtoms::handlers) {
     332               0 :           mState = eXBL_InBinding;
     333               0 :           mHandler = nsnull;
     334                 :         }
     335               0 :         else if (localName == nsGkAtoms::handler)
     336               0 :           mSecondaryState = eXBL_None;
     337               0 :         return NS_OK;
     338                 :       }
     339               0 :       else if (mState == eXBL_InResources) {
     340               0 :         if (localName == nsGkAtoms::resources)
     341               0 :           mState = eXBL_InBinding;
     342               0 :         return NS_OK;
     343                 :       }
     344               0 :       else if (mState == eXBL_InImplementation) {
     345               0 :         if (localName == nsGkAtoms::implementation)
     346               0 :           mState = eXBL_InBinding;
     347               0 :         else if (localName == nsGkAtoms::property) {
     348               0 :           mSecondaryState = eXBL_None;
     349               0 :           mProperty = nsnull;
     350                 :         }
     351               0 :         else if (localName == nsGkAtoms::method) {
     352               0 :           mSecondaryState = eXBL_None;
     353               0 :           mMethod = nsnull;
     354                 :         }
     355               0 :         else if (localName == nsGkAtoms::field) {
     356               0 :           mSecondaryState = eXBL_None;
     357               0 :           mField = nsnull;
     358                 :         }
     359               0 :         else if (localName == nsGkAtoms::constructor ||
     360               0 :                  localName == nsGkAtoms::destructor)
     361               0 :           mSecondaryState = eXBL_None;
     362               0 :         else if (localName == nsGkAtoms::getter ||
     363               0 :                  localName == nsGkAtoms::setter)
     364               0 :           mSecondaryState = eXBL_InProperty;
     365               0 :         else if (localName == nsGkAtoms::parameter ||
     366               0 :                  localName == nsGkAtoms::body)
     367               0 :           mSecondaryState = eXBL_InMethod;
     368               0 :         return NS_OK;
     369                 :       }
     370               0 :       else if (mState == eXBL_InBindings &&
     371               0 :                localName == nsGkAtoms::bindings) {
     372               0 :         mState = eXBL_InDocument;
     373                 :       }
     374                 :       
     375               0 :       nsresult rv = nsXMLContentSink::HandleEndElement(aName);
     376               0 :       if (NS_FAILED(rv))
     377               0 :         return rv;
     378                 : 
     379               0 :       if (mState == eXBL_InBinding && localName == nsGkAtoms::binding) {
     380               0 :         mState = eXBL_InBindings;
     381               0 :         if (mBinding) {  // See comment in HandleStartElement()
     382               0 :           mBinding->Initialize();
     383               0 :           mBinding = nsnull; // Clear our current binding ref.
     384                 :         }
     385                 :       }
     386                 : 
     387               0 :       return NS_OK;
     388                 :     }
     389                 :   }
     390                 : 
     391               0 :   return nsXMLContentSink::HandleEndElement(aName);
     392                 : }
     393                 : 
     394                 : NS_IMETHODIMP 
     395               0 : nsXBLContentSink::HandleCDataSection(const PRUnichar *aData, 
     396                 :                                      PRUint32 aLength)
     397                 : {
     398               0 :   if (mState == eXBL_InHandlers || mState == eXBL_InImplementation)
     399               0 :     return AddText(aData, aLength);
     400               0 :   return nsXMLContentSink::HandleCDataSection(aData, aLength);
     401                 : }
     402                 : 
     403                 : #define ENSURE_XBL_STATE(_cond)                                                       \
     404                 :   PR_BEGIN_MACRO                                                                      \
     405                 :     if (!(_cond)) { ReportUnexpectedElement(aTagName, aLineNumber); return true; } \
     406                 :   PR_END_MACRO
     407                 : 
     408                 : bool 
     409               0 : nsXBLContentSink::OnOpenContainer(const PRUnichar **aAtts, 
     410                 :                                   PRUint32 aAttsCount, 
     411                 :                                   PRInt32 aNameSpaceID, 
     412                 :                                   nsIAtom* aTagName,
     413                 :                                   PRUint32 aLineNumber)
     414                 : {
     415               0 :   if (mState == eXBL_Error) {
     416               0 :     return true;
     417                 :   }
     418                 :   
     419               0 :   if (aNameSpaceID != kNameSpaceID_XBL) {
     420                 :     // Construct non-XBL nodes
     421               0 :     return true;
     422                 :   }
     423                 : 
     424               0 :   bool ret = true;
     425               0 :   if (aTagName == nsGkAtoms::bindings) {
     426               0 :     ENSURE_XBL_STATE(mState == eXBL_InDocument);
     427                 :       
     428               0 :     mDocInfo = NS_NewXBLDocumentInfo(mDocument);
     429               0 :     if (!mDocInfo) {
     430               0 :       mState = eXBL_Error;
     431               0 :       return true;
     432                 :     }
     433                 : 
     434               0 :     mDocument->BindingManager()->PutXBLDocumentInfo(mDocInfo);
     435                 : 
     436               0 :     nsIURI *uri = mDocument->GetDocumentURI();
     437                 :       
     438               0 :     bool isChrome = false;
     439               0 :     bool isRes = false;
     440                 : 
     441               0 :     uri->SchemeIs("chrome", &isChrome);
     442               0 :     uri->SchemeIs("resource", &isRes);
     443               0 :     mIsChromeOrResource = isChrome || isRes;
     444                 :       
     445               0 :     nsXBLDocumentInfo* info = mDocInfo;
     446               0 :     NS_RELEASE(info); // We keep a weak ref. We've created a cycle between doc/binding manager/doc info.
     447               0 :     mState = eXBL_InBindings;
     448                 :   }
     449               0 :   else if (aTagName == nsGkAtoms::binding) {
     450               0 :     ENSURE_XBL_STATE(mState == eXBL_InBindings);
     451               0 :     mState = eXBL_InBinding;
     452                 :   }
     453               0 :   else if (aTagName == nsGkAtoms::handlers) {
     454               0 :     ENSURE_XBL_STATE(mState == eXBL_InBinding && mBinding);
     455               0 :     mState = eXBL_InHandlers;
     456               0 :     ret = false;
     457                 :   }
     458               0 :   else if (aTagName == nsGkAtoms::handler) {
     459               0 :     ENSURE_XBL_STATE(mState == eXBL_InHandlers);
     460               0 :     mSecondaryState = eXBL_InHandler;
     461               0 :     ConstructHandler(aAtts, aLineNumber);
     462               0 :     ret = false;
     463                 :   }
     464               0 :   else if (aTagName == nsGkAtoms::resources) {
     465               0 :     ENSURE_XBL_STATE(mState == eXBL_InBinding && mBinding);
     466               0 :     mState = eXBL_InResources;
     467                 :     // Note that this mState will cause us to return false, so no need
     468                 :     // to set ret to false.
     469                 :   }
     470               0 :   else if (aTagName == nsGkAtoms::stylesheet || aTagName == nsGkAtoms::image) {
     471               0 :     ENSURE_XBL_STATE(mState == eXBL_InResources);
     472               0 :     NS_ASSERTION(mBinding, "Must have binding here");
     473               0 :     ConstructResource(aAtts, aTagName);
     474                 :   }
     475               0 :   else if (aTagName == nsGkAtoms::implementation) {
     476               0 :     ENSURE_XBL_STATE(mState == eXBL_InBinding && mBinding);
     477               0 :     mState = eXBL_InImplementation;
     478               0 :     ConstructImplementation(aAtts);
     479                 :     // Note that this mState will cause us to return false, so no need
     480                 :     // to set ret to false.
     481                 :   }
     482               0 :   else if (aTagName == nsGkAtoms::constructor) {
     483               0 :     ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
     484                 :                      mSecondaryState == eXBL_None);
     485               0 :     NS_ASSERTION(mBinding, "Must have binding here");
     486                 :       
     487               0 :     mSecondaryState = eXBL_InConstructor;
     488                 :     nsXBLProtoImplAnonymousMethod* newMethod =
     489               0 :       new nsXBLProtoImplAnonymousMethod();
     490               0 :     if (newMethod) {
     491               0 :       newMethod->SetLineNumber(aLineNumber);
     492               0 :       mBinding->SetConstructor(newMethod);
     493               0 :       AddMember(newMethod);
     494                 :     }
     495                 :   }
     496               0 :   else if (aTagName == nsGkAtoms::destructor) {
     497               0 :     ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
     498                 :                      mSecondaryState == eXBL_None);
     499               0 :     NS_ASSERTION(mBinding, "Must have binding here");
     500               0 :     mSecondaryState = eXBL_InDestructor;
     501                 :     nsXBLProtoImplAnonymousMethod* newMethod =
     502               0 :       new nsXBLProtoImplAnonymousMethod();
     503               0 :     if (newMethod) {
     504               0 :       newMethod->SetLineNumber(aLineNumber);
     505               0 :       mBinding->SetDestructor(newMethod);
     506               0 :       AddMember(newMethod);
     507                 :     }
     508                 :   }
     509               0 :   else if (aTagName == nsGkAtoms::field) {
     510               0 :     ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
     511                 :                      mSecondaryState == eXBL_None);
     512               0 :     NS_ASSERTION(mBinding, "Must have binding here");
     513               0 :     mSecondaryState = eXBL_InField;
     514               0 :     ConstructField(aAtts, aLineNumber);
     515                 :   }
     516               0 :   else if (aTagName == nsGkAtoms::property) {
     517               0 :     ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
     518                 :                      mSecondaryState == eXBL_None);
     519               0 :     NS_ASSERTION(mBinding, "Must have binding here");
     520               0 :     mSecondaryState = eXBL_InProperty;
     521               0 :     ConstructProperty(aAtts);
     522                 :   }
     523               0 :   else if (aTagName == nsGkAtoms::getter) {
     524               0 :     ENSURE_XBL_STATE(mSecondaryState == eXBL_InProperty && mProperty);
     525               0 :     NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
     526               0 :     mProperty->SetGetterLineNumber(aLineNumber);
     527               0 :     mSecondaryState = eXBL_InGetter;
     528                 :   }
     529               0 :   else if (aTagName == nsGkAtoms::setter) {
     530               0 :     ENSURE_XBL_STATE(mSecondaryState == eXBL_InProperty && mProperty);
     531               0 :     NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
     532               0 :     mProperty->SetSetterLineNumber(aLineNumber);
     533               0 :     mSecondaryState = eXBL_InSetter;
     534                 :   }
     535               0 :   else if (aTagName == nsGkAtoms::method) {
     536               0 :     ENSURE_XBL_STATE(mState == eXBL_InImplementation &&
     537                 :                      mSecondaryState == eXBL_None);
     538               0 :     NS_ASSERTION(mBinding, "Must have binding here");
     539               0 :     mSecondaryState = eXBL_InMethod;
     540               0 :     ConstructMethod(aAtts);
     541                 :   }
     542               0 :   else if (aTagName == nsGkAtoms::parameter) {
     543               0 :     ENSURE_XBL_STATE(mSecondaryState == eXBL_InMethod && mMethod);
     544               0 :     NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
     545               0 :     ConstructParameter(aAtts);
     546                 :   }
     547               0 :   else if (aTagName == nsGkAtoms::body) {
     548               0 :     ENSURE_XBL_STATE(mSecondaryState == eXBL_InMethod && mMethod);
     549               0 :     NS_ASSERTION(mState == eXBL_InImplementation, "Unexpected state");
     550                 :     // stash away the line number
     551               0 :     mMethod->SetLineNumber(aLineNumber);
     552               0 :     mSecondaryState = eXBL_InBody;
     553                 :   }
     554                 : 
     555               0 :   return ret && mState != eXBL_InResources && mState != eXBL_InImplementation;
     556                 : }
     557                 : 
     558                 : #undef ENSURE_XBL_STATE
     559                 : 
     560                 : nsresult
     561               0 : nsXBLContentSink::ConstructBinding(PRUint32 aLineNumber)
     562                 : {
     563               0 :   nsCOMPtr<nsIContent> binding = GetCurrentContent();
     564               0 :   nsAutoString id;
     565               0 :   binding->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
     566               0 :   NS_ConvertUTF16toUTF8 cid(id);
     567                 : 
     568               0 :   nsresult rv = NS_OK;
     569                 : 
     570                 :   // Don't create a binding with no id. nsXBLPrototypeBinding::Read also
     571                 :   // performs this check.
     572               0 :   if (!cid.IsEmpty()) {
     573               0 :     mBinding = new nsXBLPrototypeBinding();
     574               0 :     if (!mBinding)
     575               0 :       return NS_ERROR_OUT_OF_MEMORY;
     576                 :       
     577               0 :     rv = mBinding->Init(cid, mDocInfo, binding, !mFoundFirstBinding);
     578               0 :     if (NS_SUCCEEDED(rv) &&
     579               0 :         NS_SUCCEEDED(mDocInfo->SetPrototypeBinding(cid, mBinding))) {
     580               0 :       if (!mFoundFirstBinding) {
     581               0 :         mFoundFirstBinding = true;
     582               0 :         mDocInfo->SetFirstPrototypeBinding(mBinding);
     583                 :       }
     584               0 :       binding->UnsetAttr(kNameSpaceID_None, nsGkAtoms::id, false);
     585                 :     } else {
     586               0 :       delete mBinding;
     587               0 :       mBinding = nsnull;
     588                 :     }
     589                 :   } else {
     590                 :     nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
     591                 :                                     "XBL Content Sink", nsnull,
     592                 :                                     nsContentUtils::eXBL_PROPERTIES,
     593                 :                                     "MissingIdAttr", nsnull, 0,
     594                 :                                     mDocumentURI,
     595               0 :                                     EmptyString(),
     596               0 :                                     aLineNumber);
     597                 :   }
     598                 : 
     599               0 :   return rv;
     600                 : }
     601                 : 
     602                 : static bool
     603               0 : FindValue(const PRUnichar **aAtts, nsIAtom *aAtom, const PRUnichar **aResult)
     604                 : {
     605               0 :   nsCOMPtr<nsIAtom> prefix, localName;
     606               0 :   for (; *aAtts; aAtts += 2) {
     607                 :     PRInt32 nameSpaceID;
     608               0 :     nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
     609               0 :                                    getter_AddRefs(localName), &nameSpaceID);
     610                 : 
     611                 :     // Is this attribute one of the ones we care about?
     612               0 :     if (nameSpaceID == kNameSpaceID_None && localName == aAtom) {
     613               0 :       *aResult = aAtts[1];
     614                 : 
     615               0 :       return true;
     616                 :     }
     617                 :   }
     618                 : 
     619               0 :   return false;
     620                 : }
     621                 : 
     622                 : void
     623               0 : nsXBLContentSink::ConstructHandler(const PRUnichar **aAtts, PRUint32 aLineNumber)
     624                 : {
     625               0 :   const PRUnichar* event          = nsnull;
     626               0 :   const PRUnichar* modifiers      = nsnull;
     627               0 :   const PRUnichar* button         = nsnull;
     628               0 :   const PRUnichar* clickcount     = nsnull;
     629               0 :   const PRUnichar* keycode        = nsnull;
     630               0 :   const PRUnichar* charcode       = nsnull;
     631               0 :   const PRUnichar* phase          = nsnull;
     632               0 :   const PRUnichar* command        = nsnull;
     633               0 :   const PRUnichar* action         = nsnull;
     634               0 :   const PRUnichar* group          = nsnull;
     635               0 :   const PRUnichar* preventdefault = nsnull;
     636               0 :   const PRUnichar* allowuntrusted = nsnull;
     637                 : 
     638               0 :   nsCOMPtr<nsIAtom> prefix, localName;
     639               0 :   for (; *aAtts; aAtts += 2) {
     640                 :     PRInt32 nameSpaceID;
     641               0 :     nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
     642               0 :                                    getter_AddRefs(localName), &nameSpaceID);
     643                 : 
     644               0 :     if (nameSpaceID != kNameSpaceID_None) {
     645               0 :       continue;
     646                 :     }
     647                 : 
     648                 :     // Is this attribute one of the ones we care about?
     649               0 :     if (localName == nsGkAtoms::event)
     650               0 :       event = aAtts[1];
     651               0 :     else if (localName == nsGkAtoms::modifiers)
     652               0 :       modifiers = aAtts[1];
     653               0 :     else if (localName == nsGkAtoms::button)
     654               0 :       button = aAtts[1];
     655               0 :     else if (localName == nsGkAtoms::clickcount)
     656               0 :       clickcount = aAtts[1];
     657               0 :     else if (localName == nsGkAtoms::keycode)
     658               0 :       keycode = aAtts[1];
     659               0 :     else if (localName == nsGkAtoms::key || localName == nsGkAtoms::charcode)
     660               0 :       charcode = aAtts[1];
     661               0 :     else if (localName == nsGkAtoms::phase)
     662               0 :       phase = aAtts[1];
     663               0 :     else if (localName == nsGkAtoms::command)
     664               0 :       command = aAtts[1];
     665               0 :     else if (localName == nsGkAtoms::action)
     666               0 :       action = aAtts[1];
     667               0 :     else if (localName == nsGkAtoms::group)
     668               0 :       group = aAtts[1];
     669               0 :     else if (localName == nsGkAtoms::preventdefault)
     670               0 :       preventdefault = aAtts[1];
     671               0 :     else if (localName == nsGkAtoms::allowuntrusted)
     672               0 :       allowuntrusted = aAtts[1];
     673                 :   }
     674                 : 
     675               0 :   if (command && !mIsChromeOrResource) {
     676                 :     // Make sure the XBL doc is chrome or resource if we have a command
     677                 :     // shorthand syntax.
     678               0 :     mState = eXBL_Error;
     679                 :     nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
     680                 :                                     "XBL Content Sink",
     681                 :                                     mDocument,
     682                 :                                     nsContentUtils::eXBL_PROPERTIES,
     683                 :                                     "CommandNotInChrome", nsnull, 0,
     684                 :                                     nsnull,
     685               0 :                                     EmptyString() /* source line */,
     686               0 :                                     aLineNumber);
     687                 :     return; // Don't even make this handler.
     688                 :   }
     689                 : 
     690                 :   // All of our pointers are now filled in. Construct our handler with all of
     691                 :   // these parameters.
     692                 :   nsXBLPrototypeHandler* newHandler;
     693                 :   newHandler = new nsXBLPrototypeHandler(event, phase, action, command,
     694                 :                                          keycode, charcode, modifiers, button,
     695                 :                                          clickcount, group, preventdefault,
     696               0 :                                          allowuntrusted, mBinding, aLineNumber);
     697                 : 
     698               0 :   if (newHandler) {
     699                 :     // Add this handler to our chain of handlers.
     700               0 :     if (mHandler) {
     701                 :       // Already have a chain. Just append to the end.
     702               0 :       mHandler->SetNextHandler(newHandler);
     703                 :     }
     704                 :     else {
     705                 :       // We're the first handler in the chain.
     706               0 :       mBinding->SetPrototypeHandlers(newHandler);
     707                 :     }
     708                 :     // Adjust our mHandler pointer to point to the new last handler in the
     709                 :     // chain.
     710               0 :     mHandler = newHandler;
     711                 :   } else {
     712               0 :     mState = eXBL_Error;
     713                 :   }
     714                 : }
     715                 : 
     716                 : void
     717               0 : nsXBLContentSink::ConstructResource(const PRUnichar **aAtts,
     718                 :                                     nsIAtom* aResourceType)
     719                 : {
     720               0 :   if (!mBinding)
     721               0 :     return;
     722                 : 
     723               0 :   const PRUnichar* src = nsnull;
     724               0 :   if (FindValue(aAtts, nsGkAtoms::src, &src)) {
     725               0 :     mBinding->AddResource(aResourceType, nsDependentString(src));
     726                 :   }
     727                 : }
     728                 : 
     729                 : void
     730               0 : nsXBLContentSink::ConstructImplementation(const PRUnichar **aAtts)
     731                 : {
     732               0 :   mImplementation = nsnull;
     733               0 :   mImplMember = nsnull;
     734               0 :   mImplField = nsnull;
     735                 :   
     736               0 :   if (!mBinding)
     737               0 :     return;
     738                 : 
     739               0 :   const PRUnichar* name = nsnull;
     740                 : 
     741               0 :   nsCOMPtr<nsIAtom> prefix, localName;
     742               0 :   for (; *aAtts; aAtts += 2) {
     743                 :     PRInt32 nameSpaceID;
     744               0 :     nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
     745               0 :                                    getter_AddRefs(localName), &nameSpaceID);
     746                 : 
     747               0 :     if (nameSpaceID != kNameSpaceID_None) {
     748               0 :       continue;
     749                 :     }
     750                 : 
     751                 :     // Is this attribute one of the ones we care about?
     752               0 :     if (localName == nsGkAtoms::name) {
     753               0 :       name = aAtts[1];
     754                 :     }
     755               0 :     else if (localName == nsGkAtoms::implements) {
     756                 :       // Only allow implementation of interfaces via XBL if the principal of
     757                 :       // our XBL document has UniversalXPConnect privileges.  No principal
     758                 :       // means no privs!
     759                 :       
     760                 :       // XXX this api is so badly tied to JS it's not even funny.  We don't
     761                 :       // have a concept of enabling capabilities on a per-principal basis,
     762                 :       // but only on a per-principal-and-JS-stackframe basis!  So for now
     763                 :       // this is basically equivalent to testing that we have the system
     764                 :       // principal, since there is no JS stackframe in sight here...
     765                 :       bool hasUniversalXPConnect;
     766               0 :       nsresult rv = mDocument->NodePrincipal()->
     767                 :         IsCapabilityEnabled("UniversalXPConnect", nsnull,
     768               0 :                             &hasUniversalXPConnect);
     769               0 :       if (NS_SUCCEEDED(rv) && hasUniversalXPConnect) {
     770               0 :         mBinding->ConstructInterfaceTable(nsDependentString(aAtts[1]));
     771                 :       }
     772                 :     }
     773                 :   }
     774                 : 
     775               0 :   NS_NewXBLProtoImpl(mBinding, name, &mImplementation);
     776                 : }
     777                 : 
     778                 : void
     779               0 : nsXBLContentSink::ConstructField(const PRUnichar **aAtts, PRUint32 aLineNumber)
     780                 : {
     781               0 :   const PRUnichar* name     = nsnull;
     782               0 :   const PRUnichar* readonly = nsnull;
     783                 : 
     784               0 :   nsCOMPtr<nsIAtom> prefix, localName;
     785               0 :   for (; *aAtts; aAtts += 2) {
     786                 :     PRInt32 nameSpaceID;
     787               0 :     nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
     788               0 :                                    getter_AddRefs(localName), &nameSpaceID);
     789                 : 
     790               0 :     if (nameSpaceID != kNameSpaceID_None) {
     791               0 :       continue;
     792                 :     }
     793                 : 
     794                 :     // Is this attribute one of the ones we care about?
     795               0 :     if (localName == nsGkAtoms::name) {
     796               0 :       name = aAtts[1];
     797                 :     }
     798               0 :     else if (localName == nsGkAtoms::readonly) {
     799               0 :       readonly = aAtts[1];
     800                 :     }
     801                 :   }
     802                 : 
     803               0 :   if (name) {
     804                 :     // All of our pointers are now filled in. Construct our field with all of
     805                 :     // these parameters.
     806               0 :     mField = new nsXBLProtoImplField(name, readonly);
     807               0 :     if (mField) {
     808               0 :       mField->SetLineNumber(aLineNumber);
     809               0 :       AddField(mField);
     810                 :     }
     811                 :   }
     812               0 : }
     813                 : 
     814                 : void
     815               0 : nsXBLContentSink::ConstructProperty(const PRUnichar **aAtts)
     816                 : {
     817               0 :   const PRUnichar* name     = nsnull;
     818               0 :   const PRUnichar* readonly = nsnull;
     819               0 :   const PRUnichar* onget    = nsnull;
     820               0 :   const PRUnichar* onset    = nsnull;
     821                 : 
     822               0 :   nsCOMPtr<nsIAtom> prefix, localName;
     823               0 :   for (; *aAtts; aAtts += 2) {
     824                 :     PRInt32 nameSpaceID;
     825               0 :     nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
     826               0 :                                    getter_AddRefs(localName), &nameSpaceID);
     827                 : 
     828               0 :     if (nameSpaceID != kNameSpaceID_None) {
     829               0 :       continue;
     830                 :     }
     831                 : 
     832                 :     // Is this attribute one of the ones we care about?
     833               0 :     if (localName == nsGkAtoms::name) {
     834               0 :       name = aAtts[1];
     835                 :     }
     836               0 :     else if (localName == nsGkAtoms::readonly) {
     837               0 :       readonly = aAtts[1];
     838                 :     }
     839               0 :     else if (localName == nsGkAtoms::onget) {
     840               0 :       onget = aAtts[1];
     841                 :     }
     842               0 :     else if (localName == nsGkAtoms::onset) {
     843               0 :       onset = aAtts[1];
     844                 :     }
     845                 :   }
     846                 : 
     847               0 :   if (name) {
     848                 :     // All of our pointers are now filled in. Construct our property with all of
     849                 :     // these parameters.
     850               0 :     mProperty = new nsXBLProtoImplProperty(name, onget, onset, readonly);
     851               0 :     if (mProperty) {
     852               0 :       AddMember(mProperty);
     853                 :     }
     854                 :   }
     855               0 : }
     856                 : 
     857                 : void
     858               0 : nsXBLContentSink::ConstructMethod(const PRUnichar **aAtts)
     859                 : {
     860               0 :   mMethod = nsnull;
     861                 : 
     862               0 :   const PRUnichar* name = nsnull;
     863               0 :   if (FindValue(aAtts, nsGkAtoms::name, &name)) {
     864               0 :     mMethod = new nsXBLProtoImplMethod(name);
     865                 :   }
     866                 : 
     867               0 :   if (mMethod) {
     868               0 :     AddMember(mMethod);
     869                 :   }
     870               0 : }
     871                 : 
     872                 : void
     873               0 : nsXBLContentSink::ConstructParameter(const PRUnichar **aAtts)
     874                 : {
     875               0 :   if (!mMethod)
     876               0 :     return;
     877                 : 
     878               0 :   const PRUnichar* name = nsnull;
     879               0 :   if (FindValue(aAtts, nsGkAtoms::name, &name)) {
     880               0 :     mMethod->AddParameter(nsDependentString(name));
     881                 :   }
     882                 : }
     883                 : 
     884                 : nsresult
     885               0 : nsXBLContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
     886                 :                                 nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
     887                 :                                 nsIContent** aResult, bool* aAppendContent,
     888                 :                                 FromParser aFromParser)
     889                 : {
     890                 : #ifdef MOZ_XUL
     891               0 :   if (!aNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
     892                 : #endif
     893                 :     return nsXMLContentSink::CreateElement(aAtts, aAttsCount, aNodeInfo,
     894                 :                                            aLineNumber, aResult,
     895               0 :                                            aAppendContent, aFromParser);
     896                 : #ifdef MOZ_XUL
     897                 :   }
     898                 : 
     899                 :   // Note that this needs to match the code in nsXBLPrototypeBinding::ReadContentNode.
     900                 : 
     901               0 :   *aAppendContent = true;
     902               0 :   nsRefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement();
     903               0 :   if (!prototype)
     904               0 :     return NS_ERROR_OUT_OF_MEMORY;
     905                 : 
     906               0 :   prototype->mNodeInfo = aNodeInfo;
     907                 :   // XXX - we need to do exactly what the XUL content-sink does (eg,
     908                 :   // look for 'type', 'version' etc attributes)
     909               0 :   prototype->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
     910                 : 
     911               0 :   AddAttributesToXULPrototype(aAtts, aAttsCount, prototype);
     912                 : 
     913                 :   Element* result;
     914               0 :   nsresult rv = nsXULElement::Create(prototype, mDocument, false, &result);
     915               0 :   *aResult = result;
     916               0 :   return rv;
     917                 : #endif
     918                 : }
     919                 : 
     920                 : nsresult 
     921               0 : nsXBLContentSink::AddAttributes(const PRUnichar** aAtts,
     922                 :                                 nsIContent* aContent)
     923                 : {
     924               0 :   if (aContent->IsXUL())
     925               0 :     return NS_OK; // Nothing to do, since the proto already has the attrs.
     926                 : 
     927               0 :   return nsXMLContentSink::AddAttributes(aAtts, aContent);
     928                 : }
     929                 : 
     930                 : #ifdef MOZ_XUL
     931                 : nsresult
     932               0 : nsXBLContentSink::AddAttributesToXULPrototype(const PRUnichar **aAtts, 
     933                 :                                               PRUint32 aAttsCount, 
     934                 :                                               nsXULPrototypeElement* aElement)
     935                 : {
     936                 :   // Add tag attributes to the element
     937                 :   nsresult rv;
     938                 : 
     939                 :   // Create storage for the attributes
     940               0 :   nsXULPrototypeAttribute* attrs = nsnull;
     941               0 :   if (aAttsCount > 0) {
     942               0 :     attrs = new nsXULPrototypeAttribute[aAttsCount];
     943               0 :     if (!attrs)
     944               0 :       return NS_ERROR_OUT_OF_MEMORY;
     945                 :   }
     946                 : 
     947               0 :   aElement->mAttributes    = attrs;
     948               0 :   aElement->mNumAttributes = aAttsCount;
     949                 : 
     950                 :   // Copy the attributes into the prototype
     951               0 :   nsCOMPtr<nsIAtom> prefix, localName;
     952                 : 
     953                 :   PRUint32 i;  
     954               0 :   for (i = 0; i < aAttsCount; ++i) {
     955                 :     PRInt32 nameSpaceID;
     956               0 :     nsContentUtils::SplitExpatName(aAtts[i * 2], getter_AddRefs(prefix),
     957               0 :                                    getter_AddRefs(localName), &nameSpaceID);
     958                 : 
     959               0 :     if (nameSpaceID == kNameSpaceID_None) {
     960               0 :       attrs[i].mName.SetTo(localName);
     961                 :     }
     962                 :     else {
     963               0 :       nsCOMPtr<nsINodeInfo> ni;
     964                 :       ni = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
     965               0 :                                          nsIDOMNode::ATTRIBUTE_NODE);
     966               0 :       attrs[i].mName.SetTo(ni);
     967                 :     }
     968                 :     
     969               0 :     rv = aElement->SetAttrAt(i, nsDependentString(aAtts[i * 2 + 1]),
     970               0 :                              mDocumentURI); 
     971               0 :     NS_ENSURE_SUCCESS(rv, rv);
     972                 :   }
     973                 : 
     974               0 :   return NS_OK;
     975                 : }
     976                 : #endif

Generated by: LCOV version 1.7