LCOV - code coverage report
Current view: top level - dom/xul - nsXULContentSink.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 468 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 43 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set ts=8 sts=4 et sw=4 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*
       8             :  * An implementation for a Gecko-style content sink that knows how
       9             :  * to build a content model (the "prototype" document) from XUL.
      10             :  *
      11             :  * For more information on XUL,
      12             :  * see http://developer.mozilla.org/en/docs/XUL
      13             :  */
      14             : 
      15             : #include "nsXULContentSink.h"
      16             : 
      17             : #include "jsfriendapi.h"
      18             : 
      19             : #include "nsCOMPtr.h"
      20             : #include "nsForwardReference.h"
      21             : #include "nsHTMLStyleSheet.h"
      22             : #include "nsIContentSink.h"
      23             : #include "nsIDocument.h"
      24             : #include "nsIDOMEventListener.h"
      25             : #include "nsIDOMHTMLFormElement.h"
      26             : #include "nsIDOMXULDocument.h"
      27             : #include "nsIFormControl.h"
      28             : #include "mozilla/dom/NodeInfo.h"
      29             : #include "nsIScriptContext.h"
      30             : #include "nsIScriptGlobalObject.h"
      31             : #include "nsIServiceManager.h"
      32             : #include "nsIURL.h"
      33             : #include "nsNameSpaceManager.h"
      34             : #include "nsParserBase.h"
      35             : #include "nsViewManager.h"
      36             : #include "nsIXULDocument.h"
      37             : #include "nsIScriptSecurityManager.h"
      38             : #include "nsLayoutCID.h"
      39             : #include "nsNetUtil.h"
      40             : #include "nsRDFCID.h"
      41             : #include "nsXPIDLString.h"
      42             : #include "nsReadableUtils.h"
      43             : #include "nsXULElement.h"
      44             : #include "mozilla/Logging.h"
      45             : #include "nsCRT.h"
      46             : 
      47             : #include "nsXULPrototypeDocument.h"     // XXXbe temporary
      48             : #include "mozilla/css/Loader.h"
      49             : 
      50             : #include "nsUnicharUtils.h"
      51             : #include "nsGkAtoms.h"
      52             : #include "nsContentUtils.h"
      53             : #include "nsAttrName.h"
      54             : #include "nsXMLContentSink.h"
      55             : #include "nsIConsoleService.h"
      56             : #include "nsIScriptError.h"
      57             : #include "nsContentTypeParser.h"
      58             : 
      59             : static mozilla::LazyLogModule gContentSinkLog("nsXULContentSink");;
      60             : 
      61             : //----------------------------------------------------------------------
      62             : 
      63           0 : XULContentSinkImpl::ContextStack::ContextStack()
      64           0 :     : mTop(nullptr), mDepth(0)
      65             : {
      66           0 : }
      67             : 
      68           0 : XULContentSinkImpl::ContextStack::~ContextStack()
      69             : {
      70           0 :     while (mTop) {
      71           0 :         Entry* doomed = mTop;
      72           0 :         mTop = mTop->mNext;
      73           0 :         delete doomed;
      74             :     }
      75           0 : }
      76             : 
      77             : nsresult
      78           0 : XULContentSinkImpl::ContextStack::Push(nsXULPrototypeNode* aNode, State aState)
      79             : {
      80           0 :     Entry* entry = new Entry;
      81           0 :     entry->mNode  = aNode;
      82           0 :     entry->mState = aState;
      83           0 :     entry->mNext  = mTop;
      84             : 
      85           0 :     mTop = entry;
      86             : 
      87           0 :     ++mDepth;
      88           0 :     return NS_OK;
      89             : }
      90             : 
      91             : nsresult
      92           0 : XULContentSinkImpl::ContextStack::Pop(State* aState)
      93             : {
      94           0 :     if (mDepth == 0)
      95           0 :         return NS_ERROR_UNEXPECTED;
      96             : 
      97           0 :     Entry* entry = mTop;
      98           0 :     mTop = mTop->mNext;
      99           0 :     --mDepth;
     100             : 
     101           0 :     *aState = entry->mState;
     102           0 :     delete entry;
     103             : 
     104           0 :     return NS_OK;
     105             : }
     106             : 
     107             : 
     108             : nsresult
     109           0 : XULContentSinkImpl::ContextStack::GetTopNode(RefPtr<nsXULPrototypeNode>& aNode)
     110             : {
     111           0 :     if (mDepth == 0)
     112           0 :         return NS_ERROR_UNEXPECTED;
     113             : 
     114           0 :     aNode = mTop->mNode;
     115           0 :     return NS_OK;
     116             : }
     117             : 
     118             : 
     119             : nsresult
     120           0 : XULContentSinkImpl::ContextStack::GetTopChildren(nsPrototypeArray** aChildren)
     121             : {
     122           0 :     if (mDepth == 0)
     123           0 :         return NS_ERROR_UNEXPECTED;
     124             : 
     125           0 :     *aChildren = &(mTop->mChildren);
     126           0 :     return NS_OK;
     127             : }
     128             : 
     129             : void
     130           0 : XULContentSinkImpl::ContextStack::Clear()
     131             : {
     132           0 :   Entry *cur = mTop;
     133           0 :   while (cur) {
     134             :     // Release the root element (and its descendants).
     135           0 :     Entry *next = cur->mNext;
     136           0 :     delete cur;
     137           0 :     cur = next;
     138             :   }
     139             : 
     140           0 :   mTop = nullptr;
     141           0 :   mDepth = 0;
     142           0 : }
     143             : 
     144             : void
     145           0 : XULContentSinkImpl::ContextStack::Traverse(nsCycleCollectionTraversalCallback& aCb)
     146             : {
     147           0 :   nsCycleCollectionTraversalCallback& cb = aCb;
     148           0 :   for (ContextStack::Entry* tmp = mTop; tmp; tmp = tmp->mNext) {
     149           0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNode)
     150           0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildren)
     151             :   }
     152           0 : }
     153             : 
     154             : //----------------------------------------------------------------------
     155             : 
     156             : 
     157           0 : XULContentSinkImpl::XULContentSinkImpl()
     158             :     : mText(nullptr),
     159             :       mTextLength(0),
     160             :       mTextSize(0),
     161             :       mConstrainSize(true),
     162           0 :       mState(eInProlog)
     163             : {
     164           0 : }
     165             : 
     166             : 
     167           0 : XULContentSinkImpl::~XULContentSinkImpl()
     168             : {
     169             :     // The context stack _should_ be empty, unless something has gone wrong.
     170           0 :     NS_ASSERTION(mContextStack.Depth() == 0, "Context stack not empty?");
     171           0 :     mContextStack.Clear();
     172             : 
     173           0 :     free(mText);
     174           0 : }
     175             : 
     176             : //----------------------------------------------------------------------
     177             : // nsISupports interface
     178             : 
     179             : NS_IMPL_CYCLE_COLLECTION_CLASS(XULContentSinkImpl)
     180             : 
     181           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XULContentSinkImpl)
     182           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager)
     183           0 :   tmp->mContextStack.Clear();
     184           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrototype)
     185           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser)
     186           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     187             : 
     188           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XULContentSinkImpl)
     189           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager)
     190           0 :   tmp->mContextStack.Traverse(cb);
     191           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrototype)
     192           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParser)
     193           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     194             : 
     195           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XULContentSinkImpl)
     196           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXMLContentSink)
     197           0 :   NS_INTERFACE_MAP_ENTRY(nsIXMLContentSink)
     198           0 :   NS_INTERFACE_MAP_ENTRY(nsIExpatSink)
     199           0 :   NS_INTERFACE_MAP_ENTRY(nsIContentSink)
     200           0 : NS_INTERFACE_MAP_END
     201             : 
     202           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(XULContentSinkImpl)
     203           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(XULContentSinkImpl)
     204             : 
     205             : //----------------------------------------------------------------------
     206             : // nsIContentSink interface
     207             : 
     208             : NS_IMETHODIMP
     209           0 : XULContentSinkImpl::WillBuildModel(nsDTDMode aDTDMode)
     210             : {
     211             : #if FIXME
     212             :     if (! mParentContentSink) {
     213             :         // If we're _not_ an overlay, then notify the document that
     214             :         // the load is beginning.
     215             :         mDocument->BeginLoad();
     216             :     }
     217             : #endif
     218             : 
     219           0 :     return NS_OK;
     220             : }
     221             : 
     222             : NS_IMETHODIMP
     223           0 : XULContentSinkImpl::DidBuildModel(bool aTerminated)
     224             : {
     225           0 :     nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
     226           0 :     if (doc) {
     227           0 :         doc->EndLoad();
     228           0 :         mDocument = nullptr;
     229             :     }
     230             : 
     231             :     // Drop our reference to the parser to get rid of a circular
     232             :     // reference.
     233           0 :     mParser = nullptr;
     234           0 :     return NS_OK;
     235             : }
     236             : 
     237             : NS_IMETHODIMP
     238           0 : XULContentSinkImpl::WillInterrupt(void)
     239             : {
     240             :     // XXX Notify the docshell, if necessary
     241           0 :     return NS_OK;
     242             : }
     243             : 
     244             : NS_IMETHODIMP
     245           0 : XULContentSinkImpl::WillResume(void)
     246             : {
     247             :     // XXX Notify the docshell, if necessary
     248           0 :     return NS_OK;
     249             : }
     250             : 
     251             : NS_IMETHODIMP
     252           0 : XULContentSinkImpl::SetParser(nsParserBase* aParser)
     253             : {
     254           0 :     mParser = aParser;
     255           0 :     return NS_OK;
     256             : }
     257             : 
     258             : void
     259           0 : XULContentSinkImpl::SetDocumentCharset(NotNull<const Encoding*> aEncoding)
     260             : {
     261           0 :     nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
     262           0 :     if (doc) {
     263           0 :         doc->SetDocumentCharacterSet(aEncoding);
     264             :     }
     265           0 : }
     266             : 
     267             : nsISupports *
     268           0 : XULContentSinkImpl::GetTarget()
     269             : {
     270           0 :     nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
     271           0 :     return doc;
     272             : }
     273             : 
     274             : //----------------------------------------------------------------------
     275             : 
     276             : nsresult
     277           0 : XULContentSinkImpl::Init(nsIDocument* aDocument,
     278             :                          nsXULPrototypeDocument* aPrototype)
     279             : {
     280           0 :     NS_PRECONDITION(aDocument != nullptr, "null ptr");
     281           0 :     if (! aDocument)
     282           0 :         return NS_ERROR_NULL_POINTER;
     283             : 
     284             :     nsresult rv;
     285             : 
     286           0 :     mDocument    = do_GetWeakReference(aDocument);
     287           0 :     mPrototype   = aPrototype;
     288             : 
     289           0 :     mDocumentURL = mPrototype->GetURI();
     290             : 
     291             :     // XXX this presumes HTTP header info is already set in document
     292             :     // XXX if it isn't we need to set it here...
     293             :     // XXXbz not like GetHeaderData on the proto doc _does_ anything....
     294           0 :     nsAutoString preferredStyle;
     295           0 :     rv = mPrototype->GetHeaderData(nsGkAtoms::headerDefaultStyle,
     296           0 :                                    preferredStyle);
     297           0 :     if (NS_FAILED(rv)) return rv;
     298             : 
     299           0 :     if (!preferredStyle.IsEmpty()) {
     300             :         aDocument->SetHeaderData(nsGkAtoms::headerDefaultStyle,
     301           0 :                                  preferredStyle);
     302             :     }
     303             : 
     304             :     // Set the right preferred style on the document's CSSLoader.
     305           0 :     aDocument->CSSLoader()->SetPreferredSheet(preferredStyle);
     306             : 
     307           0 :     mNodeInfoManager = aPrototype->GetNodeInfoManager();
     308           0 :     if (! mNodeInfoManager)
     309           0 :         return NS_ERROR_UNEXPECTED;
     310             : 
     311           0 :     mState = eInProlog;
     312           0 :     return NS_OK;
     313             : }
     314             : 
     315             : 
     316             : //----------------------------------------------------------------------
     317             : //
     318             : // Text buffering
     319             : //
     320             : 
     321             : bool
     322           0 : XULContentSinkImpl::IsDataInBuffer(char16_t* buffer, int32_t length)
     323             : {
     324           0 :     for (int32_t i = 0; i < length; ++i) {
     325           0 :         if (buffer[i] == ' ' ||
     326           0 :             buffer[i] == '\t' ||
     327           0 :             buffer[i] == '\n' ||
     328           0 :             buffer[i] == '\r')
     329           0 :             continue;
     330             : 
     331           0 :         return true;
     332             :     }
     333           0 :     return false;
     334             : }
     335             : 
     336             : 
     337             : nsresult
     338           0 : XULContentSinkImpl::FlushText(bool aCreateTextNode)
     339             : {
     340             :     nsresult rv;
     341             : 
     342             :     do {
     343             :         // Don't do anything if there's no text to create a node from, or
     344             :         // if they've told us not to create a text node
     345           0 :         if (! mTextLength)
     346           0 :             break;
     347             : 
     348           0 :         if (! aCreateTextNode)
     349           0 :             break;
     350             : 
     351           0 :         RefPtr<nsXULPrototypeNode> node;
     352           0 :         rv = mContextStack.GetTopNode(node);
     353           0 :         if (NS_FAILED(rv)) return rv;
     354             : 
     355           0 :         bool stripWhitespace = false;
     356           0 :         if (node->mType == nsXULPrototypeNode::eType_Element) {
     357             :             mozilla::dom::NodeInfo *nodeInfo =
     358           0 :                 static_cast<nsXULPrototypeElement*>(node.get())->mNodeInfo;
     359             : 
     360           0 :             if (nodeInfo->NamespaceEquals(kNameSpaceID_XUL))
     361           0 :                 stripWhitespace = !nodeInfo->Equals(nsGkAtoms::label) &&
     362           0 :                                   !nodeInfo->Equals(nsGkAtoms::description);
     363             :         }
     364             : 
     365             :         // Don't bother if there's nothing but whitespace.
     366           0 :         if (stripWhitespace && ! IsDataInBuffer(mText, mTextLength))
     367           0 :             break;
     368             : 
     369             :         // Don't bother if we're not in XUL document body
     370           0 :         if (mState != eInDocumentElement || mContextStack.Depth() == 0)
     371           0 :             break;
     372             : 
     373           0 :         nsXULPrototypeText* text = new nsXULPrototypeText();
     374           0 :         text->mValue.Assign(mText, mTextLength);
     375           0 :         if (stripWhitespace)
     376           0 :             text->mValue.Trim(" \t\n\r");
     377             : 
     378             :         // hook it up
     379           0 :         nsPrototypeArray* children = nullptr;
     380           0 :         rv = mContextStack.GetTopChildren(&children);
     381           0 :         if (NS_FAILED(rv)) return rv;
     382             : 
     383             :         // transfer ownership of 'text' to the children array
     384           0 :         children->AppendElement(text);
     385             :     } while (0);
     386             : 
     387             :     // Reset our text buffer
     388           0 :     mTextLength = 0;
     389           0 :     return NS_OK;
     390             : }
     391             : 
     392             : //----------------------------------------------------------------------
     393             : 
     394             : nsresult
     395           0 : XULContentSinkImpl::NormalizeAttributeString(const char16_t *aExpatName,
     396             :                                              nsAttrName &aName)
     397             : {
     398             :     int32_t nameSpaceID;
     399           0 :     nsCOMPtr<nsIAtom> prefix, localName;
     400           0 :     nsContentUtils::SplitExpatName(aExpatName, getter_AddRefs(prefix),
     401           0 :                                    getter_AddRefs(localName), &nameSpaceID);
     402             : 
     403           0 :     if (nameSpaceID == kNameSpaceID_None) {
     404           0 :         aName.SetTo(localName);
     405             : 
     406           0 :         return NS_OK;
     407             :     }
     408             : 
     409           0 :     RefPtr<mozilla::dom::NodeInfo> ni;
     410           0 :     ni = mNodeInfoManager->GetNodeInfo(localName, prefix,
     411             :                                        nameSpaceID,
     412           0 :                                        nsIDOMNode::ATTRIBUTE_NODE);
     413           0 :     aName.SetTo(ni);
     414             : 
     415           0 :     return NS_OK;
     416             : }
     417             : 
     418             : nsresult
     419           0 : XULContentSinkImpl::CreateElement(mozilla::dom::NodeInfo *aNodeInfo,
     420             :                                   nsXULPrototypeElement** aResult)
     421             : {
     422           0 :     nsXULPrototypeElement* element = new nsXULPrototypeElement();
     423           0 :     element->mNodeInfo    = aNodeInfo;
     424             : 
     425           0 :     *aResult = element;
     426           0 :     return NS_OK;
     427             : }
     428             : 
     429             : /**** BEGIN NEW APIs ****/
     430             : 
     431             : 
     432             : NS_IMETHODIMP
     433           0 : XULContentSinkImpl::HandleStartElement(const char16_t *aName,
     434             :                                        const char16_t **aAtts,
     435             :                                        uint32_t aAttsCount,
     436             :                                        uint32_t aLineNumber)
     437             : {
     438             :   // XXX Hopefully the parser will flag this before we get here. If
     439             :   // we're in the epilog, there should be no new elements
     440           0 :   NS_PRECONDITION(mState != eInEpilog, "tag in XUL doc epilog");
     441           0 :   NS_PRECONDITION(aAttsCount % 2 == 0, "incorrect aAttsCount");
     442             :   // Adjust aAttsCount so it's the actual number of attributes
     443           0 :   aAttsCount /= 2;
     444             : 
     445           0 :   if (mState == eInEpilog)
     446           0 :       return NS_ERROR_UNEXPECTED;
     447             : 
     448           0 :   if (mState != eInScript) {
     449           0 :       FlushText();
     450             :   }
     451             : 
     452             :   int32_t nameSpaceID;
     453           0 :   nsCOMPtr<nsIAtom> prefix, localName;
     454           0 :   nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
     455           0 :                                  getter_AddRefs(localName), &nameSpaceID);
     456             : 
     457           0 :   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
     458           0 :   nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
     459           0 :                                            nsIDOMNode::ELEMENT_NODE);
     460             : 
     461           0 :   nsresult rv = NS_OK;
     462           0 :   switch (mState) {
     463             :   case eInProlog:
     464             :       // We're the root document element
     465           0 :       rv = OpenRoot(aAtts, aAttsCount, nodeInfo);
     466           0 :       break;
     467             : 
     468             :   case eInDocumentElement:
     469           0 :       rv = OpenTag(aAtts, aAttsCount, aLineNumber, nodeInfo);
     470           0 :       break;
     471             : 
     472             :   case eInEpilog:
     473             :   case eInScript:
     474           0 :       MOZ_LOG(gContentSinkLog, LogLevel::Warning,
     475             :              ("xul: warning: unexpected tags in epilog at line %d",
     476             :              aLineNumber));
     477           0 :       rv = NS_ERROR_UNEXPECTED; // XXX
     478           0 :       break;
     479             :   }
     480             : 
     481           0 :   return rv;
     482             : }
     483             : 
     484             : NS_IMETHODIMP
     485           0 : XULContentSinkImpl::HandleEndElement(const char16_t *aName)
     486             : {
     487             :     // Never EVER return anything but NS_OK or
     488             :     // NS_ERROR_HTMLPARSER_BLOCK from this method. Doing so will blow
     489             :     // the parser's little mind all over the planet.
     490             :     nsresult rv;
     491             : 
     492           0 :     RefPtr<nsXULPrototypeNode> node;
     493           0 :     rv = mContextStack.GetTopNode(node);
     494             : 
     495           0 :     if (NS_FAILED(rv)) {
     496           0 :       return NS_OK;
     497             :     }
     498             : 
     499           0 :     switch (node->mType) {
     500             :     case nsXULPrototypeNode::eType_Element: {
     501             :         // Flush any text _now_, so that we'll get text nodes created
     502             :         // before popping the stack.
     503           0 :         FlushText();
     504             : 
     505             :         // Pop the context stack and do prototype hookup.
     506           0 :         nsPrototypeArray* children = nullptr;
     507           0 :         rv = mContextStack.GetTopChildren(&children);
     508           0 :         if (NS_FAILED(rv)) return rv;
     509             : 
     510             :         nsXULPrototypeElement* element =
     511           0 :           static_cast<nsXULPrototypeElement*>(node.get());
     512             : 
     513           0 :         int32_t count = children->Length();
     514           0 :         if (count) {
     515           0 :             element->mChildren.SetCapacity(count);
     516             : 
     517           0 :             for (int32_t i = 0; i < count; ++i)
     518           0 :                 element->mChildren.AppendElement(children->ElementAt(i));
     519             : 
     520             :         }
     521             :     }
     522           0 :     break;
     523             : 
     524             :     case nsXULPrototypeNode::eType_Script: {
     525             :         nsXULPrototypeScript* script =
     526           0 :             static_cast<nsXULPrototypeScript*>(node.get());
     527             : 
     528             :         // If given a src= attribute, we must ignore script tag content.
     529           0 :         if (!script->mSrcURI && !script->HasScriptObject()) {
     530           0 :             nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
     531             : 
     532           0 :             script->mOutOfLine = false;
     533           0 :             if (doc)
     534           0 :                 script->Compile(mText, mTextLength, mDocumentURL,
     535           0 :                                 script->mLineNo, doc);
     536             :         }
     537             : 
     538           0 :         FlushText(false);
     539             :     }
     540           0 :     break;
     541             : 
     542             :     default:
     543           0 :         NS_ERROR("didn't expect that");
     544           0 :         break;
     545             :     }
     546             : 
     547           0 :     rv = mContextStack.Pop(&mState);
     548           0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "context stack corrupted");
     549           0 :     if (NS_FAILED(rv)) return rv;
     550             : 
     551           0 :     if (mContextStack.Depth() == 0) {
     552             :         // The root element should -always- be an element, because
     553             :         // it'll have been created via XULContentSinkImpl::OpenRoot().
     554           0 :         NS_ASSERTION(node->mType == nsXULPrototypeNode::eType_Element, "root is not an element");
     555           0 :         if (node->mType != nsXULPrototypeNode::eType_Element)
     556           0 :             return NS_ERROR_UNEXPECTED;
     557             : 
     558             :         // Now that we're done parsing, set the prototype document's
     559             :         // root element. This transfers ownership of the prototype
     560             :         // element tree to the prototype document.
     561             :         nsXULPrototypeElement* element =
     562           0 :             static_cast<nsXULPrototypeElement*>(node.get());
     563             : 
     564           0 :         mPrototype->SetRootElement(element);
     565           0 :         mState = eInEpilog;
     566             :     }
     567             : 
     568           0 :     return NS_OK;
     569             : }
     570             : 
     571             : NS_IMETHODIMP
     572           0 : XULContentSinkImpl::HandleComment(const char16_t *aName)
     573             : {
     574           0 :    FlushText();
     575           0 :    return NS_OK;
     576             : }
     577             : 
     578             : NS_IMETHODIMP
     579           0 : XULContentSinkImpl::HandleCDataSection(const char16_t *aData, uint32_t aLength)
     580             : {
     581           0 :     FlushText();
     582           0 :     return AddText(aData, aLength);
     583             : }
     584             : 
     585             : NS_IMETHODIMP
     586           0 : XULContentSinkImpl::HandleDoctypeDecl(const nsAString & aSubset,
     587             :                                       const nsAString & aName,
     588             :                                       const nsAString & aSystemId,
     589             :                                       const nsAString & aPublicId,
     590             :                                       nsISupports* aCatalogData)
     591             : {
     592           0 :     return NS_OK;
     593             : }
     594             : 
     595             : NS_IMETHODIMP
     596           0 : XULContentSinkImpl::HandleCharacterData(const char16_t *aData,
     597             :                                         uint32_t aLength)
     598             : {
     599           0 :   if (aData && mState != eInProlog && mState != eInEpilog) {
     600           0 :     return AddText(aData, aLength);
     601             :   }
     602           0 :   return NS_OK;
     603             : }
     604             : 
     605             : NS_IMETHODIMP
     606           0 : XULContentSinkImpl::HandleProcessingInstruction(const char16_t *aTarget,
     607             :                                                 const char16_t *aData)
     608             : {
     609           0 :     FlushText();
     610             : 
     611           0 :     const nsDependentString target(aTarget);
     612           0 :     const nsDependentString data(aData);
     613             : 
     614             :     // Note: the created nsXULPrototypePI has mRefCnt == 1
     615           0 :     RefPtr<nsXULPrototypePI> pi = new nsXULPrototypePI();
     616           0 :     pi->mTarget = target;
     617           0 :     pi->mData = data;
     618             : 
     619           0 :     if (mState == eInProlog) {
     620             :         // Note: passing in already addrefed pi
     621           0 :         return mPrototype->AddProcessingInstruction(pi);
     622             :     }
     623             : 
     624             :     nsresult rv;
     625           0 :     nsPrototypeArray* children = nullptr;
     626           0 :     rv = mContextStack.GetTopChildren(&children);
     627           0 :     if (NS_FAILED(rv)) {
     628           0 :         return rv;
     629             :     }
     630             : 
     631           0 :     if (!children->AppendElement(pi)) {
     632           0 :         return NS_ERROR_OUT_OF_MEMORY;
     633             :     }
     634             : 
     635           0 :     return NS_OK;
     636             : }
     637             : 
     638             : 
     639             : NS_IMETHODIMP
     640           0 : XULContentSinkImpl::HandleXMLDeclaration(const char16_t *aVersion,
     641             :                                          const char16_t *aEncoding,
     642             :                                          int32_t aStandalone)
     643             : {
     644           0 :   return NS_OK;
     645             : }
     646             : 
     647             : 
     648             : NS_IMETHODIMP
     649           0 : XULContentSinkImpl::ReportError(const char16_t* aErrorText,
     650             :                                 const char16_t* aSourceText,
     651             :                                 nsIScriptError *aError,
     652             :                                 bool *_retval)
     653             : {
     654           0 :   NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
     655             : 
     656             :   // The expat driver should report the error.
     657           0 :   *_retval = true;
     658             : 
     659           0 :   nsresult rv = NS_OK;
     660             : 
     661             :   // make sure to empty the context stack so that
     662             :   // <parsererror> could become the root element.
     663           0 :   mContextStack.Clear();
     664             : 
     665           0 :   mState = eInProlog;
     666             : 
     667             :   // Clear any buffered-up text we have.  It's enough to set the length to 0.
     668             :   // The buffer itself is allocated when we're created and deleted in our
     669             :   // destructor, so don't mess with it.
     670           0 :   mTextLength = 0;
     671             : 
     672             :   // return leaving the document empty if we're asked to not add a <parsererror> root node
     673           0 :   nsCOMPtr<nsIDocument> idoc = do_QueryReferent(mDocument);
     674           0 :   if (idoc && idoc->SuppressParserErrorElement()) {
     675           0 :     return NS_OK;
     676             :   };
     677             : 
     678           0 :   nsCOMPtr<nsIXULDocument> doc = do_QueryReferent(mDocument);
     679           0 :   if (doc && !doc->OnDocumentParserError()) {
     680             :     // The overlay was broken.  Don't add a messy element to the master doc.
     681           0 :     return NS_OK;
     682             :   }
     683             : 
     684           0 :   const char16_t* noAtts[] = { 0, 0 };
     685             : 
     686           0 :   NS_NAMED_LITERAL_STRING(errorNs,
     687             :                           "http://www.mozilla.org/newlayout/xml/parsererror.xml");
     688             : 
     689           0 :   nsAutoString parsererror(errorNs);
     690           0 :   parsererror.Append((char16_t)0xFFFF);
     691           0 :   parsererror.AppendLiteral("parsererror");
     692             : 
     693           0 :   rv = HandleStartElement(parsererror.get(), noAtts, 0, 0);
     694           0 :   NS_ENSURE_SUCCESS(rv,rv);
     695             : 
     696           0 :   rv = HandleCharacterData(aErrorText, NS_strlen(aErrorText));
     697           0 :   NS_ENSURE_SUCCESS(rv,rv);
     698             : 
     699           0 :   nsAutoString sourcetext(errorNs);
     700           0 :   sourcetext.Append((char16_t)0xFFFF);
     701           0 :   sourcetext.AppendLiteral("sourcetext");
     702             : 
     703           0 :   rv = HandleStartElement(sourcetext.get(), noAtts, 0, 0);
     704           0 :   NS_ENSURE_SUCCESS(rv,rv);
     705             : 
     706           0 :   rv = HandleCharacterData(aSourceText, NS_strlen(aSourceText));
     707           0 :   NS_ENSURE_SUCCESS(rv,rv);
     708             : 
     709           0 :   rv = HandleEndElement(sourcetext.get());
     710           0 :   NS_ENSURE_SUCCESS(rv,rv);
     711             : 
     712           0 :   rv = HandleEndElement(parsererror.get());
     713           0 :   NS_ENSURE_SUCCESS(rv,rv);
     714             : 
     715           0 :   return rv;
     716             : }
     717             : 
     718             : nsresult
     719           0 : XULContentSinkImpl::OpenRoot(const char16_t** aAttributes,
     720             :                              const uint32_t aAttrLen,
     721             :                              mozilla::dom::NodeInfo *aNodeInfo)
     722             : {
     723           0 :     NS_ASSERTION(mState == eInProlog, "how'd we get here?");
     724           0 :     if (mState != eInProlog)
     725           0 :         return NS_ERROR_UNEXPECTED;
     726             : 
     727             :     nsresult rv;
     728             : 
     729           0 :     if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) ||
     730           0 :         aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XUL)) {
     731           0 :         MOZ_LOG(gContentSinkLog, LogLevel::Error,
     732             :                ("xul: script tag not allowed as root content element"));
     733             : 
     734           0 :         return NS_ERROR_UNEXPECTED;
     735             :     }
     736             : 
     737             :     // Create the element
     738             :     nsXULPrototypeElement* element;
     739           0 :     rv = CreateElement(aNodeInfo, &element);
     740             : 
     741           0 :     if (NS_FAILED(rv)) {
     742           0 :         if (MOZ_LOG_TEST(gContentSinkLog, LogLevel::Error)) {
     743           0 :             nsAutoString anodeC;
     744           0 :             aNodeInfo->GetName(anodeC);
     745           0 :             MOZ_LOG(gContentSinkLog, LogLevel::Error,
     746             :                    ("xul: unable to create element '%s' at line %d",
     747             :                     NS_ConvertUTF16toUTF8(anodeC).get(),
     748             :                     -1)); // XXX pass in line number
     749             :         }
     750             : 
     751           0 :         return rv;
     752             :     }
     753             : 
     754             :     // Push the element onto the context stack, so that child
     755             :     // containers will hook up to us as their parent.
     756           0 :     rv = mContextStack.Push(element, mState);
     757           0 :     if (NS_FAILED(rv)) {
     758           0 :         element->Release();
     759           0 :         return rv;
     760             :     }
     761             : 
     762             :     // Add the attributes
     763           0 :     rv = AddAttributes(aAttributes, aAttrLen, element);
     764           0 :     if (NS_FAILED(rv)) return rv;
     765             : 
     766           0 :     mState = eInDocumentElement;
     767           0 :     return NS_OK;
     768             : }
     769             : 
     770             : nsresult
     771           0 : XULContentSinkImpl::OpenTag(const char16_t** aAttributes,
     772             :                             const uint32_t aAttrLen,
     773             :                             const uint32_t aLineNumber,
     774             :                             mozilla::dom::NodeInfo *aNodeInfo)
     775             : {
     776             :     nsresult rv;
     777             : 
     778             :     // Create the element
     779             :     nsXULPrototypeElement* element;
     780           0 :     rv = CreateElement(aNodeInfo, &element);
     781             : 
     782           0 :     if (NS_FAILED(rv)) {
     783           0 :         if (MOZ_LOG_TEST(gContentSinkLog, LogLevel::Error)) {
     784           0 :             nsAutoString anodeC;
     785           0 :             aNodeInfo->GetName(anodeC);
     786           0 :             MOZ_LOG(gContentSinkLog, LogLevel::Error,
     787             :                    ("xul: unable to create element '%s' at line %d",
     788             :                     NS_ConvertUTF16toUTF8(anodeC).get(),
     789             :                     aLineNumber));
     790             :         }
     791             : 
     792           0 :         return rv;
     793             :     }
     794             : 
     795             :     // Link this element to its parent.
     796           0 :     nsPrototypeArray* children = nullptr;
     797           0 :     rv = mContextStack.GetTopChildren(&children);
     798           0 :     if (NS_FAILED(rv)) {
     799           0 :         delete element;
     800           0 :         return rv;
     801             :     }
     802             : 
     803             :     // Add the attributes
     804           0 :     rv = AddAttributes(aAttributes, aAttrLen, element);
     805           0 :     if (NS_FAILED(rv)) return rv;
     806             : 
     807           0 :     children->AppendElement(element);
     808             : 
     809           0 :     if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) ||
     810           0 :         aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XUL)) {
     811             :         // Do scripty things now
     812           0 :         rv = OpenScript(aAttributes, aLineNumber);
     813           0 :         NS_ENSURE_SUCCESS(rv, rv);
     814             : 
     815           0 :         NS_ASSERTION(mState == eInScript || mState == eInDocumentElement,
     816             :                      "Unexpected state");
     817           0 :         if (mState == eInScript) {
     818             :             // OpenScript has pushed the nsPrototypeScriptElement onto the
     819             :             // stack, so we're done.
     820           0 :             return NS_OK;
     821             :         }
     822             :     }
     823             : 
     824             :     // Push the element onto the context stack, so that child
     825             :     // containers will hook up to us as their parent.
     826           0 :     rv = mContextStack.Push(element, mState);
     827           0 :     if (NS_FAILED(rv)) return rv;
     828             : 
     829           0 :     mState = eInDocumentElement;
     830           0 :     return NS_OK;
     831             : }
     832             : 
     833             : nsresult
     834           0 : XULContentSinkImpl::OpenScript(const char16_t** aAttributes,
     835             :                                const uint32_t aLineNumber)
     836             : {
     837           0 :   bool isJavaScript = true;
     838           0 :   uint32_t version = JSVERSION_LATEST;
     839             :   nsresult rv;
     840             : 
     841             :   // Look for SRC attribute and look for a LANGUAGE attribute
     842           0 :   nsAutoString src;
     843           0 :   while (*aAttributes) {
     844           0 :       const nsDependentString key(aAttributes[0]);
     845           0 :       if (key.EqualsLiteral("src")) {
     846           0 :           src.Assign(aAttributes[1]);
     847           0 :       } else if (key.EqualsLiteral("type")) {
     848           0 :           nsDependentString str(aAttributes[1]);
     849           0 :           nsContentTypeParser parser(str);
     850           0 :           nsAutoString mimeType;
     851           0 :           rv = parser.GetType(mimeType);
     852           0 :           if (NS_FAILED(rv)) {
     853           0 :               if (rv == NS_ERROR_INVALID_ARG) {
     854             :                   // Fail immediately rather than checking if later things
     855             :                   // are okay.
     856           0 :                   return NS_OK;
     857             :               }
     858             :               // We do want the warning here
     859           0 :               NS_ENSURE_SUCCESS(rv, rv);
     860             :           }
     861             : 
     862           0 :           if (nsContentUtils::IsJavascriptMIMEType(mimeType)) {
     863           0 :               isJavaScript = true;
     864           0 :               version = JSVERSION_LATEST;
     865             : 
     866             :               // Get the version string, and ensure that JavaScript supports it.
     867           0 :               nsAutoString versionName;
     868           0 :               rv = parser.GetParameter("version", versionName);
     869             : 
     870           0 :               if (NS_SUCCEEDED(rv)) {
     871           0 :                   version = nsContentUtils::ParseJavascriptVersion(versionName);
     872           0 :               } else if (rv != NS_ERROR_INVALID_ARG) {
     873           0 :                   return rv;
     874             :               }
     875             :           } else {
     876           0 :               isJavaScript = false;
     877             :           }
     878           0 :       } else if (key.EqualsLiteral("language")) {
     879             :           // Language is deprecated, and the impl in ScriptLoader ignores the
     880             :           // various version strings anyway.  So we make no attempt to support
     881             :           // languages other than JS for language=
     882           0 :           nsAutoString lang(aAttributes[1]);
     883           0 :           if (nsContentUtils::IsJavaScriptLanguage(lang)) {
     884           0 :               isJavaScript = true;
     885           0 :               version = JSVERSION_DEFAULT;
     886             :           }
     887             :       }
     888           0 :       aAttributes += 2;
     889             :   }
     890             : 
     891             :   // Don't process scripts that aren't JavaScript.
     892           0 :   if (!isJavaScript) {
     893           0 :       return NS_OK;
     894             :   }
     895             : 
     896           0 :   nsCOMPtr<nsIDocument> doc(do_QueryReferent(mDocument));
     897           0 :   nsCOMPtr<nsIScriptGlobalObject> globalObject;
     898           0 :   if (doc)
     899           0 :       globalObject = do_QueryInterface(doc->GetWindow());
     900             :   RefPtr<nsXULPrototypeScript> script =
     901           0 :       new nsXULPrototypeScript(aLineNumber, version);
     902             : 
     903             :   // If there is a SRC attribute...
     904           0 :   if (! src.IsEmpty()) {
     905             :       // Use the SRC attribute value to load the URL
     906           0 :       rv = NS_NewURI(getter_AddRefs(script->mSrcURI), src, nullptr, mDocumentURL);
     907             : 
     908             :       // Check if this document is allowed to load a script from this source
     909             :       // NOTE: if we ever allow scripts added via the DOM to run, we need to
     910             :       // add a CheckLoadURI call for that as well.
     911           0 :       if (NS_SUCCEEDED(rv)) {
     912           0 :           if (!mSecMan)
     913           0 :               mSecMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     914           0 :           if (NS_SUCCEEDED(rv)) {
     915           0 :               nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument, &rv);
     916             : 
     917           0 :               if (NS_SUCCEEDED(rv)) {
     918           0 :                   rv = mSecMan->
     919           0 :                       CheckLoadURIWithPrincipal(doc->NodePrincipal(),
     920           0 :                                                 script->mSrcURI,
     921           0 :                                                 nsIScriptSecurityManager::ALLOW_CHROME);
     922             :               }
     923             :           }
     924             :       }
     925             : 
     926           0 :       if (NS_FAILED(rv)) {
     927           0 :           return rv;
     928             :       }
     929             : 
     930             :       // Attempt to deserialize an out-of-line script from the FastLoad
     931             :       // file right away.  Otherwise we'll end up reloading the script and
     932             :       // corrupting the FastLoad file trying to serialize it, in the case
     933             :       // where it's already there.
     934           0 :       script->DeserializeOutOfLine(nullptr, mPrototype);
     935             :   }
     936             : 
     937           0 :   nsPrototypeArray* children = nullptr;
     938           0 :   rv = mContextStack.GetTopChildren(&children);
     939           0 :   if (NS_FAILED(rv)) {
     940           0 :       return rv;
     941             :   }
     942             : 
     943           0 :   children->AppendElement(script);
     944             : 
     945           0 :   mConstrainSize = false;
     946             : 
     947           0 :   mContextStack.Push(script, mState);
     948           0 :   mState = eInScript;
     949             : 
     950           0 :   return NS_OK;
     951             : }
     952             : 
     953             : nsresult
     954           0 : XULContentSinkImpl::AddAttributes(const char16_t** aAttributes,
     955             :                                   const uint32_t aAttrLen,
     956             :                                   nsXULPrototypeElement* aElement)
     957             : {
     958             :   // Add tag attributes to the element
     959             :   nsresult rv;
     960             : 
     961             :   // Create storage for the attributes
     962           0 :   nsXULPrototypeAttribute* attrs = nullptr;
     963           0 :   if (aAttrLen > 0) {
     964           0 :     attrs = new nsXULPrototypeAttribute[aAttrLen];
     965             :   }
     966             : 
     967           0 :   aElement->mAttributes    = attrs;
     968           0 :   aElement->mNumAttributes = aAttrLen;
     969             : 
     970             :   // Copy the attributes into the prototype
     971             :   uint32_t i;
     972           0 :   for (i = 0; i < aAttrLen; ++i) {
     973           0 :       rv = NormalizeAttributeString(aAttributes[i * 2], attrs[i].mName);
     974           0 :       NS_ENSURE_SUCCESS(rv, rv);
     975             : 
     976           0 :       rv = aElement->SetAttrAt(i, nsDependentString(aAttributes[i * 2 + 1]),
     977           0 :                                mDocumentURL);
     978           0 :       NS_ENSURE_SUCCESS(rv, rv);
     979             : 
     980           0 :       if (MOZ_LOG_TEST(gContentSinkLog, LogLevel::Debug)) {
     981           0 :           nsAutoString extraWhiteSpace;
     982           0 :           int32_t cnt = mContextStack.Depth();
     983           0 :           while (--cnt >= 0)
     984           0 :               extraWhiteSpace.AppendLiteral("  ");
     985           0 :           nsAutoString qnameC,valueC;
     986           0 :           qnameC.Assign(aAttributes[0]);
     987           0 :           valueC.Assign(aAttributes[1]);
     988           0 :           MOZ_LOG(gContentSinkLog, LogLevel::Debug,
     989             :                  ("xul: %.5d. %s    %s=%s",
     990             :                   -1, // XXX pass in line number
     991             :                   NS_ConvertUTF16toUTF8(extraWhiteSpace).get(),
     992             :                   NS_ConvertUTF16toUTF8(qnameC).get(),
     993             :                   NS_ConvertUTF16toUTF8(valueC).get()));
     994             :       }
     995             :   }
     996             : 
     997           0 :   return NS_OK;
     998             : }
     999             : 
    1000             : nsresult
    1001           0 : XULContentSinkImpl::AddText(const char16_t* aText,
    1002             :                             int32_t aLength)
    1003             : {
    1004             :   // Create buffer when we first need it
    1005           0 :   if (0 == mTextSize) {
    1006           0 :       mText = (char16_t *) malloc(sizeof(char16_t) * 4096);
    1007           0 :       if (nullptr == mText) {
    1008           0 :           return NS_ERROR_OUT_OF_MEMORY;
    1009             :       }
    1010           0 :       mTextSize = 4096;
    1011             :   }
    1012             : 
    1013             :   // Copy data from string into our buffer; flush buffer when it fills up
    1014           0 :   int32_t offset = 0;
    1015           0 :   while (0 != aLength) {
    1016           0 :     int32_t amount = mTextSize - mTextLength;
    1017           0 :     if (amount > aLength) {
    1018           0 :         amount = aLength;
    1019             :     }
    1020           0 :     if (0 == amount) {
    1021           0 :       if (mConstrainSize) {
    1022           0 :         nsresult rv = FlushText();
    1023           0 :         if (NS_OK != rv) {
    1024           0 :             return rv;
    1025             :         }
    1026             :       } else {
    1027           0 :         CheckedInt32 size = mTextSize;
    1028           0 :         size += aLength;
    1029           0 :         if (!size.isValid()) {
    1030           0 :           return NS_ERROR_OUT_OF_MEMORY;
    1031             :         }
    1032           0 :         mTextSize = size.value();
    1033             : 
    1034           0 :         mText = (char16_t *) realloc(mText, sizeof(char16_t) * mTextSize);
    1035           0 :         if (nullptr == mText) {
    1036           0 :             return NS_ERROR_OUT_OF_MEMORY;
    1037             :         }
    1038             :       }
    1039             :     }
    1040           0 :     memcpy(&mText[mTextLength],aText + offset, sizeof(char16_t) * amount);
    1041             : 
    1042           0 :     mTextLength += amount;
    1043           0 :     offset += amount;
    1044           0 :     aLength -= amount;
    1045             :   }
    1046             : 
    1047           0 :   return NS_OK;
    1048             : }

Generated by: LCOV version 1.13