LCOV - code coverage report
Current view: directory - content/xul/document/src - nsXULContentSink.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 532 0 0.0 %
Date: 2012-06-02 Functions: 41 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       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                 :  *   Chris Waterson <waterson@netscape.com>
      24                 :  *   David Hyatt <hyatt@netscape.com>
      25                 :  *   Brendan Eich <brendan@mozilla.org>
      26                 :  *   Mark Hammond <mhammond@skippinet.com.au>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : /*
      43                 :  * An implementation for a Gecko-style content sink that knows how
      44                 :  * to build a content model (the "prototype" document) from XUL.
      45                 :  *
      46                 :  * For more information on XUL,
      47                 :  * see http://developer.mozilla.org/en/docs/XUL
      48                 :  */
      49                 : 
      50                 : #include "jsapi.h"
      51                 : #include "jsfriendapi.h"
      52                 : #include "nsXULContentSink.h"
      53                 : #include "nsCOMPtr.h"
      54                 : #include "nsForwardReference.h"
      55                 : #include "nsIContentSink.h"
      56                 : #include "nsIDOMDocument.h"
      57                 : #include "nsIDOMEventListener.h"
      58                 : #include "nsIDOMHTMLFormElement.h"
      59                 : #include "nsIDOMXULDocument.h"
      60                 : #include "nsIDocument.h"
      61                 : #include "nsIFormControl.h"
      62                 : #include "nsHTMLStyleSheet.h"
      63                 : #include "nsINameSpaceManager.h"
      64                 : #include "nsINodeInfo.h"
      65                 : #include "nsIParser.h"
      66                 : #include "nsIScriptContext.h"
      67                 : #include "nsIScriptRuntime.h"
      68                 : #include "nsIScriptGlobalObject.h"
      69                 : #include "nsIServiceManager.h"
      70                 : #include "nsIURL.h"
      71                 : #include "nsIViewManager.h"
      72                 : #include "nsIXULDocument.h"
      73                 : #include "nsIScriptSecurityManager.h"
      74                 : #include "nsLayoutCID.h"
      75                 : #include "nsNetUtil.h"
      76                 : #include "nsRDFCID.h"
      77                 : #include "nsXPIDLString.h"
      78                 : #include "nsReadableUtils.h"
      79                 : #include "nsXULElement.h"
      80                 : #include "prlog.h"
      81                 : #include "prmem.h"
      82                 : #include "nsCRT.h"
      83                 : 
      84                 : #include "nsXULPrototypeDocument.h"     // XXXbe temporary
      85                 : #include "mozilla/css/Loader.h"
      86                 : 
      87                 : #include "nsUnicharUtils.h"
      88                 : #include "nsGkAtoms.h"
      89                 : #include "nsContentUtils.h"
      90                 : #include "nsAttrName.h"
      91                 : #include "nsXMLContentSink.h"
      92                 : #include "nsIConsoleService.h"
      93                 : #include "nsIScriptError.h"
      94                 : 
      95                 : #ifdef PR_LOGGING
      96                 : static PRLogModuleInfo* gLog;
      97                 : #endif
      98                 : 
      99                 : //----------------------------------------------------------------------
     100                 : 
     101               0 : XULContentSinkImpl::ContextStack::ContextStack()
     102               0 :     : mTop(nsnull), mDepth(0)
     103                 : {
     104               0 : }
     105                 : 
     106               0 : XULContentSinkImpl::ContextStack::~ContextStack()
     107                 : {
     108               0 :     while (mTop) {
     109               0 :         Entry* doomed = mTop;
     110               0 :         mTop = mTop->mNext;
     111               0 :         delete doomed;
     112                 :     }
     113               0 : }
     114                 : 
     115                 : nsresult
     116               0 : XULContentSinkImpl::ContextStack::Push(nsXULPrototypeNode* aNode, State aState)
     117                 : {
     118               0 :     Entry* entry = new Entry;
     119               0 :     if (! entry)
     120               0 :         return NS_ERROR_OUT_OF_MEMORY;
     121                 : 
     122               0 :     entry->mNode  = aNode;
     123               0 :     entry->mState = aState;
     124               0 :     entry->mNext  = mTop;
     125               0 :     mTop = entry;
     126                 : 
     127               0 :     ++mDepth;
     128               0 :     return NS_OK;
     129                 : }
     130                 : 
     131                 : nsresult
     132               0 : XULContentSinkImpl::ContextStack::Pop(State* aState)
     133                 : {
     134               0 :     if (mDepth == 0)
     135               0 :         return NS_ERROR_UNEXPECTED;
     136                 : 
     137               0 :     Entry* entry = mTop;
     138               0 :     mTop = mTop->mNext;
     139               0 :     --mDepth;
     140                 : 
     141               0 :     *aState = entry->mState;
     142               0 :     delete entry;
     143                 : 
     144               0 :     return NS_OK;
     145                 : }
     146                 : 
     147                 : 
     148                 : nsresult
     149               0 : XULContentSinkImpl::ContextStack::GetTopNode(nsRefPtr<nsXULPrototypeNode>& aNode)
     150                 : {
     151               0 :     if (mDepth == 0)
     152               0 :         return NS_ERROR_UNEXPECTED;
     153                 : 
     154               0 :     aNode = mTop->mNode;
     155               0 :     return NS_OK;
     156                 : }
     157                 : 
     158                 : 
     159                 : nsresult
     160               0 : XULContentSinkImpl::ContextStack::GetTopChildren(nsPrototypeArray** aChildren)
     161                 : {
     162               0 :     if (mDepth == 0)
     163               0 :         return NS_ERROR_UNEXPECTED;
     164                 : 
     165               0 :     *aChildren = &(mTop->mChildren);
     166               0 :     return NS_OK;
     167                 : }
     168                 : 
     169                 : nsresult
     170               0 : XULContentSinkImpl::ContextStack::GetTopNodeScriptType(PRUint32 *aScriptType)
     171                 : {
     172               0 :     if (mDepth == 0)
     173               0 :         return NS_ERROR_UNEXPECTED;
     174                 : 
     175                 :     // This would be much simpler if nsXULPrototypeNode itself
     176                 :     // stored the language ID - but text elements don't need it!
     177               0 :     nsresult rv = NS_OK;
     178               0 :     nsRefPtr<nsXULPrototypeNode> node;
     179               0 :     rv = GetTopNode(node);
     180               0 :     if (NS_FAILED(rv)) return rv;
     181               0 :     switch (node->mType) {
     182                 :         case nsXULPrototypeNode::eType_Element: {
     183                 :             nsXULPrototypeElement *parent =
     184               0 :                 reinterpret_cast<nsXULPrototypeElement*>(node.get());
     185               0 :             *aScriptType = parent->mScriptTypeID;
     186               0 :             break;
     187                 :         }
     188                 :         case nsXULPrototypeNode::eType_Script: {
     189                 :             nsXULPrototypeScript *parent =
     190               0 :                 reinterpret_cast<nsXULPrototypeScript*>(node.get());
     191               0 :             *aScriptType = parent->mScriptObject.mLangID;
     192               0 :             break;
     193                 :         }
     194                 :         default: {
     195               0 :             NS_WARNING("Unexpected parent node type");
     196               0 :             rv = NS_ERROR_UNEXPECTED;
     197                 :         }
     198                 :     }
     199               0 :     return rv;
     200                 : }
     201                 : 
     202                 : void
     203               0 : XULContentSinkImpl::ContextStack::Clear()
     204                 : {
     205               0 :   Entry *cur = mTop;
     206               0 :   while (cur) {
     207                 :     // Release the root element (and its descendants).
     208               0 :     Entry *next = cur->mNext;
     209               0 :     delete cur;
     210               0 :     cur = next;
     211                 :   }
     212                 : 
     213               0 :   mTop = nsnull;
     214               0 :   mDepth = 0;
     215               0 : }
     216                 : 
     217                 : //----------------------------------------------------------------------
     218                 : 
     219                 : 
     220               0 : XULContentSinkImpl::XULContentSinkImpl()
     221                 :     : mText(nsnull),
     222                 :       mTextLength(0),
     223                 :       mTextSize(0),
     224                 :       mConstrainSize(true),
     225                 :       mState(eInProlog),
     226               0 :       mParser(nsnull)
     227                 : {
     228                 : 
     229                 : #ifdef PR_LOGGING
     230               0 :     if (! gLog)
     231               0 :         gLog = PR_NewLogModule("nsXULContentSink");
     232                 : #endif
     233               0 : }
     234                 : 
     235                 : 
     236               0 : XULContentSinkImpl::~XULContentSinkImpl()
     237                 : {
     238               0 :     NS_IF_RELEASE(mParser); // XXX should've been released by now, unless error.
     239                 : 
     240                 :     // The context stack _should_ be empty, unless something has gone wrong.
     241               0 :     NS_ASSERTION(mContextStack.Depth() == 0, "Context stack not empty?");
     242               0 :     mContextStack.Clear();
     243                 : 
     244               0 :     PR_FREEIF(mText);
     245               0 : }
     246                 : 
     247                 : //----------------------------------------------------------------------
     248                 : // nsISupports interface
     249                 : 
     250               0 : NS_IMPL_ISUPPORTS3(XULContentSinkImpl,
     251                 :                    nsIXMLContentSink,
     252                 :                    nsIContentSink,
     253                 :                    nsIExpatSink)
     254                 : 
     255                 : //----------------------------------------------------------------------
     256                 : // nsIContentSink interface
     257                 : 
     258                 : NS_IMETHODIMP 
     259               0 : XULContentSinkImpl::WillBuildModel(nsDTDMode aDTDMode)
     260                 : {
     261                 : #if FIXME
     262                 :     if (! mParentContentSink) {
     263                 :         // If we're _not_ an overlay, then notify the document that
     264                 :         // the load is beginning.
     265                 :         mDocument->BeginLoad();
     266                 :     }
     267                 : #endif
     268                 : 
     269               0 :     return NS_OK;
     270                 : }
     271                 : 
     272                 : NS_IMETHODIMP 
     273               0 : XULContentSinkImpl::DidBuildModel(bool aTerminated)
     274                 : {
     275               0 :     nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
     276               0 :     if (doc) {
     277               0 :         doc->EndLoad();
     278               0 :         mDocument = nsnull;
     279                 :     }
     280                 : 
     281                 :     // Drop our reference to the parser to get rid of a circular
     282                 :     // reference.
     283               0 :     NS_IF_RELEASE(mParser);
     284               0 :     return NS_OK;
     285                 : }
     286                 : 
     287                 : NS_IMETHODIMP 
     288               0 : XULContentSinkImpl::WillInterrupt(void)
     289                 : {
     290                 :     // XXX Notify the docshell, if necessary
     291               0 :     return NS_OK;
     292                 : }
     293                 : 
     294                 : NS_IMETHODIMP 
     295               0 : XULContentSinkImpl::WillResume(void)
     296                 : {
     297                 :     // XXX Notify the docshell, if necessary
     298               0 :     return NS_OK;
     299                 : }
     300                 : 
     301                 : NS_IMETHODIMP 
     302               0 : XULContentSinkImpl::SetParser(nsParserBase* aParser)
     303                 : {
     304               0 :     NS_IF_RELEASE(mParser);
     305               0 :     mParser = aParser;
     306               0 :     NS_IF_ADDREF(mParser);
     307               0 :     return NS_OK;
     308                 : }
     309                 : 
     310                 : NS_IMETHODIMP 
     311               0 : XULContentSinkImpl::SetDocumentCharset(nsACString& aCharset)
     312                 : {
     313               0 :     nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
     314               0 :     if (doc) {
     315               0 :         doc->SetDocumentCharacterSet(aCharset);
     316                 :     }
     317                 :   
     318               0 :     return NS_OK;
     319                 : }
     320                 : 
     321                 : nsISupports *
     322               0 : XULContentSinkImpl::GetTarget()
     323                 : {
     324               0 :     nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
     325               0 :     return doc;    
     326                 : }
     327                 : 
     328                 : //----------------------------------------------------------------------
     329                 : 
     330                 : nsresult
     331               0 : XULContentSinkImpl::Init(nsIDocument* aDocument,
     332                 :                          nsXULPrototypeDocument* aPrototype)
     333                 : {
     334               0 :     NS_PRECONDITION(aDocument != nsnull, "null ptr");
     335               0 :     if (! aDocument)
     336               0 :         return NS_ERROR_NULL_POINTER;
     337                 :     
     338                 :     nsresult rv;
     339                 : 
     340               0 :     mDocument    = do_GetWeakReference(aDocument);
     341               0 :     mPrototype   = aPrototype;
     342                 : 
     343               0 :     mDocumentURL = mPrototype->GetURI();
     344                 : 
     345                 :     // XXX this presumes HTTP header info is already set in document
     346                 :     // XXX if it isn't we need to set it here...
     347                 :     // XXXbz not like GetHeaderData on the proto doc _does_ anything....
     348               0 :     nsAutoString preferredStyle;
     349               0 :     rv = mPrototype->GetHeaderData(nsGkAtoms::headerDefaultStyle,
     350               0 :                                    preferredStyle);
     351               0 :     if (NS_FAILED(rv)) return rv;
     352                 : 
     353               0 :     if (!preferredStyle.IsEmpty()) {
     354                 :         aDocument->SetHeaderData(nsGkAtoms::headerDefaultStyle,
     355               0 :                                  preferredStyle);
     356                 :     }
     357                 : 
     358                 :     // Set the right preferred style on the document's CSSLoader.
     359               0 :     aDocument->CSSLoader()->SetPreferredSheet(preferredStyle);
     360                 : 
     361               0 :     mNodeInfoManager = aPrototype->GetNodeInfoManager();
     362               0 :     if (! mNodeInfoManager)
     363               0 :         return NS_ERROR_UNEXPECTED;
     364                 : 
     365               0 :     mState = eInProlog;
     366               0 :     return NS_OK;
     367                 : }
     368                 : 
     369                 : 
     370                 : //----------------------------------------------------------------------
     371                 : //
     372                 : // Text buffering
     373                 : //
     374                 : 
     375                 : bool
     376               0 : XULContentSinkImpl::IsDataInBuffer(PRUnichar* buffer, PRInt32 length)
     377                 : {
     378               0 :     for (PRInt32 i = 0; i < length; ++i) {
     379               0 :         if (buffer[i] == ' ' ||
     380               0 :             buffer[i] == '\t' ||
     381               0 :             buffer[i] == '\n' ||
     382               0 :             buffer[i] == '\r')
     383               0 :             continue;
     384                 : 
     385               0 :         return true;
     386                 :     }
     387               0 :     return false;
     388                 : }
     389                 : 
     390                 : 
     391                 : nsresult
     392               0 : XULContentSinkImpl::FlushText(bool aCreateTextNode)
     393                 : {
     394                 :     nsresult rv;
     395                 : 
     396                 :     do {
     397                 :         // Don't do anything if there's no text to create a node from, or
     398                 :         // if they've told us not to create a text node
     399               0 :         if (! mTextLength)
     400               0 :             break;
     401                 : 
     402               0 :         if (! aCreateTextNode)
     403               0 :             break;
     404                 : 
     405               0 :         nsRefPtr<nsXULPrototypeNode> node;
     406               0 :         rv = mContextStack.GetTopNode(node);
     407               0 :         if (NS_FAILED(rv)) return rv;
     408                 : 
     409               0 :         bool stripWhitespace = false;
     410               0 :         if (node->mType == nsXULPrototypeNode::eType_Element) {
     411                 :             nsINodeInfo *nodeInfo =
     412               0 :                 static_cast<nsXULPrototypeElement*>(node.get())->mNodeInfo;
     413                 : 
     414               0 :             if (nodeInfo->NamespaceEquals(kNameSpaceID_XUL))
     415               0 :                 stripWhitespace = !nodeInfo->Equals(nsGkAtoms::label) &&
     416               0 :                                   !nodeInfo->Equals(nsGkAtoms::description);
     417                 :         }
     418                 : 
     419                 :         // Don't bother if there's nothing but whitespace.
     420               0 :         if (stripWhitespace && ! IsDataInBuffer(mText, mTextLength))
     421                 :             break;
     422                 : 
     423                 :         // Don't bother if we're not in XUL document body
     424               0 :         if (mState != eInDocumentElement || mContextStack.Depth() == 0)
     425                 :             break;
     426                 : 
     427               0 :         nsXULPrototypeText* text = new nsXULPrototypeText();
     428               0 :         if (! text)
     429               0 :             return NS_ERROR_OUT_OF_MEMORY;
     430                 : 
     431               0 :         text->mValue.Assign(mText, mTextLength);
     432               0 :         if (stripWhitespace)
     433               0 :             text->mValue.Trim(" \t\n\r");
     434                 : 
     435                 :         // hook it up
     436               0 :         nsPrototypeArray* children = nsnull;
     437               0 :         rv = mContextStack.GetTopChildren(&children);
     438               0 :         if (NS_FAILED(rv)) return rv;
     439                 : 
     440                 :         // transfer ownership of 'text' to the children array
     441               0 :         children->AppendElement(text);
     442                 :     } while (0);
     443                 : 
     444                 :     // Reset our text buffer
     445               0 :     mTextLength = 0;
     446               0 :     return NS_OK;
     447                 : }
     448                 : 
     449                 : //----------------------------------------------------------------------
     450                 : 
     451                 : nsresult
     452               0 : XULContentSinkImpl::NormalizeAttributeString(const PRUnichar *aExpatName,
     453                 :                                              nsAttrName &aName)
     454                 : {
     455                 :     PRInt32 nameSpaceID;
     456               0 :     nsCOMPtr<nsIAtom> prefix, localName;
     457               0 :     nsContentUtils::SplitExpatName(aExpatName, getter_AddRefs(prefix),
     458               0 :                                    getter_AddRefs(localName), &nameSpaceID);
     459                 : 
     460               0 :     if (nameSpaceID == kNameSpaceID_None) {
     461               0 :         aName.SetTo(localName);
     462                 : 
     463               0 :         return NS_OK;
     464                 :     }
     465                 : 
     466               0 :     nsCOMPtr<nsINodeInfo> ni;
     467                 :     ni = mNodeInfoManager->GetNodeInfo(localName, prefix,
     468                 :                                        nameSpaceID,
     469               0 :                                        nsIDOMNode::ATTRIBUTE_NODE);
     470               0 :     NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
     471                 : 
     472               0 :     aName.SetTo(ni);
     473                 : 
     474               0 :     return NS_OK;
     475                 : }
     476                 : 
     477                 : nsresult
     478               0 : XULContentSinkImpl::CreateElement(nsINodeInfo *aNodeInfo,
     479                 :                                   nsXULPrototypeElement** aResult)
     480                 : {
     481               0 :     nsXULPrototypeElement* element = new nsXULPrototypeElement();
     482               0 :     if (! element)
     483               0 :         return NS_ERROR_OUT_OF_MEMORY;
     484                 : 
     485               0 :     element->mNodeInfo    = aNodeInfo;
     486                 :     
     487               0 :     *aResult = element;
     488               0 :     return NS_OK;
     489                 : }
     490                 : 
     491                 : /**** BEGIN NEW APIs ****/
     492                 : 
     493                 : 
     494                 : NS_IMETHODIMP 
     495               0 : XULContentSinkImpl::HandleStartElement(const PRUnichar *aName, 
     496                 :                                        const PRUnichar **aAtts,
     497                 :                                        PRUint32 aAttsCount, 
     498                 :                                        PRInt32 aIndex, 
     499                 :                                        PRUint32 aLineNumber)
     500                 : { 
     501                 :   // XXX Hopefully the parser will flag this before we get here. If
     502                 :   // we're in the epilog, there should be no new elements
     503               0 :   NS_PRECONDITION(mState != eInEpilog, "tag in XUL doc epilog");
     504               0 :   NS_PRECONDITION(aIndex >= -1, "Bogus aIndex");
     505               0 :   NS_PRECONDITION(aAttsCount % 2 == 0, "incorrect aAttsCount");
     506                 :   // Adjust aAttsCount so it's the actual number of attributes
     507               0 :   aAttsCount /= 2;
     508                 :   
     509               0 :   if (mState == eInEpilog)
     510               0 :       return NS_ERROR_UNEXPECTED;
     511                 : 
     512               0 :   if (mState != eInScript) {
     513               0 :       FlushText();
     514                 :   }
     515                 : 
     516                 :   PRInt32 nameSpaceID;
     517               0 :   nsCOMPtr<nsIAtom> prefix, localName;
     518               0 :   nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
     519               0 :                                  getter_AddRefs(localName), &nameSpaceID);
     520                 : 
     521               0 :   nsCOMPtr<nsINodeInfo> nodeInfo;
     522                 :   nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
     523               0 :                                            nsIDOMNode::ELEMENT_NODE);
     524               0 :   NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
     525                 :   
     526               0 :   nsresult rv = NS_OK;
     527               0 :   switch (mState) {
     528                 :   case eInProlog:
     529                 :       // We're the root document element
     530               0 :       rv = OpenRoot(aAtts, aAttsCount, nodeInfo);
     531               0 :       break;
     532                 : 
     533                 :   case eInDocumentElement:
     534               0 :       rv = OpenTag(aAtts, aAttsCount, aLineNumber, nodeInfo);
     535               0 :       break;
     536                 : 
     537                 :   case eInEpilog:
     538                 :   case eInScript:
     539               0 :       PR_LOG(gLog, PR_LOG_WARNING,
     540                 :              ("xul: warning: unexpected tags in epilog at line %d",
     541                 :              aLineNumber));
     542               0 :       rv = NS_ERROR_UNEXPECTED; // XXX
     543               0 :       break;
     544                 :   }
     545                 : 
     546                 :   // Set the ID attribute atom on the node info object for this node
     547               0 :   if (aIndex != -1 && NS_SUCCEEDED(rv)) {
     548               0 :     nsCOMPtr<nsIAtom> IDAttr = do_GetAtom(aAtts[aIndex]);
     549                 : 
     550               0 :     if (IDAttr) {
     551               0 :       nodeInfo->SetIDAttributeAtom(IDAttr);
     552                 :     }
     553                 :   }
     554                 : 
     555               0 :   return rv;
     556                 : }
     557                 : 
     558                 : NS_IMETHODIMP 
     559               0 : XULContentSinkImpl::HandleEndElement(const PRUnichar *aName)
     560                 : {
     561                 :     // Never EVER return anything but NS_OK or
     562                 :     // NS_ERROR_HTMLPARSER_BLOCK from this method. Doing so will blow
     563                 :     // the parser's little mind all over the planet.
     564                 :     nsresult rv;
     565                 : 
     566               0 :     nsRefPtr<nsXULPrototypeNode> node;
     567               0 :     rv = mContextStack.GetTopNode(node);
     568                 : 
     569               0 :     if (NS_FAILED(rv)) {
     570               0 :       return NS_OK;
     571                 :     }
     572                 : 
     573               0 :     switch (node->mType) {
     574                 :     case nsXULPrototypeNode::eType_Element: {
     575                 :         // Flush any text _now_, so that we'll get text nodes created
     576                 :         // before popping the stack.
     577               0 :         FlushText();
     578                 : 
     579                 :         // Pop the context stack and do prototype hookup.
     580               0 :         nsPrototypeArray* children = nsnull;
     581               0 :         rv = mContextStack.GetTopChildren(&children);
     582               0 :         if (NS_FAILED(rv)) return rv;
     583                 : 
     584                 :         nsXULPrototypeElement* element =
     585               0 :           static_cast<nsXULPrototypeElement*>(node.get());
     586                 : 
     587               0 :         PRInt32 count = children->Length();
     588               0 :         if (count) {
     589               0 :             if (!element->mChildren.SetCapacity(count))
     590               0 :                 return NS_ERROR_OUT_OF_MEMORY;
     591                 : 
     592               0 :             for (PRInt32 i = 0; i < count; ++i)
     593               0 :                 element->mChildren.AppendElement(children->ElementAt(i));
     594                 : 
     595                 :         }
     596                 :     }
     597               0 :     break;
     598                 : 
     599                 :     case nsXULPrototypeNode::eType_Script: {
     600                 :         nsXULPrototypeScript* script =
     601               0 :             static_cast<nsXULPrototypeScript*>(node.get());
     602                 : 
     603                 :         // If given a src= attribute, we must ignore script tag content.
     604               0 :         if (! script->mSrcURI && ! script->mScriptObject.mObject) {
     605               0 :             nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
     606                 : 
     607               0 :             script->mOutOfLine = false;
     608               0 :             if (doc)
     609                 :                 script->Compile(mText, mTextLength, mDocumentURL,
     610               0 :                                 script->mLineNo, doc, mPrototype);
     611                 :         }
     612                 : 
     613               0 :         FlushText(false);
     614                 :     }
     615               0 :     break;
     616                 : 
     617                 :     default:
     618               0 :         NS_ERROR("didn't expect that");
     619               0 :         break;
     620                 :     }
     621                 : 
     622               0 :     rv = mContextStack.Pop(&mState);
     623               0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "context stack corrupted");
     624               0 :     if (NS_FAILED(rv)) return rv;
     625                 : 
     626               0 :     if (mContextStack.Depth() == 0) {
     627                 :         // The root element should -always- be an element, because
     628                 :         // it'll have been created via XULContentSinkImpl::OpenRoot().
     629               0 :         NS_ASSERTION(node->mType == nsXULPrototypeNode::eType_Element, "root is not an element");
     630               0 :         if (node->mType != nsXULPrototypeNode::eType_Element)
     631               0 :             return NS_ERROR_UNEXPECTED;
     632                 : 
     633                 :         // Now that we're done parsing, set the prototype document's
     634                 :         // root element. This transfers ownership of the prototype
     635                 :         // element tree to the prototype document.
     636                 :         nsXULPrototypeElement* element =
     637               0 :             static_cast<nsXULPrototypeElement*>(node.get());
     638                 : 
     639               0 :         mPrototype->SetRootElement(element);
     640               0 :         mState = eInEpilog;
     641                 :     }
     642                 : 
     643               0 :     return NS_OK;
     644                 : }
     645                 : 
     646                 : NS_IMETHODIMP 
     647               0 : XULContentSinkImpl::HandleComment(const PRUnichar *aName)
     648                 : {
     649               0 :    FlushText();
     650               0 :    return NS_OK;
     651                 : }
     652                 : 
     653                 : NS_IMETHODIMP 
     654               0 : XULContentSinkImpl::HandleCDataSection(const PRUnichar *aData, PRUint32 aLength)
     655                 : {
     656               0 :     FlushText();
     657               0 :     return AddText(aData, aLength);
     658                 : }
     659                 : 
     660                 : NS_IMETHODIMP 
     661               0 : XULContentSinkImpl::HandleDoctypeDecl(const nsAString & aSubset, 
     662                 :                                       const nsAString & aName, 
     663                 :                                       const nsAString & aSystemId, 
     664                 :                                       const nsAString & aPublicId,
     665                 :                                       nsISupports* aCatalogData)
     666                 : {
     667               0 :     return NS_OK;
     668                 : }
     669                 : 
     670                 : NS_IMETHODIMP 
     671               0 : XULContentSinkImpl::HandleCharacterData(const PRUnichar *aData, 
     672                 :                                         PRUint32 aLength)
     673                 : {
     674               0 :   if (aData && mState != eInProlog && mState != eInEpilog) {
     675               0 :     return AddText(aData, aLength);
     676                 :   }
     677               0 :   return NS_OK;
     678                 : }
     679                 : 
     680                 : NS_IMETHODIMP 
     681               0 : XULContentSinkImpl::HandleProcessingInstruction(const PRUnichar *aTarget, 
     682                 :                                                 const PRUnichar *aData)
     683                 : {
     684               0 :     FlushText();
     685                 : 
     686               0 :     const nsDependentString target(aTarget);
     687               0 :     const nsDependentString data(aData);
     688                 : 
     689                 :     // Note: the created nsXULPrototypePI has mRefCnt == 1
     690               0 :     nsRefPtr<nsXULPrototypePI> pi = new nsXULPrototypePI();
     691               0 :     if (!pi)
     692               0 :         return NS_ERROR_OUT_OF_MEMORY;
     693                 : 
     694               0 :     pi->mTarget = target;
     695               0 :     pi->mData = data;
     696                 : 
     697               0 :     if (mState == eInProlog) {
     698                 :         // Note: passing in already addrefed pi
     699               0 :         return mPrototype->AddProcessingInstruction(pi);
     700                 :     }
     701                 : 
     702                 :     nsresult rv;
     703               0 :     nsPrototypeArray* children = nsnull;
     704               0 :     rv = mContextStack.GetTopChildren(&children);
     705               0 :     if (NS_FAILED(rv)) {
     706               0 :         return rv;
     707                 :     }
     708                 : 
     709               0 :     if (!children->AppendElement(pi)) {
     710               0 :         return NS_ERROR_OUT_OF_MEMORY;
     711                 :     }
     712                 : 
     713               0 :     return NS_OK;
     714                 : }
     715                 : 
     716                 : 
     717                 : NS_IMETHODIMP
     718               0 : XULContentSinkImpl::HandleXMLDeclaration(const PRUnichar *aVersion,
     719                 :                                          const PRUnichar *aEncoding,
     720                 :                                          PRInt32 aStandalone)
     721                 : {
     722               0 :   return NS_OK;
     723                 : }
     724                 : 
     725                 : 
     726                 : NS_IMETHODIMP
     727               0 : XULContentSinkImpl::ReportError(const PRUnichar* aErrorText, 
     728                 :                                 const PRUnichar* aSourceText,
     729                 :                                 nsIScriptError *aError,
     730                 :                                 bool *_retval)
     731                 : {
     732               0 :   NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
     733                 : 
     734                 :   // The expat driver should report the error.
     735               0 :   *_retval = true;
     736                 : 
     737               0 :   nsresult rv = NS_OK;
     738                 : 
     739                 :   // make sure to empty the context stack so that
     740                 :   // <parsererror> could become the root element.
     741               0 :   mContextStack.Clear();
     742                 : 
     743               0 :   mState = eInProlog;
     744                 : 
     745                 :   // Clear any buffered-up text we have.  It's enough to set the length to 0.
     746                 :   // The buffer itself is allocated when we're created and deleted in our
     747                 :   // destructor, so don't mess with it.
     748               0 :   mTextLength = 0;
     749                 : 
     750               0 :   nsCOMPtr<nsIXULDocument> doc = do_QueryReferent(mDocument);
     751               0 :   if (doc && !doc->OnDocumentParserError()) {
     752                 :     // The overlay was broken.  Don't add a messy element to the master doc.
     753               0 :     return NS_OK;
     754                 :   }
     755                 : 
     756               0 :   const PRUnichar* noAtts[] = { 0, 0 };
     757                 : 
     758               0 :   NS_NAMED_LITERAL_STRING(errorNs,
     759                 :                           "http://www.mozilla.org/newlayout/xml/parsererror.xml");
     760                 : 
     761               0 :   nsAutoString parsererror(errorNs);
     762               0 :   parsererror.Append((PRUnichar)0xFFFF);
     763               0 :   parsererror.AppendLiteral("parsererror");
     764                 :   
     765               0 :   rv = HandleStartElement(parsererror.get(), noAtts, 0, -1, 0);
     766               0 :   NS_ENSURE_SUCCESS(rv,rv);
     767                 : 
     768               0 :   rv = HandleCharacterData(aErrorText, nsCRT::strlen(aErrorText));
     769               0 :   NS_ENSURE_SUCCESS(rv,rv);  
     770                 :   
     771               0 :   nsAutoString sourcetext(errorNs);
     772               0 :   sourcetext.Append((PRUnichar)0xFFFF);
     773               0 :   sourcetext.AppendLiteral("sourcetext");
     774                 : 
     775               0 :   rv = HandleStartElement(sourcetext.get(), noAtts, 0, -1, 0);
     776               0 :   NS_ENSURE_SUCCESS(rv,rv);
     777                 :   
     778               0 :   rv = HandleCharacterData(aSourceText, nsCRT::strlen(aSourceText));
     779               0 :   NS_ENSURE_SUCCESS(rv,rv);
     780                 :   
     781               0 :   rv = HandleEndElement(sourcetext.get());
     782               0 :   NS_ENSURE_SUCCESS(rv,rv); 
     783                 :   
     784               0 :   rv = HandleEndElement(parsererror.get());
     785               0 :   NS_ENSURE_SUCCESS(rv,rv);
     786                 : 
     787               0 :   return rv;
     788                 : }
     789                 : 
     790                 : nsresult
     791               0 : XULContentSinkImpl::SetElementScriptType(nsXULPrototypeElement* element,
     792                 :                                          const PRUnichar** aAttributes, 
     793                 :                                          const PRUint32 aAttrLen)
     794                 : {
     795                 :     // First check if the attributes specify an explicit script type.
     796               0 :     nsresult rv = NS_OK;
     797                 :     PRUint32 i;
     798               0 :     bool found = false;
     799               0 :     for (i=0;i<aAttrLen;i++) {
     800               0 :         const nsDependentString key(aAttributes[i*2]);
     801               0 :         if (key.EqualsLiteral("script-type")) {
     802               0 :             const nsDependentString value(aAttributes[i*2+1]);
     803               0 :             if (!value.IsEmpty()) {
     804               0 :                 nsCOMPtr<nsIScriptRuntime> runtime;
     805               0 :                 rv = NS_GetScriptRuntime(value, getter_AddRefs(runtime));
     806               0 :                 if (NS_SUCCEEDED(rv))
     807               0 :                     element->mScriptTypeID = runtime->GetScriptTypeID();
     808                 :                 else {
     809                 :                     // probably just a bad language name (typo, etc)
     810               0 :                     NS_WARNING("Failed to load the node's script language!");
     811                 :                     // Leave the default language as unknown - we don't want js
     812                 :                     // trying to execute this stuff.
     813               0 :                     NS_ASSERTION(element->mScriptTypeID == nsIProgrammingLanguage::UNKNOWN,
     814                 :                                  "Default script type should be unknown");
     815                 :                 }
     816               0 :                 found = true;
     817                 :                 break;
     818                 :             }
     819                 :         }
     820                 :     }
     821                 :     // If not specified, look at the context stack and use the element
     822                 :     // there.
     823               0 :     if (!found) {
     824               0 :         if (mContextStack.Depth() == 0) {
     825                 :             // This is the root element - default to JS
     826               0 :             element->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
     827                 :         } else {
     828                 :             // Ask the top-node for its script type (which has already
     829                 :             // had this function called for it - so no need to recurse
     830                 :             // until we find it)
     831               0 :             PRUint32 scriptId = 0;
     832               0 :             rv = mContextStack.GetTopNodeScriptType(&scriptId);
     833               0 :             element->mScriptTypeID = scriptId;
     834                 :         }
     835                 :     }
     836               0 :     return rv;
     837                 : }
     838                 : 
     839                 : nsresult
     840               0 : XULContentSinkImpl::OpenRoot(const PRUnichar** aAttributes, 
     841                 :                              const PRUint32 aAttrLen, 
     842                 :                              nsINodeInfo *aNodeInfo)
     843                 : {
     844               0 :     NS_ASSERTION(mState == eInProlog, "how'd we get here?");
     845               0 :     if (mState != eInProlog)
     846               0 :         return NS_ERROR_UNEXPECTED;
     847                 : 
     848                 :     nsresult rv;
     849                 : 
     850               0 :     if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) || 
     851               0 :         aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XUL)) {
     852               0 :         PR_LOG(gLog, PR_LOG_ERROR,
     853                 :                ("xul: script tag not allowed as root content element"));
     854                 : 
     855               0 :         return NS_ERROR_UNEXPECTED;
     856                 :     }
     857                 : 
     858                 :     // Create the element
     859                 :     nsXULPrototypeElement* element;
     860               0 :     rv = CreateElement(aNodeInfo, &element);
     861                 : 
     862               0 :     if (NS_FAILED(rv)) {
     863                 : #ifdef PR_LOGGING
     864               0 :         if (PR_LOG_TEST(gLog, PR_LOG_ERROR)) {
     865               0 :             nsAutoString anodeC;
     866               0 :             aNodeInfo->GetName(anodeC);
     867               0 :             PR_LOG(gLog, PR_LOG_ERROR,
     868                 :                    ("xul: unable to create element '%s' at line %d",
     869                 :                     NS_ConvertUTF16toUTF8(anodeC).get(),
     870                 :                     -1)); // XXX pass in line number
     871                 :         }
     872                 : #endif
     873                 : 
     874               0 :         return rv;
     875                 :     }
     876                 : 
     877                 :     // Set the correct script-type for the element.
     878               0 :     rv = SetElementScriptType(element, aAttributes, aAttrLen);
     879               0 :     if (NS_FAILED(rv)) return rv;
     880                 : 
     881                 :     // Push the element onto the context stack, so that child
     882                 :     // containers will hook up to us as their parent.
     883               0 :     rv = mContextStack.Push(element, mState);
     884               0 :     if (NS_FAILED(rv)) {
     885               0 :         element->Release();
     886               0 :         return rv;
     887                 :     }
     888                 : 
     889                 :     // Add the attributes
     890               0 :     rv = AddAttributes(aAttributes, aAttrLen, element);
     891               0 :     if (NS_FAILED(rv)) return rv;
     892                 : 
     893               0 :     mState = eInDocumentElement;
     894               0 :     return NS_OK;
     895                 : }
     896                 : 
     897                 : nsresult
     898               0 : XULContentSinkImpl::OpenTag(const PRUnichar** aAttributes, 
     899                 :                             const PRUint32 aAttrLen,
     900                 :                             const PRUint32 aLineNumber,
     901                 :                             nsINodeInfo *aNodeInfo)
     902                 : {
     903                 :     nsresult rv;
     904                 : 
     905                 :     // Create the element
     906                 :     nsXULPrototypeElement* element;
     907               0 :     rv = CreateElement(aNodeInfo, &element);
     908                 : 
     909               0 :     if (NS_FAILED(rv)) {
     910                 : #ifdef PR_LOGGING
     911               0 :         if (PR_LOG_TEST(gLog, PR_LOG_ERROR)) {
     912               0 :             nsAutoString anodeC;
     913               0 :             aNodeInfo->GetName(anodeC);
     914               0 :             PR_LOG(gLog, PR_LOG_ERROR,
     915                 :                    ("xul: unable to create element '%s' at line %d",
     916                 :                     NS_ConvertUTF16toUTF8(anodeC).get(),
     917                 :                     aLineNumber));
     918                 :         }
     919                 : #endif
     920                 : 
     921               0 :         return rv;
     922                 :     }
     923                 : 
     924                 :     // Link this element to its parent.
     925               0 :     nsPrototypeArray* children = nsnull;
     926               0 :     rv = mContextStack.GetTopChildren(&children);
     927               0 :     if (NS_FAILED(rv)) {
     928               0 :         delete element;
     929               0 :         return rv;
     930                 :     }
     931                 : 
     932                 :     // Add the attributes
     933               0 :     rv = AddAttributes(aAttributes, aAttrLen, element);
     934               0 :     if (NS_FAILED(rv)) return rv;
     935                 : 
     936               0 :     children->AppendElement(element);
     937                 : 
     938               0 :     if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) || 
     939               0 :         aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XUL)) {
     940                 :         // Do scripty things now.  Set a script language for the element,
     941                 :         // even though it is ignored (the nsPrototypeScriptElement
     942                 :         // has its own script-type).
     943               0 :         element->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
     944               0 :         rv = OpenScript(aAttributes, aLineNumber);
     945               0 :         NS_ENSURE_SUCCESS(rv, rv);
     946                 : 
     947               0 :         NS_ASSERTION(mState == eInScript || mState == eInDocumentElement,
     948                 :                      "Unexpected state");
     949               0 :         if (mState == eInScript) {
     950                 :             // OpenScript has pushed the nsPrototypeScriptElement onto the 
     951                 :             // stack, so we're done.
     952               0 :             return NS_OK;
     953                 :         }
     954                 :     }
     955                 : 
     956                 :     // Set the correct script-type for the element.
     957               0 :     rv = SetElementScriptType(element, aAttributes, aAttrLen);
     958               0 :     if (NS_FAILED(rv)) return rv;
     959                 : 
     960                 :     // Push the element onto the context stack, so that child
     961                 :     // containers will hook up to us as their parent.
     962               0 :     rv = mContextStack.Push(element, mState);
     963               0 :     if (NS_FAILED(rv)) return rv;
     964                 : 
     965               0 :     mState = eInDocumentElement;
     966               0 :     return NS_OK;
     967                 : }
     968                 : 
     969                 : nsresult
     970               0 : XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
     971                 :                                const PRUint32 aLineNumber)
     972                 : {
     973                 :   PRUint32 langID;
     974               0 :   nsresult rv = mContextStack.GetTopNodeScriptType(&langID);
     975               0 :   if (NS_FAILED(rv)) return rv;
     976               0 :   PRUint32 version = 0;
     977                 : 
     978                 :   // Look for SRC attribute and look for a LANGUAGE attribute
     979               0 :   nsAutoString src;
     980               0 :   while (*aAttributes) {
     981               0 :       const nsDependentString key(aAttributes[0]);
     982               0 :       if (key.EqualsLiteral("src")) {
     983               0 :           src.Assign(aAttributes[1]);
     984                 :       }
     985               0 :       else if (key.EqualsLiteral("type")) {
     986               0 :           nsDependentString str(aAttributes[1]);
     987               0 :           nsContentTypeParser parser(str);
     988               0 :           nsAutoString mimeType;
     989               0 :           rv = parser.GetType(mimeType);
     990               0 :           if (NS_FAILED(rv)) {
     991               0 :               if (rv == NS_ERROR_INVALID_ARG) {
     992                 :                   // Might as well bail out now instead of setting langID to
     993                 :                   // nsIProgrammingLanguage::UNKNOWN and bailing out later.
     994               0 :                   return NS_OK;
     995                 :               }
     996                 :               // We do want the warning here
     997               0 :               NS_ENSURE_SUCCESS(rv, rv);
     998                 :           }
     999                 : 
    1000                 :           // Javascript keeps the fast path, optimized for most-likely type
    1001                 :           // Table ordered from most to least likely JS MIME types. For .xul
    1002                 :           // files that we host, the likeliest type is application/x-javascript.
    1003                 :           // See bug 62485, feel free to add <script type="..."> survey data to it,
    1004                 :           // or to a new bug once 62485 is closed.
    1005                 :           static const char *jsTypes[] = {
    1006                 :               "application/x-javascript",
    1007                 :               "text/javascript",
    1008                 :               "text/ecmascript",
    1009                 :               "application/javascript",
    1010                 :               "application/ecmascript",
    1011                 :               nsnull
    1012                 :           };
    1013                 : 
    1014               0 :           bool isJavaScript = false;
    1015               0 :           for (PRInt32 i = 0; jsTypes[i]; i++) {
    1016               0 :               if (mimeType.LowerCaseEqualsASCII(jsTypes[i])) {
    1017               0 :                   isJavaScript = true;
    1018               0 :                   break;
    1019                 :               }
    1020                 :           }
    1021                 : 
    1022               0 :           if (isJavaScript) {
    1023               0 :               langID = nsIProgrammingLanguage::JAVASCRIPT;
    1024               0 :               version = JSVERSION_LATEST;
    1025                 :           } else {
    1026                 :               // Use the script object factory to locate the language.
    1027               0 :               nsCOMPtr<nsIScriptRuntime> runtime;
    1028               0 :               rv = NS_GetScriptRuntime(mimeType, getter_AddRefs(runtime));
    1029               0 :               if (NS_FAILED(rv) || runtime == nsnull) {
    1030                 :                   // Failed to get the explicitly specified language
    1031               0 :                   NS_WARNING("Failed to find a scripting language");
    1032               0 :                   langID = nsIProgrammingLanguage::UNKNOWN;
    1033                 :               } else
    1034               0 :                   langID = runtime->GetScriptTypeID();
    1035                 :           }
    1036                 : 
    1037               0 :           if (langID != nsIProgrammingLanguage::UNKNOWN) {
    1038                 :             // Get the version string, and ensure the language supports it.
    1039               0 :             nsAutoString versionName;
    1040               0 :             rv = parser.GetParameter("version", versionName);
    1041               0 :             if (NS_FAILED(rv)) {
    1042               0 :               if (rv != NS_ERROR_INVALID_ARG)
    1043               0 :                 return rv;
    1044                 :               // no version specified - version remains the default.
    1045                 :             } else {
    1046               0 :               nsCOMPtr<nsIScriptRuntime> runtime;
    1047               0 :               rv = NS_GetScriptRuntimeByID(langID, getter_AddRefs(runtime));
    1048               0 :               if (NS_FAILED(rv))
    1049               0 :                 return rv;
    1050               0 :               rv = runtime->ParseVersion(versionName, &version);
    1051               0 :               if (NS_FAILED(rv)) {
    1052               0 :                 NS_WARNING("This script language version is not supported - ignored");
    1053               0 :                 langID = nsIProgrammingLanguage::UNKNOWN;
    1054                 :               }
    1055                 :             }
    1056                 :           }
    1057                 :           // Some js specifics yet to be abstracted.
    1058               0 :           if (langID == nsIProgrammingLanguage::JAVASCRIPT) {
    1059                 :               // By default scripts in XUL documents have E4X turned on. We use
    1060                 :               // our implementation knowledge to reuse JSVERSION_HAS_XML as a
    1061                 :               // safe version flag. This is still OK if version is
    1062                 :               // JSVERSION_UNKNOWN (-1),
    1063               0 :               version = js::VersionSetXML(JSVersion(version), true);
    1064                 : 
    1065               0 :               nsAutoString value;
    1066               0 :               rv = parser.GetParameter("e4x", value);
    1067               0 :               if (NS_FAILED(rv)) {
    1068               0 :                   if (rv != NS_ERROR_INVALID_ARG)
    1069               0 :                       return rv;
    1070                 :               } else {
    1071               0 :                   if (value.Length() == 1 && value[0] == '0')
    1072               0 :                     version = js::VersionSetXML(JSVersion(version), false);
    1073                 :               }
    1074                 :           }
    1075                 :       }
    1076               0 :       else if (key.EqualsLiteral("language")) {
    1077                 :           // Language is deprecated, and the impl in nsScriptLoader ignores the
    1078                 :           // various version strings anyway.  So we make no attempt to support
    1079                 :           // languages other than JS for language=
    1080               0 :           nsAutoString lang(aAttributes[1]);
    1081               0 :           if (nsContentUtils::IsJavaScriptLanguage(lang, &version)) {
    1082               0 :               langID = nsIProgrammingLanguage::JAVASCRIPT;
    1083                 : 
    1084                 :               // Even when JS version < 1.6 is specified, E4X is
    1085                 :               // turned on in XUL.
    1086               0 :               version = js::VersionSetXML(JSVersion(version), true);
    1087                 :           }
    1088                 :       }
    1089               0 :       aAttributes += 2;
    1090                 :   }
    1091                 :   // Not all script languages have a "sandbox" concept.  At time of
    1092                 :   // writing, Python is the only other language, and it does not.
    1093                 :   // For such languages, neither any inline script nor remote script are
    1094                 :   // safe to execute from untrusted sources.
    1095                 :   // So for such languages, we only allow script when the document
    1096                 :   // itself is from chrome.  We then don't bother to check the
    1097                 :   // "src=" tag - we trust chrome to do the right thing.
    1098                 :   // (See also similar code in nsScriptLoader.cpp)
    1099               0 :   nsCOMPtr<nsIDocument> doc(do_QueryReferent(mDocument));
    1100               0 :   if (langID != nsIProgrammingLanguage::UNKNOWN && 
    1101                 :       langID != nsIProgrammingLanguage::JAVASCRIPT &&
    1102               0 :       doc && !nsContentUtils::IsChromeDoc(doc)) {
    1103               0 :       langID = nsIProgrammingLanguage::UNKNOWN;
    1104               0 :       NS_WARNING("Non JS language called from non chrome - ignored");
    1105                 :   }
    1106                 :   // Don't process scripts that aren't known
    1107               0 :   if (langID != nsIProgrammingLanguage::UNKNOWN) {
    1108               0 :       nsIScriptGlobalObject* globalObject = nsnull; // borrowed reference
    1109               0 :       if (doc)
    1110               0 :           globalObject = doc->GetScriptGlobalObject();
    1111                 :       nsRefPtr<nsXULPrototypeScript> script =
    1112               0 :           new nsXULPrototypeScript(langID, aLineNumber, version);
    1113               0 :       if (! script)
    1114               0 :           return NS_ERROR_OUT_OF_MEMORY;
    1115                 : 
    1116                 :       // If there is a SRC attribute...
    1117               0 :       if (! src.IsEmpty()) {
    1118                 :           // Use the SRC attribute value to load the URL
    1119               0 :           rv = NS_NewURI(getter_AddRefs(script->mSrcURI), src, nsnull, mDocumentURL);
    1120                 : 
    1121                 :           // Check if this document is allowed to load a script from this source
    1122                 :           // NOTE: if we ever allow scripts added via the DOM to run, we need to
    1123                 :           // add a CheckLoadURI call for that as well.
    1124               0 :           if (NS_SUCCEEDED(rv)) {
    1125               0 :               if (!mSecMan)
    1126               0 :                   mSecMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
    1127               0 :               if (NS_SUCCEEDED(rv)) {
    1128               0 :                   nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument, &rv);
    1129                 : 
    1130               0 :                   if (NS_SUCCEEDED(rv)) {
    1131               0 :                       rv = mSecMan->
    1132               0 :                           CheckLoadURIWithPrincipal(doc->NodePrincipal(),
    1133               0 :                                                     script->mSrcURI,
    1134               0 :                                                     nsIScriptSecurityManager::ALLOW_CHROME);
    1135                 :                   }
    1136                 :               }
    1137                 :           }
    1138                 : 
    1139               0 :           if (NS_FAILED(rv)) {
    1140               0 :               return rv;
    1141                 :           }
    1142                 : 
    1143                 :           // Attempt to deserialize an out-of-line script from the FastLoad
    1144                 :           // file right away.  Otherwise we'll end up reloading the script and
    1145                 :           // corrupting the FastLoad file trying to serialize it, in the case
    1146                 :           // where it's already there.
    1147               0 :           if (globalObject)
    1148               0 :                 script->DeserializeOutOfLine(nsnull, globalObject);
    1149                 :       }
    1150                 : 
    1151               0 :       nsPrototypeArray* children = nsnull;
    1152               0 :       rv = mContextStack.GetTopChildren(&children);
    1153               0 :       if (NS_FAILED(rv)) {
    1154               0 :           return rv;
    1155                 :       }
    1156                 : 
    1157               0 :       children->AppendElement(script);
    1158                 : 
    1159               0 :       mConstrainSize = false;
    1160                 : 
    1161               0 :       mContextStack.Push(script, mState);
    1162               0 :       mState = eInScript;
    1163                 :   }
    1164                 : 
    1165               0 :   return NS_OK;
    1166                 : }
    1167                 : 
    1168                 : nsresult
    1169               0 : XULContentSinkImpl::AddAttributes(const PRUnichar** aAttributes, 
    1170                 :                                   const PRUint32 aAttrLen, 
    1171                 :                                   nsXULPrototypeElement* aElement)
    1172                 : {
    1173                 :   // Add tag attributes to the element
    1174                 :   nsresult rv;
    1175                 : 
    1176                 :   // Create storage for the attributes
    1177               0 :   nsXULPrototypeAttribute* attrs = nsnull;
    1178               0 :   if (aAttrLen > 0) {
    1179               0 :     attrs = new nsXULPrototypeAttribute[aAttrLen];
    1180               0 :     if (! attrs)
    1181               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1182                 :   }
    1183                 : 
    1184               0 :   aElement->mAttributes    = attrs;
    1185               0 :   aElement->mNumAttributes = aAttrLen;
    1186                 : 
    1187                 :   // Copy the attributes into the prototype
    1188                 :   PRUint32 i;
    1189               0 :   for (i = 0; i < aAttrLen; ++i) {
    1190               0 :       rv = NormalizeAttributeString(aAttributes[i * 2], attrs[i].mName);
    1191               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1192                 : 
    1193               0 :       rv = aElement->SetAttrAt(i, nsDependentString(aAttributes[i * 2 + 1]),
    1194               0 :                                mDocumentURL);
    1195               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1196                 : 
    1197                 : #ifdef PR_LOGGING
    1198               0 :       if (PR_LOG_TEST(gLog, PR_LOG_DEBUG)) {
    1199               0 :           nsAutoString extraWhiteSpace;
    1200               0 :           PRInt32 cnt = mContextStack.Depth();
    1201               0 :           while (--cnt >= 0)
    1202               0 :               extraWhiteSpace.AppendLiteral("  ");
    1203               0 :           nsAutoString qnameC,valueC;
    1204               0 :           qnameC.Assign(aAttributes[0]);
    1205               0 :           valueC.Assign(aAttributes[1]);
    1206               0 :           PR_LOG(gLog, PR_LOG_DEBUG,
    1207                 :                  ("xul: %.5d. %s    %s=%s",
    1208                 :                   -1, // XXX pass in line number
    1209                 :                   NS_ConvertUTF16toUTF8(extraWhiteSpace).get(),
    1210                 :                   NS_ConvertUTF16toUTF8(qnameC).get(),
    1211                 :                   NS_ConvertUTF16toUTF8(valueC).get()));
    1212                 :       }
    1213                 : #endif
    1214                 :   }
    1215                 : 
    1216               0 :   return NS_OK;
    1217                 : }
    1218                 : 
    1219                 : nsresult
    1220               0 : XULContentSinkImpl::AddText(const PRUnichar* aText, 
    1221                 :                             PRInt32 aLength)
    1222                 : {
    1223                 :   // Create buffer when we first need it
    1224               0 :   if (0 == mTextSize) {
    1225               0 :       mText = (PRUnichar *) PR_MALLOC(sizeof(PRUnichar) * 4096);
    1226               0 :       if (nsnull == mText) {
    1227               0 :           return NS_ERROR_OUT_OF_MEMORY;
    1228                 :       }
    1229               0 :       mTextSize = 4096;
    1230                 :   }
    1231                 : 
    1232                 :   // Copy data from string into our buffer; flush buffer when it fills up
    1233               0 :   PRInt32 offset = 0;
    1234               0 :   while (0 != aLength) {
    1235               0 :     PRInt32 amount = mTextSize - mTextLength;
    1236               0 :     if (amount > aLength) {
    1237               0 :         amount = aLength;
    1238                 :     }
    1239               0 :     if (0 == amount) {
    1240               0 :       if (mConstrainSize) {
    1241               0 :         nsresult rv = FlushText();
    1242               0 :         if (NS_OK != rv) {
    1243               0 :             return rv;
    1244                 :         }
    1245                 :       }
    1246                 :       else {
    1247               0 :         mTextSize += aLength;
    1248               0 :         mText = (PRUnichar *) PR_REALLOC(mText, sizeof(PRUnichar) * mTextSize);
    1249               0 :         if (nsnull == mText) {
    1250               0 :             return NS_ERROR_OUT_OF_MEMORY;
    1251                 :         }
    1252                 :       }
    1253                 :     }
    1254               0 :     memcpy(&mText[mTextLength],aText + offset, sizeof(PRUnichar) * amount);
    1255                 :     
    1256               0 :     mTextLength += amount;
    1257               0 :     offset += amount;
    1258               0 :     aLength -= amount;
    1259                 :   }
    1260                 : 
    1261               0 :   return NS_OK;
    1262                 : }

Generated by: LCOV version 1.7