LCOV - code coverage report
Current view: directory - content/base/src - nsGenericElement.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 2809 1116 39.7 %
Date: 2012-06-02 Functions: 342 149 43.6 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=79: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Ms2ger <ms2ger@gmail.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : /*
      41                 :  * Base class for all element classes; this provides an implementation
      42                 :  * of DOM Core's nsIDOMElement, implements nsIContent, provides
      43                 :  * utility methods for subclasses, and so forth.
      44                 :  */
      45                 : 
      46                 : #include "mozilla/Util.h"
      47                 : 
      48                 : #include "nsGenericElement.h"
      49                 : 
      50                 : #include "nsDOMAttribute.h"
      51                 : #include "nsDOMAttributeMap.h"
      52                 : #include "nsIAtom.h"
      53                 : #include "nsINodeInfo.h"
      54                 : #include "nsIDocument.h"
      55                 : #include "nsIDOMNodeList.h"
      56                 : #include "nsIDOMDocument.h"
      57                 : #include "nsIContentIterator.h"
      58                 : #include "nsEventListenerManager.h"
      59                 : #include "nsFocusManager.h"
      60                 : #include "nsILinkHandler.h"
      61                 : #include "nsIScriptGlobalObject.h"
      62                 : #include "nsIURL.h"
      63                 : #include "nsNetUtil.h"
      64                 : #include "nsIFrame.h"
      65                 : #include "nsIAnonymousContentCreator.h"
      66                 : #include "nsIPresShell.h"
      67                 : #include "nsPresContext.h"
      68                 : #include "nsStyleConsts.h"
      69                 : #include "nsString.h"
      70                 : #include "nsUnicharUtils.h"
      71                 : #include "nsEventStateManager.h"
      72                 : #include "nsIDOMEvent.h"
      73                 : #include "nsIPrivateDOMEvent.h"
      74                 : #include "nsDOMCID.h"
      75                 : #include "nsIServiceManager.h"
      76                 : #include "nsIDOMCSSStyleDeclaration.h"
      77                 : #include "nsDOMCSSAttrDeclaration.h"
      78                 : #include "nsINameSpaceManager.h"
      79                 : #include "nsContentList.h"
      80                 : #include "nsDOMTokenList.h"
      81                 : #include "nsXBLPrototypeBinding.h"
      82                 : #include "nsDOMError.h"
      83                 : #include "nsDOMString.h"
      84                 : #include "nsIScriptSecurityManager.h"
      85                 : #include "nsIDOMMutationEvent.h"
      86                 : #include "nsMutationEvent.h"
      87                 : #include "nsNodeUtils.h"
      88                 : #include "nsDocument.h"
      89                 : #include "nsAttrValueOrString.h"
      90                 : #ifdef MOZ_XUL
      91                 : #include "nsXULElement.h"
      92                 : #endif /* MOZ_XUL */
      93                 : #include "nsFrameManager.h"
      94                 : #include "nsFrameSelection.h"
      95                 : #ifdef DEBUG
      96                 : #include "nsRange.h"
      97                 : #endif
      98                 : 
      99                 : #include "nsBindingManager.h"
     100                 : #include "nsXBLBinding.h"
     101                 : #include "nsIXBLService.h"
     102                 : #include "nsPIDOMWindow.h"
     103                 : #include "nsPIBoxObject.h"
     104                 : #include "nsIDOMNSElement.h"
     105                 : #include "nsClientRect.h"
     106                 : #include "nsSVGUtils.h"
     107                 : #include "nsLayoutUtils.h"
     108                 : #include "nsGkAtoms.h"
     109                 : #include "nsContentUtils.h"
     110                 : #include "nsIJSContextStack.h"
     111                 : 
     112                 : #include "nsIServiceManager.h"
     113                 : #include "nsIDOMEventListener.h"
     114                 : #include "nsIWebNavigation.h"
     115                 : #include "nsIBaseWindow.h"
     116                 : #include "nsIWidget.h"
     117                 : 
     118                 : #include "jsapi.h"
     119                 : 
     120                 : #include "nsNodeInfoManager.h"
     121                 : #include "nsICategoryManager.h"
     122                 : #include "nsIDOMDocumentType.h"
     123                 : #include "nsIDOMUserDataHandler.h"
     124                 : #include "nsGenericHTMLElement.h"
     125                 : #include "nsIEditor.h"
     126                 : #include "nsIEditorIMESupport.h"
     127                 : #include "nsIEditorDocShell.h"
     128                 : #include "nsEventDispatcher.h"
     129                 : #include "nsContentCreatorFunctions.h"
     130                 : #include "nsIControllers.h"
     131                 : #include "nsLayoutUtils.h"
     132                 : #include "nsIView.h"
     133                 : #include "nsIViewManager.h"
     134                 : #include "nsIScrollableFrame.h"
     135                 : #include "nsXBLInsertionPoint.h"
     136                 : #include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
     137                 : #include "nsCSSRuleProcessor.h"
     138                 : #include "nsRuleProcessorData.h"
     139                 : #include "nsAsyncDOMEvent.h"
     140                 : #include "nsTextNode.h"
     141                 : #include "dombindings.h"
     142                 : 
     143                 : #ifdef MOZ_XUL
     144                 : #include "nsIXULDocument.h"
     145                 : #endif /* MOZ_XUL */
     146                 : 
     147                 : #include "nsCycleCollectionParticipant.h"
     148                 : #include "nsCCUncollectableMarker.h"
     149                 : 
     150                 : #include "mozAutoDocUpdate.h"
     151                 : 
     152                 : #include "nsCSSParser.h"
     153                 : #include "prprf.h"
     154                 : 
     155                 : #include "nsSVGFeatures.h"
     156                 : #include "nsWrapperCacheInlines.h"
     157                 : #include "nsCycleCollector.h"
     158                 : #include "xpcpublic.h"
     159                 : #include "xpcprivate.h"
     160                 : #include "nsLayoutStatics.h"
     161                 : #include "mozilla/Telemetry.h"
     162                 : 
     163                 : #include "mozilla/CORSMode.h"
     164                 : 
     165                 : using namespace mozilla;
     166                 : using namespace mozilla::dom;
     167                 : 
     168                 : NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
     169                 : 
     170                 : PRInt32 nsIContent::sTabFocusModel = eTabFocus_any;
     171                 : bool nsIContent::sTabFocusModelAppliesToXUL = false;
     172                 : PRUint32 nsMutationGuard::sMutationCount = 0;
     173                 : 
     174                 : nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult);
     175                 : 
     176                 : void
     177          125499 : nsWrapperCache::RemoveExpandoObject()
     178                 : {
     179          125499 :   JSObject *expando = GetExpandoObjectPreserveColor();
     180          125499 :   if (expando) {
     181               0 :     JSCompartment *compartment = js::GetObjectCompartment(expando);
     182                 :     xpc::CompartmentPrivate *priv =
     183               0 :       static_cast<xpc::CompartmentPrivate *>(JS_GetCompartmentPrivate(compartment));
     184               0 :     priv->RemoveDOMExpandoObject(expando);
     185                 :   }
     186          125499 : }
     187                 : 
     188                 : //----------------------------------------------------------------------
     189                 : 
     190           10489 : nsINode::nsSlots::~nsSlots()
     191                 : {
     192            4609 :   if (mChildNodes) {
     193               0 :     mChildNodes->DropReference();
     194               0 :     NS_RELEASE(mChildNodes);
     195                 :   }
     196                 : 
     197            4609 :   if (mWeakReference) {
     198               0 :     mWeakReference->NoticeNodeDestruction();
     199                 :   }
     200           11760 : }
     201                 : 
     202                 : void
     203            4988 : nsINode::nsSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
     204                 : {
     205            4988 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildNodes");
     206            4988 :   cb.NoteXPCOMChild(mChildNodes);
     207            4988 : }
     208                 : 
     209                 : void
     210            4609 : nsINode::nsSlots::Unlink()
     211                 : {
     212            4609 :   if (mChildNodes) {
     213            1527 :     mChildNodes->DropReference();
     214            1527 :     NS_RELEASE(mChildNodes);
     215                 :   }
     216            4609 : }
     217                 : 
     218                 : //----------------------------------------------------------------------
     219                 : 
     220          230562 : nsINode::~nsINode()
     221                 : {
     222          115281 :   NS_ASSERTION(!HasSlots(), "nsNodeUtils::LastRelease was not called?");
     223          230562 : }
     224                 : 
     225                 : void*
     226               0 : nsINode::GetProperty(PRUint16 aCategory, nsIAtom *aPropertyName,
     227                 :                      nsresult *aStatus) const
     228                 : {
     229                 :   return OwnerDoc()->PropertyTable(aCategory)->GetProperty(this, aPropertyName,
     230               0 :                                                            aStatus);
     231                 : }
     232                 : 
     233                 : nsresult
     234               0 : nsINode::SetProperty(PRUint16 aCategory, nsIAtom *aPropertyName, void *aValue,
     235                 :                      NSPropertyDtorFunc aDtor, bool aTransfer,
     236                 :                      void **aOldValue)
     237                 : {
     238                 :   nsresult rv = OwnerDoc()->PropertyTable(aCategory)->SetProperty(this,
     239                 :                                                                   aPropertyName,
     240                 :                                                                   aValue, aDtor,
     241                 :                                                                   nsnull,
     242                 :                                                                   aTransfer,
     243               0 :                                                                   aOldValue);
     244               0 :   if (NS_SUCCEEDED(rv)) {
     245               0 :     SetFlags(NODE_HAS_PROPERTIES);
     246                 :   }
     247                 : 
     248               0 :   return rv;
     249                 : }
     250                 : 
     251                 : void
     252               0 : nsINode::DeleteProperty(PRUint16 aCategory, nsIAtom *aPropertyName)
     253                 : {
     254               0 :   OwnerDoc()->PropertyTable(aCategory)->DeleteProperty(this, aPropertyName);
     255               0 : }
     256                 : 
     257                 : void*
     258               0 : nsINode::UnsetProperty(PRUint16 aCategory, nsIAtom *aPropertyName,
     259                 :                        nsresult *aStatus)
     260                 : {
     261                 :   return OwnerDoc()->PropertyTable(aCategory)->UnsetProperty(this,
     262                 :                                                              aPropertyName,
     263               0 :                                                              aStatus);
     264                 : }
     265                 : 
     266                 : nsINode::nsSlots*
     267            1273 : nsINode::CreateSlots()
     268                 : {
     269            1273 :   return new nsSlots();
     270                 : }
     271                 : 
     272                 : bool
     273           49496 : nsINode::IsEditableInternal() const
     274                 : {
     275           49496 :   if (HasFlag(NODE_IS_EDITABLE)) {
     276                 :     // The node is in an editable contentEditable subtree.
     277               5 :     return true;
     278                 :   }
     279                 : 
     280           49491 :   nsIDocument *doc = GetCurrentDoc();
     281                 : 
     282                 :   // Check if the node is in a document and the document is in designMode.
     283           49491 :   return doc && doc->HasFlag(NODE_IS_EDITABLE);
     284                 : }
     285                 : 
     286               0 : static nsIContent* GetEditorRootContent(nsIEditor* aEditor)
     287                 : {
     288               0 :   nsCOMPtr<nsIDOMElement> rootElement;
     289               0 :   aEditor->GetRootElement(getter_AddRefs(rootElement));
     290               0 :   nsCOMPtr<nsIContent> rootContent(do_QueryInterface(rootElement));
     291               0 :   return rootContent;
     292                 : }
     293                 : 
     294                 : nsIContent*
     295               0 : nsINode::GetTextEditorRootContent(nsIEditor** aEditor)
     296                 : {
     297               0 :   if (aEditor)
     298               0 :     *aEditor = nsnull;
     299               0 :   for (nsINode* node = this; node; node = node->GetNodeParent()) {
     300               0 :     if (!node->IsElement() ||
     301               0 :         !node->AsElement()->IsHTML())
     302               0 :       continue;
     303                 : 
     304               0 :     nsCOMPtr<nsIEditor> editor;
     305                 :     static_cast<nsGenericHTMLElement*>(node)->
     306               0 :         GetEditorInternal(getter_AddRefs(editor));
     307               0 :     if (!editor)
     308               0 :       continue;
     309                 : 
     310               0 :     nsIContent* rootContent = GetEditorRootContent(editor);
     311               0 :     if (aEditor)
     312               0 :       editor.swap(*aEditor);
     313               0 :     return rootContent;
     314                 :   }
     315               0 :   return nsnull;
     316                 : }
     317                 : 
     318               0 : static nsIEditor* GetHTMLEditor(nsPresContext* aPresContext)
     319                 : {
     320               0 :   nsCOMPtr<nsISupports> container = aPresContext->GetContainer();
     321               0 :   nsCOMPtr<nsIEditorDocShell> editorDocShell(do_QueryInterface(container));
     322                 :   bool isEditable;
     323               0 :   if (!editorDocShell ||
     324               0 :       NS_FAILED(editorDocShell->GetEditable(&isEditable)) || !isEditable)
     325               0 :     return nsnull;
     326                 : 
     327               0 :   nsCOMPtr<nsIEditor> editor;
     328               0 :   editorDocShell->GetEditor(getter_AddRefs(editor));
     329               0 :   return editor;
     330                 : }
     331                 : 
     332               0 : static nsIContent* GetRootForContentSubtree(nsIContent* aContent)
     333                 : {
     334               0 :   NS_ENSURE_TRUE(aContent, nsnull);
     335               0 :   nsIContent* stop = aContent->GetBindingParent();
     336               0 :   while (aContent) {
     337               0 :     nsIContent* parent = aContent->GetParent();
     338               0 :     if (parent == stop) {
     339               0 :       break;
     340                 :     }
     341               0 :     aContent = parent;
     342                 :   }
     343               0 :   return aContent;
     344                 : }
     345                 : 
     346                 : nsIContent*
     347               0 : nsINode::GetSelectionRootContent(nsIPresShell* aPresShell)
     348                 : {
     349               0 :   NS_ENSURE_TRUE(aPresShell, nsnull);
     350                 : 
     351               0 :   if (IsNodeOfType(eDOCUMENT))
     352               0 :     return static_cast<nsIDocument*>(this)->GetRootElement();
     353               0 :   if (!IsNodeOfType(eCONTENT))
     354               0 :     return nsnull;
     355                 : 
     356               0 :   if (GetCurrentDoc() != aPresShell->GetDocument()) {
     357               0 :     return nsnull;
     358                 :   }
     359                 : 
     360               0 :   if (static_cast<nsIContent*>(this)->HasIndependentSelection()) {
     361                 :     // This node should be a descendant of input/textarea editor.
     362               0 :     nsIContent* content = GetTextEditorRootContent();
     363               0 :     if (content)
     364               0 :       return content;
     365                 :   }
     366                 : 
     367               0 :   nsPresContext* presContext = aPresShell->GetPresContext();
     368               0 :   if (presContext) {
     369               0 :     nsIEditor* editor = GetHTMLEditor(presContext);
     370               0 :     if (editor) {
     371                 :       // This node is in HTML editor.
     372               0 :       nsIDocument* doc = GetCurrentDoc();
     373               0 :       if (!doc || doc->HasFlag(NODE_IS_EDITABLE) ||
     374               0 :           !HasFlag(NODE_IS_EDITABLE)) {
     375               0 :         nsIContent* editorRoot = GetEditorRootContent(editor);
     376               0 :         NS_ENSURE_TRUE(editorRoot, nsnull);
     377               0 :         return nsContentUtils::IsInSameAnonymousTree(this, editorRoot) ?
     378                 :                  editorRoot :
     379               0 :                  GetRootForContentSubtree(static_cast<nsIContent*>(this));
     380                 :       }
     381                 :       // If the document isn't editable but this is editable, this is in
     382                 :       // contenteditable.  Use the editing host element for selection root.
     383               0 :       return static_cast<nsIContent*>(this)->GetEditingHost();
     384                 :     }
     385                 :   }
     386                 : 
     387               0 :   nsRefPtr<nsFrameSelection> fs = aPresShell->FrameSelection();
     388               0 :   nsIContent* content = fs->GetLimiter();
     389               0 :   if (!content) {
     390               0 :     content = fs->GetAncestorLimiter();
     391               0 :     if (!content) {
     392               0 :       nsIDocument* doc = aPresShell->GetDocument();
     393               0 :       NS_ENSURE_TRUE(doc, nsnull);
     394               0 :       content = doc->GetRootElement();
     395               0 :       if (!content)
     396               0 :         return nsnull;
     397                 :     }
     398                 :   }
     399                 : 
     400                 :   // This node might be in another subtree, if so, we should find this subtree's
     401                 :   // root.  Otherwise, we can return the content simply.
     402               0 :   NS_ENSURE_TRUE(content, nsnull);
     403               0 :   return nsContentUtils::IsInSameAnonymousTree(this, content) ?
     404               0 :            content : GetRootForContentSubtree(static_cast<nsIContent*>(this));
     405                 : }
     406                 : 
     407                 : nsINodeList*
     408            9178 : nsINode::GetChildNodesList()
     409                 : {
     410            9178 :   nsSlots *slots = GetSlots();
     411            9178 :   if (!slots) {
     412               0 :     return nsnull;
     413                 :   }
     414                 : 
     415            9178 :   if (!slots->mChildNodes) {
     416            1527 :     slots->mChildNodes = new nsChildContentList(this);
     417            1527 :     if (slots->mChildNodes) {
     418            1527 :       NS_ADDREF(slots->mChildNodes);
     419                 :     }
     420                 :   }
     421                 : 
     422            9178 :   return slots->mChildNodes;
     423                 : }
     424                 : 
     425                 : #ifdef DEBUG
     426                 : void
     427           57871 : nsINode::CheckNotNativeAnonymous() const
     428                 : {
     429           57871 :   if (!IsNodeOfType(eCONTENT))
     430            2920 :     return;
     431           54951 :   nsIContent* content = static_cast<const nsIContent *>(this)->GetBindingParent();
     432          109902 :   while (content) {
     433               0 :     if (content->IsRootOfNativeAnonymousSubtree()) {
     434               0 :       NS_ERROR("Element not marked to be in native anonymous subtree!");
     435               0 :       break;
     436                 :     }
     437               0 :     content = content->GetBindingParent();
     438                 :   }
     439                 : }
     440                 : #endif
     441                 : 
     442                 : nsresult
     443             376 : nsINode::GetParentNode(nsIDOMNode** aParentNode)
     444                 : {
     445             376 :   *aParentNode = nsnull;
     446                 : 
     447             376 :   nsINode *parent = GetNodeParent();
     448                 : 
     449             376 :   return parent ? CallQueryInterface(parent, aParentNode) : NS_OK;
     450                 : }
     451                 : 
     452                 : nsresult
     453               0 : nsINode::GetParentElement(nsIDOMElement** aParentElement)
     454                 : {
     455               0 :   *aParentElement = nsnull;
     456               0 :   nsINode* parent = GetElementParent();
     457               0 :   return parent ? CallQueryInterface(parent, aParentElement) : NS_OK;
     458                 : }
     459                 : 
     460                 : nsresult
     461            4589 : nsINode::GetChildNodes(nsIDOMNodeList** aChildNodes)
     462                 : {
     463            4589 :   *aChildNodes = GetChildNodesList();
     464            4589 :   if (!*aChildNodes) {
     465               0 :     return NS_ERROR_OUT_OF_MEMORY;
     466                 :   }
     467                 : 
     468            4589 :   NS_ADDREF(*aChildNodes);
     469                 : 
     470            4589 :   return NS_OK;
     471                 : }
     472                 : 
     473                 : nsresult
     474             266 : nsINode::GetFirstChild(nsIDOMNode** aNode)
     475                 : {
     476             266 :   nsIContent* child = GetFirstChild();
     477             266 :   if (child) {
     478             258 :     return CallQueryInterface(child, aNode);
     479                 :   }
     480                 : 
     481               8 :   *aNode = nsnull;
     482                 : 
     483               8 :   return NS_OK;
     484                 : }
     485                 : 
     486                 : nsresult
     487              72 : nsINode::GetLastChild(nsIDOMNode** aNode)
     488                 : {
     489              72 :   nsIContent* child = GetLastChild();
     490              72 :   if (child) {
     491              10 :     return CallQueryInterface(child, aNode);
     492                 :   }
     493                 : 
     494              62 :   *aNode = nsnull;
     495                 : 
     496              62 :   return NS_OK;
     497                 : }
     498                 : 
     499                 : nsresult
     500               0 : nsINode::GetPreviousSibling(nsIDOMNode** aPrevSibling)
     501                 : {
     502               0 :   *aPrevSibling = nsnull;
     503                 : 
     504               0 :   nsIContent *sibling = GetPreviousSibling();
     505                 : 
     506               0 :   return sibling ? CallQueryInterface(sibling, aPrevSibling) : NS_OK;
     507                 : }
     508                 : 
     509                 : nsresult
     510            5122 : nsINode::GetNextSibling(nsIDOMNode** aNextSibling)
     511                 : {
     512            5122 :   *aNextSibling = nsnull;
     513                 : 
     514            5122 :   nsIContent *sibling = GetNextSibling();
     515                 : 
     516            5122 :   return sibling ? CallQueryInterface(sibling, aNextSibling) : NS_OK;
     517                 : }
     518                 : 
     519                 : nsresult
     520             365 : nsINode::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
     521                 : {
     522             365 :   *aOwnerDocument = nsnull;
     523                 : 
     524             365 :   nsIDocument *ownerDoc = GetOwnerDocument();
     525                 : 
     526             365 :   return ownerDoc ? CallQueryInterface(ownerDoc, aOwnerDocument) : NS_OK;
     527                 : }
     528                 : 
     529                 : nsresult
     530             133 : nsINode::RemoveChild(nsINode *aOldChild)
     531                 : {
     532             133 :   if (!aOldChild) {
     533               0 :     return NS_ERROR_NULL_POINTER;
     534                 :   }
     535                 : 
     536             133 :   if (IsNodeOfType(eDATA_NODE)) {
     537               0 :     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
     538                 :   }
     539                 : 
     540             133 :   if (aOldChild && aOldChild->GetNodeParent() == this) {
     541             133 :     nsContentUtils::MaybeFireNodeRemoved(aOldChild, this, OwnerDoc());
     542                 :   }
     543                 : 
     544             133 :   PRInt32 index = IndexOf(aOldChild);
     545             133 :   if (index == -1) {
     546                 :     // aOldChild isn't one of our children.
     547               0 :     return NS_ERROR_DOM_NOT_FOUND_ERR;
     548                 :   }
     549                 : 
     550             133 :   return RemoveChildAt(index, true);
     551                 : }
     552                 : 
     553                 : nsresult
     554              13 : nsINode::ReplaceOrInsertBefore(bool aReplace, nsIDOMNode* aNewChild,
     555                 :                                nsIDOMNode* aRefChild, nsIDOMNode** aReturn)
     556                 : {
     557              26 :   nsCOMPtr<nsINode> newChild = do_QueryInterface(aNewChild);
     558                 : 
     559                 :   nsresult rv;
     560              26 :   nsCOMPtr<nsINode> refChild;
     561              13 :   if (aRefChild) {
     562               4 :       refChild = do_QueryInterface(aRefChild, &rv);
     563               4 :       NS_ENSURE_SUCCESS(rv, rv);
     564                 :   }
     565                 : 
     566              13 :   rv = ReplaceOrInsertBefore(aReplace, newChild, refChild);
     567              13 :   if (NS_SUCCEEDED(rv)) {
     568              13 :     NS_ADDREF(*aReturn = aReplace ? aRefChild : aNewChild);
     569                 :   }
     570                 : 
     571              13 :   return rv;
     572                 : }
     573                 : 
     574                 : nsresult
     575              10 : nsINode::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
     576                 : {
     577              20 :   nsCOMPtr<nsIContent> oldChild = do_QueryInterface(aOldChild);
     578              10 :   nsresult rv = RemoveChild(oldChild);
     579              10 :   if (NS_SUCCEEDED(rv)) {
     580              10 :     NS_ADDREF(*aReturn = aOldChild);
     581                 :   }
     582              10 :   return rv;
     583                 : }
     584                 : 
     585                 : nsresult
     586              21 : nsINode::Normalize()
     587                 : {
     588                 :   // First collect list of nodes to be removed
     589              42 :   nsAutoTArray<nsCOMPtr<nsIContent>, 50> nodes;
     590                 : 
     591              21 :   bool canMerge = false;
     592              98 :   for (nsIContent* node = this->GetFirstChild();
     593                 :        node;
     594              77 :        node = node->GetNextNode(this)) {
     595              77 :     if (node->NodeType() != nsIDOMNode::TEXT_NODE) {
     596              14 :       canMerge = false;
     597              14 :       continue;
     598                 :     }
     599                 : 
     600              63 :     if (canMerge || node->TextLength() == 0) {
     601                 :       // No need to touch canMerge. That way we can merge across empty
     602                 :       // textnodes if and only if the node before is a textnode
     603              26 :       nodes.AppendElement(node);
     604                 :     }
     605                 :     else {
     606              37 :       canMerge = true;
     607                 :     }
     608                 : 
     609                 :     // If there's no following sibling, then we need to ensure that we don't
     610                 :     // collect following siblings of our (grand)parent as to-be-removed
     611              63 :     canMerge = canMerge && !!node->GetNextSibling();
     612                 :   }
     613                 : 
     614              21 :   if (nodes.IsEmpty()) {
     615               7 :     return NS_OK;
     616                 :   }
     617                 : 
     618                 :   // We're relying on mozAutoSubtreeModified to keep the doc alive here.
     619              14 :   nsIDocument* doc = OwnerDoc();
     620                 : 
     621                 :   // Batch possible DOMSubtreeModified events.
     622              28 :   mozAutoSubtreeModified subtree(doc, nsnull);
     623                 : 
     624                 :   // Fire all DOMNodeRemoved events. Optimize the common case of there being
     625                 :   // no listeners
     626                 :   bool hasRemoveListeners = nsContentUtils::
     627              14 :       HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED);
     628              14 :   if (hasRemoveListeners) {
     629              40 :     for (PRUint32 i = 0; i < nodes.Length(); ++i) {
     630              52 :       nsContentUtils::MaybeFireNodeRemoved(nodes[i], nodes[i]->GetNodeParent(),
     631              52 :                                            doc);
     632                 :     }
     633                 :   }
     634                 : 
     635              28 :   mozAutoDocUpdate batch(doc, UPDATE_CONTENT_MODEL, true);
     636                 : 
     637                 :   // Merge and remove all nodes
     638              28 :   nsAutoString tmpStr;
     639              40 :   for (PRUint32 i = 0; i < nodes.Length(); ++i) {
     640              26 :     nsIContent* node = nodes[i];
     641                 :     // Merge with previous node unless empty
     642              26 :     const nsTextFragment* text = node->GetText();
     643              26 :     if (text->GetLength()) {
     644               9 :       nsIContent* target = node->GetPreviousSibling();
     645               9 :       NS_ASSERTION((target && target->NodeType() == nsIDOMNode::TEXT_NODE) ||
     646                 :                    hasRemoveListeners,
     647                 :                    "Should always have a previous text sibling unless "
     648                 :                    "mutation events messed us up");
     649              18 :       if (!hasRemoveListeners ||
     650               9 :           (target && target->NodeType() == nsIDOMNode::TEXT_NODE)) {
     651               9 :         nsTextNode* t = static_cast<nsTextNode*>(target);
     652               9 :         if (text->Is2b()) {
     653               0 :           t->AppendTextForNormalize(text->Get2b(), text->GetLength(), true, node);
     654                 :         }
     655                 :         else {
     656               9 :           tmpStr.Truncate();
     657               9 :           text->AppendTo(tmpStr);
     658               9 :           t->AppendTextForNormalize(tmpStr.get(), tmpStr.Length(), true, node);
     659                 :         }
     660                 :       }
     661                 :     }
     662                 : 
     663                 :     // Remove node
     664              52 :     nsCOMPtr<nsINode> parent = node->GetNodeParent();
     665              26 :     NS_ASSERTION(parent || hasRemoveListeners,
     666                 :                  "Should always have a parent unless "
     667                 :                  "mutation events messed us up");
     668              26 :     if (parent) {
     669              26 :       parent->RemoveChildAt(parent->IndexOf(node), true);
     670                 :     }
     671                 :   }
     672                 : 
     673              14 :   return NS_OK;
     674                 : }
     675                 : 
     676                 : nsresult
     677               0 : nsINode::GetDOMBaseURI(nsAString &aURI) const
     678                 : {
     679               0 :   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
     680                 : 
     681               0 :   nsCAutoString spec;
     682               0 :   if (baseURI) {
     683               0 :     baseURI->GetSpec(spec);
     684                 :   }
     685                 : 
     686               0 :   CopyUTF8toUTF16(spec, aURI);
     687                 : 
     688               0 :   return NS_OK;
     689                 : }
     690                 : 
     691                 : nsresult
     692               0 : nsINode::LookupPrefix(const nsAString& aNamespaceURI, nsAString& aPrefix)
     693                 : {
     694               0 :   Element *element = GetNameSpaceElement();
     695               0 :   if (element) {
     696                 :     // XXX Waiting for DOM spec to list error codes.
     697                 :   
     698                 :     // Trace up the content parent chain looking for the namespace
     699                 :     // declaration that defines the aNamespaceURI namespace. Once found,
     700                 :     // return the prefix (i.e. the attribute localName).
     701               0 :     for (nsIContent* content = element; content;
     702               0 :          content = content->GetParent()) {
     703               0 :       PRUint32 attrCount = content->GetAttrCount();
     704                 :   
     705               0 :       for (PRUint32 i = 0; i < attrCount; ++i) {
     706               0 :         const nsAttrName* name = content->GetAttrNameAt(i);
     707                 :   
     708               0 :         if (name->NamespaceEquals(kNameSpaceID_XMLNS) &&
     709                 :             content->AttrValueIs(kNameSpaceID_XMLNS, name->LocalName(),
     710               0 :                                  aNamespaceURI, eCaseMatters)) {
     711                 :           // If the localName is "xmlns", the prefix we output should be
     712                 :           // null.
     713               0 :           nsIAtom *localName = name->LocalName();
     714                 :   
     715               0 :           if (localName != nsGkAtoms::xmlns) {
     716               0 :             localName->ToString(aPrefix);
     717                 :           }
     718                 :           else {
     719               0 :             SetDOMStringToNull(aPrefix);
     720                 :           }
     721               0 :           return NS_OK;
     722                 :         }
     723                 :       }
     724                 :     }
     725                 :   }
     726                 : 
     727               0 :   SetDOMStringToNull(aPrefix);
     728                 : 
     729               0 :   return NS_OK;
     730                 : }
     731                 : 
     732                 : static nsresult
     733               0 : SetUserDataProperty(PRUint16 aCategory, nsINode *aNode, nsIAtom *aKey,
     734                 :                     nsISupports* aValue, void** aOldValue)
     735                 : {
     736                 :   nsresult rv = aNode->SetProperty(aCategory, aKey, aValue,
     737                 :                                    nsPropertyTable::SupportsDtorFunc, true,
     738               0 :                                    aOldValue);
     739               0 :   NS_ENSURE_SUCCESS(rv, rv);
     740                 : 
     741                 :   // Property table owns it now.
     742               0 :   NS_ADDREF(aValue);
     743                 : 
     744               0 :   return NS_OK;
     745                 : }
     746                 : 
     747                 : nsresult
     748               0 : nsINode::SetUserData(const nsAString &aKey, nsIVariant *aData,
     749                 :                      nsIDOMUserDataHandler *aHandler, nsIVariant **aResult)
     750                 : {
     751               0 :   *aResult = nsnull;
     752                 : 
     753               0 :   nsCOMPtr<nsIAtom> key = do_GetAtom(aKey);
     754               0 :   if (!key) {
     755               0 :     return NS_ERROR_OUT_OF_MEMORY;
     756                 :   }
     757                 : 
     758                 :   nsresult rv;
     759                 :   void *data;
     760               0 :   if (aData) {
     761               0 :     rv = SetUserDataProperty(DOM_USER_DATA, this, key, aData, &data);
     762               0 :     NS_ENSURE_SUCCESS(rv, rv);
     763                 :   }
     764                 :   else {
     765               0 :     data = UnsetProperty(DOM_USER_DATA, key);
     766                 :   }
     767                 : 
     768                 :   // Take over ownership of the old data from the property table.
     769               0 :   nsCOMPtr<nsIVariant> oldData = dont_AddRef(static_cast<nsIVariant*>(data));
     770                 : 
     771               0 :   if (aData && aHandler) {
     772               0 :     nsCOMPtr<nsIDOMUserDataHandler> oldHandler;
     773                 :     rv = SetUserDataProperty(DOM_USER_DATA_HANDLER, this, key, aHandler,
     774               0 :                              getter_AddRefs(oldHandler));
     775               0 :     if (NS_FAILED(rv)) {
     776                 :       // We failed to set the handler, remove the data.
     777               0 :       DeleteProperty(DOM_USER_DATA, key);
     778                 : 
     779               0 :       return rv;
     780               0 :     }
     781                 :   }
     782                 :   else {
     783               0 :     DeleteProperty(DOM_USER_DATA_HANDLER, key);
     784                 :   }
     785                 : 
     786               0 :   oldData.swap(*aResult);
     787                 : 
     788               0 :   return NS_OK;
     789                 : }
     790                 : 
     791                 : PRUint16
     792              21 : nsINode::CompareDocPosition(nsINode* aOtherNode)
     793                 : {
     794              21 :   NS_PRECONDITION(aOtherNode, "don't pass null");
     795                 : 
     796              21 :   if (this == aOtherNode) {
     797               0 :     return 0;
     798                 :   }
     799                 : 
     800              42 :   nsAutoTArray<nsINode*, 32> parents1, parents2;
     801                 : 
     802              21 :   nsINode *node1 = aOtherNode, *node2 = this;
     803                 : 
     804                 :   // Check if either node is an attribute
     805              21 :   nsIAttribute* attr1 = nsnull;
     806              21 :   if (node1->IsNodeOfType(nsINode::eATTRIBUTE)) {
     807               0 :     attr1 = static_cast<nsIAttribute*>(node1);
     808               0 :     nsIContent* elem = attr1->GetContent();
     809                 :     // If there is an owner element add the attribute
     810                 :     // to the chain and walk up to the element
     811               0 :     if (elem) {
     812               0 :       node1 = elem;
     813               0 :       parents1.AppendElement(static_cast<nsINode*>(attr1));
     814                 :     }
     815                 :   }
     816              21 :   if (node2->IsNodeOfType(nsINode::eATTRIBUTE)) {
     817               0 :     nsIAttribute* attr2 = static_cast<nsIAttribute*>(node2);
     818               0 :     nsIContent* elem = attr2->GetContent();
     819               0 :     if (elem == node1 && attr1) {
     820                 :       // Both nodes are attributes on the same element.
     821                 :       // Compare position between the attributes.
     822                 : 
     823                 :       PRUint32 i;
     824                 :       const nsAttrName* attrName;
     825               0 :       for (i = 0; (attrName = elem->GetAttrNameAt(i)); ++i) {
     826               0 :         if (attrName->Equals(attr1->NodeInfo())) {
     827               0 :           NS_ASSERTION(!attrName->Equals(attr2->NodeInfo()),
     828                 :                        "Different attrs at same position");
     829                 :           return nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
     830               0 :             nsIDOMNode::DOCUMENT_POSITION_PRECEDING;
     831                 :         }
     832               0 :         if (attrName->Equals(attr2->NodeInfo())) {
     833                 :           return nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
     834               0 :             nsIDOMNode::DOCUMENT_POSITION_FOLLOWING;
     835                 :         }
     836                 :       }
     837               0 :       NS_NOTREACHED("neither attribute in the element");
     838               0 :       return nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED;
     839                 :     }
     840                 : 
     841               0 :     if (elem) {
     842               0 :       node2 = elem;
     843               0 :       parents2.AppendElement(static_cast<nsINode*>(attr2));
     844                 :     }
     845                 :   }
     846                 : 
     847                 :   // We now know that both nodes are either nsIContents or nsIDocuments.
     848                 :   // If either node started out as an attribute, that attribute will have
     849                 :   // the same relative position as its ownerElement, except if the
     850                 :   // ownerElement ends up being the container for the other node
     851                 : 
     852                 :   // Build the chain of parents
     853              75 :   do {
     854              75 :     parents1.AppendElement(node1);
     855              75 :     node1 = node1->GetNodeParent();
     856                 :   } while (node1);
     857              75 :   do {
     858              75 :     parents2.AppendElement(node2);
     859              75 :     node2 = node2->GetNodeParent();
     860                 :   } while (node2);
     861                 : 
     862                 :   // Check if the nodes are disconnected.
     863              21 :   PRUint32 pos1 = parents1.Length();
     864              21 :   PRUint32 pos2 = parents2.Length();
     865              21 :   nsINode* top1 = parents1.ElementAt(--pos1);
     866              21 :   nsINode* top2 = parents2.ElementAt(--pos2);
     867              21 :   if (top1 != top2) {
     868                 :     return top1 < top2 ?
     869                 :       (nsIDOMNode::DOCUMENT_POSITION_PRECEDING |
     870                 :        nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED |
     871                 :        nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC) :
     872                 :       (nsIDOMNode::DOCUMENT_POSITION_FOLLOWING |
     873                 :        nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED |
     874               0 :        nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
     875                 :   }
     876                 : 
     877                 :   // Find where the parent chain differs and check indices in the parent.
     878              21 :   nsINode* parent = top1;
     879                 :   PRUint32 len;
     880              42 :   for (len = NS_MIN(pos1, pos2); len > 0; --len) {
     881              40 :     nsINode* child1 = parents1.ElementAt(--pos1);
     882              40 :     nsINode* child2 = parents2.ElementAt(--pos2);
     883              40 :     if (child1 != child2) {
     884                 :       // child1 or child2 can be an attribute here. This will work fine since
     885                 :       // IndexOf will return -1 for the attribute making the attribute be
     886                 :       // considered before any child.
     887              19 :       return parent->IndexOf(child1) < parent->IndexOf(child2) ?
     888                 :         static_cast<PRUint16>(nsIDOMNode::DOCUMENT_POSITION_PRECEDING) :
     889              19 :         static_cast<PRUint16>(nsIDOMNode::DOCUMENT_POSITION_FOLLOWING);
     890                 :     }
     891              21 :     parent = child1;
     892                 :   }
     893                 : 
     894                 :   // We hit the end of one of the parent chains without finding a difference
     895                 :   // between the chains. That must mean that one node is an ancestor of the
     896                 :   // other. The one with the shortest chain must be the ancestor.
     897                 :   return pos1 < pos2 ?
     898                 :     (nsIDOMNode::DOCUMENT_POSITION_PRECEDING |
     899                 :      nsIDOMNode::DOCUMENT_POSITION_CONTAINS) :
     900                 :     (nsIDOMNode::DOCUMENT_POSITION_FOLLOWING |
     901               2 :      nsIDOMNode::DOCUMENT_POSITION_CONTAINED_BY);    
     902                 : }
     903                 : 
     904                 : bool
     905             999 : nsINode::IsEqualTo(nsINode* aOther)
     906                 : {
     907             999 :   if (!aOther) {
     908               0 :     return false;
     909                 :   }
     910                 : 
     911            1998 :   nsAutoString string1, string2;
     912                 : 
     913             999 :   nsINode* node1 = this;
     914             999 :   nsINode* node2 = aOther;
     915            2613 :   do {
     916            3605 :     PRUint16 nodeType = node1->NodeType();
     917            3605 :     if (nodeType != node2->NodeType()) {
     918             166 :       return false;
     919                 :     }
     920                 : 
     921            3439 :     nsINodeInfo* nodeInfo1 = node1->mNodeInfo;
     922            3439 :     nsINodeInfo* nodeInfo2 = node2->mNodeInfo;
     923            6858 :     if (!nodeInfo1->Equals(nodeInfo2) ||
     924            3419 :         nodeInfo1->GetExtraName() != nodeInfo2->GetExtraName()) {
     925              20 :       return false;
     926                 :     }
     927                 : 
     928            3419 :     switch(nodeType) {
     929                 :       case nsIDOMNode::ELEMENT_NODE:
     930                 :       {
     931                 :         // Both are elements (we checked that their nodeinfos are equal). Do the
     932                 :         // check on attributes.
     933            1015 :         Element* element1 = node1->AsElement();
     934            1015 :         Element* element2 = node2->AsElement();
     935            1015 :         PRUint32 attrCount = element1->GetAttrCount();
     936            1015 :         if (attrCount != element2->GetAttrCount()) {
     937              12 :           return false;
     938                 :         }
     939                 : 
     940                 :         // Iterate over attributes.
     941            1691 :         for (PRUint32 i = 0; i < attrCount; ++i) {
     942             692 :           const nsAttrName* attrName = element1->GetAttrNameAt(i);
     943                 : #ifdef DEBUG
     944                 :           bool hasAttr =
     945                 : #endif
     946                 :           element1->GetAttr(attrName->NamespaceID(), attrName->LocalName(),
     947             692 :                             string1);
     948             692 :           NS_ASSERTION(hasAttr, "Why don't we have an attr?");
     949                 :     
     950             692 :           if (!element2->AttrValueIs(attrName->NamespaceID(),
     951                 :                                      attrName->LocalName(),
     952                 :                                      string1,
     953             692 :                                      eCaseMatters)) {
     954               4 :             return false;
     955                 :           }
     956                 :         }
     957             999 :         break;
     958                 :       }
     959                 :       case nsIDOMNode::TEXT_NODE:
     960                 :       case nsIDOMNode::COMMENT_NODE:
     961                 :       case nsIDOMNode::CDATA_SECTION_NODE:
     962                 :       case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
     963                 :       {
     964            2245 :         string1.Truncate();
     965            2245 :         static_cast<nsIContent*>(node1)->AppendTextTo(string1);
     966            2245 :         string2.Truncate();
     967            2245 :         static_cast<nsIContent*>(node2)->AppendTextTo(string2);
     968                 : 
     969            2245 :         if (!string1.Equals(string2)) {
     970              42 :           return false;
     971                 :         }
     972                 : 
     973            2203 :         break;
     974                 :       }
     975                 :       case nsIDOMNode::DOCUMENT_NODE:
     976                 :       case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
     977              51 :         break;
     978                 :       case nsIDOMNode::ATTRIBUTE_NODE:
     979                 :       {
     980             102 :         NS_ASSERTION(node1 == this && node2 == aOther,
     981                 :                      "Did we come upon an attribute node while walking a "
     982                 :                      "subtree?");
     983             204 :         nsCOMPtr<nsIDOMNode> domNode1 = do_QueryInterface(node1);
     984             204 :         nsCOMPtr<nsIDOMNode> domNode2 = do_QueryInterface(node2);
     985             102 :         domNode1->GetNodeValue(string1);
     986             102 :         domNode2->GetNodeValue(string2);
     987                 :         
     988                 :         // Returning here as to not bother walking subtree. And there is no
     989                 :         // risk that we're half way through walking some other subtree since
     990                 :         // attribute nodes doesn't appear in subtrees.
     991             102 :         return string1.Equals(string2);
     992                 :       }
     993                 :       case nsIDOMNode::DOCUMENT_TYPE_NODE:
     994                 :       {
     995              12 :         nsCOMPtr<nsIDOMDocumentType> docType1 = do_QueryInterface(node1);
     996              12 :         nsCOMPtr<nsIDOMDocumentType> docType2 = do_QueryInterface(node2);
     997                 :     
     998               6 :         NS_ASSERTION(docType1 && docType2, "Why don't we have a document type node?");
     999                 : 
    1000                 :         // Public ID
    1001               6 :         docType1->GetPublicId(string1);
    1002               6 :         docType2->GetPublicId(string2);
    1003               6 :         if (!string1.Equals(string2)) {
    1004               0 :           return false;
    1005                 :         }
    1006                 :     
    1007                 :         // System ID
    1008               6 :         docType1->GetSystemId(string1);
    1009               6 :         docType2->GetSystemId(string2);
    1010               6 :         if (!string1.Equals(string2)) {
    1011               0 :           return false;
    1012                 :         }
    1013                 :     
    1014                 :         // Internal subset
    1015               6 :         docType1->GetInternalSubset(string1);
    1016               6 :         docType2->GetInternalSubset(string2);
    1017               6 :         if (!string1.Equals(string2)) {
    1018               0 :           return false;
    1019                 :         }
    1020                 : 
    1021               6 :         break;
    1022                 :       }
    1023                 :       default:
    1024               0 :         NS_ABORT_IF_FALSE(false, "Unknown node type");
    1025                 :     }
    1026                 : 
    1027            3259 :     nsINode* nextNode = node1->GetFirstChild();
    1028            3259 :     if (nextNode) {
    1029             519 :       node1 = nextNode;
    1030             519 :       node2 = node2->GetFirstChild();
    1031                 :     }
    1032                 :     else {
    1033            2740 :       if (node2->GetFirstChild()) {
    1034                 :         // node2 has a firstChild, but node1 doesn't
    1035               7 :         return false;
    1036                 :       }
    1037                 : 
    1038                 :       // Find next sibling, possibly walking parent chain.
    1039             486 :       while (1) {
    1040            3219 :         if (node1 == this) {
    1041             639 :           NS_ASSERTION(node2 == aOther, "Should have reached the start node "
    1042                 :                                         "for both trees at the same time");
    1043             639 :           return true;
    1044                 :         }
    1045                 : 
    1046            2580 :         nextNode = node1->GetNextSibling();
    1047            2580 :         if (nextNode) {
    1048            2094 :           node1 = nextNode;
    1049            2094 :           node2 = node2->GetNextSibling();
    1050            2094 :           break;
    1051                 :         }
    1052                 : 
    1053             486 :         if (node2->GetNextSibling()) {
    1054                 :           // node2 has a nextSibling, but node1 doesn't
    1055               0 :           return false;
    1056                 :         }
    1057                 :         
    1058             486 :         node1 = node1->GetNodeParent();
    1059             486 :         node2 = node2->GetNodeParent();
    1060             486 :         NS_ASSERTION(node1 && node2, "no parent while walking subtree");
    1061                 :       }
    1062                 :     }
    1063                 :   } while(node2);
    1064                 : 
    1065               7 :   return false;
    1066                 : }
    1067                 : 
    1068                 : nsresult
    1069               0 : nsINode::LookupNamespaceURI(const nsAString& aNamespacePrefix,
    1070                 :                             nsAString& aNamespaceURI)
    1071                 : {
    1072               0 :   Element *element = GetNameSpaceElement();
    1073               0 :   if (!element ||
    1074               0 :       NS_FAILED(element->LookupNamespaceURIInternal(aNamespacePrefix,
    1075                 :                                                     aNamespaceURI))) {
    1076               0 :     SetDOMStringToNull(aNamespaceURI);
    1077                 :   }
    1078                 : 
    1079               0 :   return NS_OK;
    1080                 : }
    1081                 : 
    1082           11838 : NS_IMPL_DOMTARGET_DEFAULTS(nsINode)
    1083                 : 
    1084                 : NS_IMETHODIMP
    1085               2 : nsINode::AddEventListener(const nsAString& aType,
    1086                 :                           nsIDOMEventListener *aListener,
    1087                 :                           bool aUseCapture,
    1088                 :                           bool aWantsUntrusted,
    1089                 :                           PRUint8 aOptionalArgc)
    1090                 : {
    1091               2 :   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
    1092                 :                "Won't check if this is chrome, you want to set "
    1093                 :                "aWantsUntrusted to false or make the aWantsUntrusted "
    1094                 :                "explicit by making aOptionalArgc non-zero.");
    1095                 : 
    1096               4 :   if (!aWantsUntrusted &&
    1097                 :       (aOptionalArgc < 2 &&
    1098               2 :        !nsContentUtils::IsChromeDoc(OwnerDoc()))) {
    1099               2 :     aWantsUntrusted = true;
    1100                 :   }
    1101                 : 
    1102               2 :   nsEventListenerManager* listener_manager = GetListenerManager(true);
    1103               2 :   NS_ENSURE_STATE(listener_manager);
    1104                 :   listener_manager->AddEventListener(aType, aListener, aUseCapture,
    1105               2 :                                      aWantsUntrusted);
    1106               2 :   return NS_OK;
    1107                 : }
    1108                 : 
    1109                 : NS_IMETHODIMP
    1110               0 : nsINode::AddSystemEventListener(const nsAString& aType,
    1111                 :                                 nsIDOMEventListener *aListener,
    1112                 :                                 bool aUseCapture,
    1113                 :                                 bool aWantsUntrusted,
    1114                 :                                 PRUint8 aOptionalArgc)
    1115                 : {
    1116               0 :   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
    1117                 :                "Won't check if this is chrome, you want to set "
    1118                 :                "aWantsUntrusted to false or make the aWantsUntrusted "
    1119                 :                "explicit by making aOptionalArgc non-zero.");
    1120                 : 
    1121               0 :   if (!aWantsUntrusted &&
    1122                 :       (aOptionalArgc < 2 &&
    1123               0 :        !nsContentUtils::IsChromeDoc(OwnerDoc()))) {
    1124               0 :     aWantsUntrusted = true;
    1125                 :   }
    1126                 : 
    1127                 :   return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
    1128               0 :                                    aWantsUntrusted);
    1129                 : }
    1130                 : 
    1131                 : NS_IMETHODIMP
    1132               0 : nsINode::RemoveEventListener(const nsAString& aType,
    1133                 :                              nsIDOMEventListener* aListener,
    1134                 :                              bool aUseCapture)
    1135                 : {
    1136               0 :   nsEventListenerManager* elm = GetListenerManager(false);
    1137               0 :   if (elm) {
    1138               0 :     elm->RemoveEventListener(aType, aListener, aUseCapture);
    1139                 :   }
    1140               0 :   return NS_OK;
    1141                 : }
    1142                 : 
    1143               0 : NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsINode)
    1144                 : 
    1145                 : nsresult
    1146               0 : nsINode::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
    1147                 : {
    1148                 :   // This is only here so that we can use the NS_DECL_NSIDOMTARGET macro
    1149               0 :   NS_ABORT();
    1150               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1151                 : }
    1152                 : 
    1153                 : nsresult
    1154            5407 : nsINode::DispatchEvent(nsIDOMEvent *aEvent, bool* aRetVal)
    1155                 : {
    1156                 :   // XXX sXBL/XBL2 issue -- do we really want the owner here?  What
    1157                 :   // if that's the XBL document?  Would we want its presshell?  Or what?
    1158           10814 :   nsCOMPtr<nsIDocument> document = OwnerDoc();
    1159                 : 
    1160                 :   // Do nothing if the element does not belong to a document
    1161            5407 :   if (!document) {
    1162               0 :     *aRetVal = true;
    1163               0 :     return NS_OK;
    1164                 :   }
    1165                 : 
    1166                 :   // Obtain a presentation shell
    1167            5407 :   nsIPresShell *shell = document->GetShell();
    1168           10814 :   nsRefPtr<nsPresContext> context;
    1169            5407 :   if (shell) {
    1170               0 :     context = shell->GetPresContext();
    1171                 :   }
    1172                 : 
    1173            5407 :   nsEventStatus status = nsEventStatus_eIgnore;
    1174                 :   nsresult rv =
    1175                 :     nsEventDispatcher::DispatchDOMEvent(this, nsnull, aEvent, context,
    1176            5407 :                                         &status);
    1177            5407 :   *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
    1178            5407 :   return rv;
    1179                 : }
    1180                 : 
    1181                 : nsresult
    1182            6465 : nsINode::PostHandleEvent(nsEventChainPostVisitor& /*aVisitor*/)
    1183                 : {
    1184            6465 :   return NS_OK;
    1185                 : }
    1186                 : 
    1187                 : nsresult
    1188               0 : nsINode::DispatchDOMEvent(nsEvent* aEvent,
    1189                 :                           nsIDOMEvent* aDOMEvent,
    1190                 :                           nsPresContext* aPresContext,
    1191                 :                           nsEventStatus* aEventStatus)
    1192                 : {
    1193                 :   return nsEventDispatcher::DispatchDOMEvent(this, aEvent, aDOMEvent,
    1194               0 :                                              aPresContext, aEventStatus);
    1195                 : }
    1196                 : 
    1197                 : nsEventListenerManager*
    1198           27262 : nsINode::GetListenerManager(bool aCreateIfNotFound)
    1199                 : {
    1200           27262 :   return nsContentUtils::GetListenerManager(this, aCreateIfNotFound);
    1201                 : }
    1202                 : 
    1203                 : nsIScriptContext*
    1204               2 : nsINode::GetContextForEventHandlers(nsresult* aRv)
    1205                 : {
    1206               2 :   return nsContentUtils::GetContextForEventHandlers(this, aRv);
    1207                 : }
    1208                 : 
    1209                 : /* static */
    1210                 : void
    1211          138789 : nsINode::Trace(nsINode *tmp, TraceCallback cb, void *closure)
    1212                 : {
    1213          138789 :   nsContentUtils::TraceWrapper(tmp, cb, closure);
    1214          138789 : }
    1215                 : 
    1216                 : 
    1217                 : static
    1218          501553 : bool UnoptimizableCCNode(nsINode* aNode)
    1219                 : {
    1220                 :   const PtrBits problematicFlags = (NODE_IS_ANONYMOUS |
    1221                 :                                     NODE_IS_IN_ANONYMOUS_SUBTREE |
    1222                 :                                     NODE_IS_NATIVE_ANONYMOUS_ROOT |
    1223                 :                                     NODE_MAY_BE_IN_BINDING_MNGR |
    1224          501553 :                                     NODE_IS_INSERTION_PARENT);
    1225          501553 :   return aNode->HasFlag(problematicFlags) ||
    1226          501553 :          aNode->NodeType() == nsIDOMNode::ATTRIBUTE_NODE ||
    1227                 :          // For strange cases like xbl:content/xbl:children
    1228          501553 :          (aNode->IsElement() &&
    1229         1504659 :           aNode->AsElement()->IsInNamespace(kNameSpaceID_XBL));
    1230                 : }
    1231                 : 
    1232                 : /* static */
    1233                 : bool
    1234          138775 : nsINode::Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb)
    1235                 : {
    1236          138775 :   nsIDocument *currentDoc = tmp->GetCurrentDoc();
    1237          274435 :   if (currentDoc &&
    1238          135660 :       nsCCUncollectableMarker::InGeneration(cb, currentDoc->GetMarkedCCGeneration())) {
    1239               0 :     return false;
    1240                 :   }
    1241                 : 
    1242          138775 :   if (nsCCUncollectableMarker::sGeneration) {
    1243                 :     // If we're black no need to traverse.
    1244           56350 :     if (tmp->IsBlack() || tmp->InCCBlackTree()) {
    1245               0 :       return false;
    1246                 :     }
    1247                 : 
    1248           56350 :     if (!UnoptimizableCCNode(tmp)) {
    1249                 :       // If we're in a black document, return early.
    1250           56350 :       if ((currentDoc && currentDoc->IsBlack())) {
    1251               0 :         return false;
    1252                 :       }
    1253                 :       // If we're not in anonymous content and we have a black parent,
    1254                 :       // return early.
    1255           56350 :       nsIContent* parent = tmp->GetParent();
    1256           56350 :       if (parent && !UnoptimizableCCNode(parent) && parent->IsBlack()) {
    1257               0 :         NS_ABORT_IF_FALSE(parent->IndexOf(tmp) >= 0, "Parent doesn't own us?");
    1258               0 :         return false;
    1259                 :       }
    1260                 :     }
    1261                 :   }
    1262                 : 
    1263          138775 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNodeInfo)
    1264          138775 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(GetParent())
    1265                 : 
    1266          138775 :   nsSlots *slots = tmp->GetExistingSlots();
    1267          138775 :   if (slots) {
    1268            4988 :     slots->Traverse(cb);
    1269                 :   }
    1270                 : 
    1271          138775 :   if (tmp->HasProperties()) {
    1272               0 :     nsNodeUtils::TraverseUserData(tmp, cb);
    1273                 :   }
    1274                 : 
    1275          276088 :   if (tmp->NodeType() != nsIDOMNode::DOCUMENT_NODE &&
    1276          137313 :       tmp->HasFlag(NODE_HAS_LISTENERMANAGER)) {
    1277               3 :     nsContentUtils::TraverseListenerManager(tmp, cb);
    1278                 :   }
    1279                 : 
    1280          138775 :   return true;
    1281                 : }
    1282                 : 
    1283                 : /* static */
    1284                 : void
    1285          114987 : nsINode::Unlink(nsINode *tmp)
    1286                 : {
    1287          114987 :   nsContentUtils::ReleaseWrapper(tmp, tmp);
    1288                 : 
    1289          114987 :   nsSlots *slots = tmp->GetExistingSlots();
    1290          114987 :   if (slots) {
    1291            4609 :     slots->Unlink();
    1292                 :   }
    1293                 : 
    1294          228703 :   if (tmp->NodeType() != nsIDOMNode::DOCUMENT_NODE &&
    1295          113716 :       tmp->HasFlag(NODE_HAS_LISTENERMANAGER)) {
    1296               0 :     nsContentUtils::RemoveListenerManager(tmp);
    1297               0 :     tmp->UnsetFlags(NODE_HAS_LISTENERMANAGER);
    1298                 :   }
    1299                 : 
    1300          114987 :   if (tmp->HasProperties()) {
    1301               0 :     nsNodeUtils::UnlinkUserData(tmp);
    1302                 :   }
    1303          114987 : }
    1304                 : 
    1305                 : //----------------------------------------------------------------------
    1306                 : 
    1307                 : nsEventStates
    1308           11603 : Element::IntrinsicState() const
    1309                 : {
    1310           11603 :   return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE :
    1311           23206 :                         NS_EVENT_STATE_MOZ_READONLY;
    1312                 : }
    1313                 : 
    1314                 : void
    1315               0 : Element::NotifyStateChange(nsEventStates aStates)
    1316                 : {
    1317               0 :   nsIDocument* doc = GetCurrentDoc();
    1318               0 :   if (doc) {
    1319               0 :     nsAutoScriptBlocker scriptBlocker;
    1320               0 :     doc->ContentStateChanged(this, aStates);
    1321                 :   }
    1322               0 : }
    1323                 : 
    1324                 : void
    1325               0 : Element::UpdateLinkState(nsEventStates aState)
    1326                 : {
    1327               0 :   NS_ABORT_IF_FALSE(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED |
    1328                 :                                                     NS_EVENT_STATE_UNVISITED)),
    1329                 :                     "Unexpected link state bits");
    1330                 :   mState =
    1331                 :     (mState & ~(NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) |
    1332               0 :     aState;
    1333               0 : }
    1334                 : 
    1335                 : void
    1336           11603 : Element::UpdateState(bool aNotify)
    1337                 : {
    1338           11603 :   nsEventStates oldState = mState;
    1339           11603 :   mState = IntrinsicState() | (oldState & ESM_MANAGED_STATES);
    1340           11603 :   if (aNotify) {
    1341            1874 :     nsEventStates changedStates = oldState ^ mState;
    1342            1874 :     if (!changedStates.IsEmpty()) {
    1343               0 :       nsIDocument* doc = GetCurrentDoc();
    1344               0 :       if (doc) {
    1345               0 :         nsAutoScriptBlocker scriptBlocker;
    1346               0 :         doc->ContentStateChanged(this, changedStates);
    1347                 :       }
    1348                 :     }
    1349                 :   }
    1350           11603 : }
    1351                 : 
    1352                 : void
    1353           74006 : nsIContent::UpdateEditableState(bool aNotify)
    1354                 : {
    1355                 :   // Guaranteed to be non-element content
    1356           74006 :   NS_ASSERTION(!IsElement(), "What happened here?");
    1357           74006 :   nsIContent *parent = GetParent();
    1358                 : 
    1359           74006 :   SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
    1360           74006 : }
    1361                 : 
    1362                 : void
    1363           37893 : nsGenericElement::UpdateEditableState(bool aNotify)
    1364                 : {
    1365           37893 :   nsIContent *parent = GetParent();
    1366                 : 
    1367           37893 :   SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
    1368           37893 :   if (aNotify) {
    1369               0 :     UpdateState(aNotify);
    1370                 :   } else {
    1371                 :     // Avoid calling UpdateState in this very common case, because
    1372                 :     // this gets called for pretty much every single element on
    1373                 :     // insertion into the document and UpdateState can be slow for
    1374                 :     // some kinds of elements even when not notifying.
    1375           37893 :     if (IsEditable()) {
    1376               0 :       RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
    1377               0 :       AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
    1378                 :     } else {
    1379           37893 :       RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
    1380           37893 :       AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
    1381                 :     }
    1382                 :   }
    1383           37893 : }
    1384                 : 
    1385                 : nsEventStates
    1386               0 : Element::StyleStateFromLocks() const
    1387                 : {
    1388               0 :   nsEventStates locks = LockedStyleStates();
    1389               0 :   nsEventStates state = mState | locks;
    1390                 : 
    1391               0 :   if (locks.HasState(NS_EVENT_STATE_VISITED)) {
    1392               0 :     return state & ~NS_EVENT_STATE_UNVISITED;
    1393                 :   }
    1394               0 :   if (locks.HasState(NS_EVENT_STATE_UNVISITED)) {
    1395               0 :     return state & ~NS_EVENT_STATE_VISITED;
    1396                 :   }
    1397               0 :   return state;
    1398                 : }
    1399                 : 
    1400                 : nsEventStates
    1401               0 : Element::LockedStyleStates() const
    1402                 : {
    1403                 :   nsEventStates *locks =
    1404               0 :     static_cast<nsEventStates*> (GetProperty(nsGkAtoms::lockedStyleStates));
    1405               0 :   if (locks) {
    1406               0 :     return *locks;
    1407                 :   }
    1408               0 :   return nsEventStates();
    1409                 : }
    1410                 : 
    1411                 : static void
    1412               0 : nsEventStatesPropertyDtor(void *aObject, nsIAtom *aProperty,
    1413                 :                           void *aPropertyValue, void *aData)
    1414                 : {
    1415               0 :   nsEventStates *states = static_cast<nsEventStates*>(aPropertyValue);
    1416                 :   delete states;
    1417               0 : }
    1418                 : 
    1419                 : void
    1420               0 : Element::NotifyStyleStateChange(nsEventStates aStates)
    1421                 : {
    1422               0 :   nsIDocument* doc = GetCurrentDoc();
    1423               0 :   if (doc) {
    1424               0 :     nsIPresShell *presShell = doc->GetShell();
    1425               0 :     if (presShell) {
    1426               0 :       nsAutoScriptBlocker scriptBlocker;
    1427               0 :       presShell->ContentStateChanged(doc, this, aStates);
    1428                 :     }
    1429                 :   }
    1430               0 : }
    1431                 : 
    1432                 : void
    1433               0 : Element::LockStyleStates(nsEventStates aStates)
    1434                 : {
    1435               0 :   nsEventStates *locks = new nsEventStates(LockedStyleStates());
    1436                 : 
    1437               0 :   *locks |= aStates;
    1438                 : 
    1439               0 :   if (aStates.HasState(NS_EVENT_STATE_VISITED)) {
    1440               0 :     *locks &= ~NS_EVENT_STATE_UNVISITED;
    1441                 :   }
    1442               0 :   if (aStates.HasState(NS_EVENT_STATE_UNVISITED)) {
    1443               0 :     *locks &= ~NS_EVENT_STATE_VISITED;
    1444                 :   }
    1445                 : 
    1446               0 :   SetProperty(nsGkAtoms::lockedStyleStates, locks, nsEventStatesPropertyDtor);
    1447               0 :   SetHasLockedStyleStates();
    1448                 : 
    1449               0 :   NotifyStyleStateChange(aStates);
    1450               0 : }
    1451                 : 
    1452                 : void
    1453               0 : Element::UnlockStyleStates(nsEventStates aStates)
    1454                 : {
    1455               0 :   nsEventStates *locks = new nsEventStates(LockedStyleStates());
    1456                 : 
    1457               0 :   *locks &= ~aStates;
    1458                 : 
    1459               0 :   if (locks->IsEmpty()) {
    1460               0 :     DeleteProperty(nsGkAtoms::lockedStyleStates);
    1461               0 :     ClearHasLockedStyleStates();
    1462                 :     delete locks;
    1463                 :   }
    1464                 :   else {
    1465               0 :     SetProperty(nsGkAtoms::lockedStyleStates, locks, nsEventStatesPropertyDtor);
    1466                 :   }
    1467                 : 
    1468               0 :   NotifyStyleStateChange(aStates);
    1469               0 : }
    1470                 : 
    1471                 : void
    1472               0 : Element::ClearStyleStateLocks()
    1473                 : {
    1474               0 :   nsEventStates locks = LockedStyleStates();
    1475                 : 
    1476               0 :   DeleteProperty(nsGkAtoms::lockedStyleStates);
    1477               0 :   ClearHasLockedStyleStates();
    1478                 : 
    1479               0 :   NotifyStyleStateChange(locks);
    1480               0 : }
    1481                 : 
    1482                 : nsIContent*
    1483               0 : nsIContent::FindFirstNonNativeAnonymous() const
    1484                 : {
    1485                 :   // This handles also nested native anonymous content.
    1486               0 :   for (const nsIContent *content = this; content;
    1487               0 :        content = content->GetBindingParent()) {
    1488               0 :     if (!content->IsInNativeAnonymousSubtree()) {
    1489                 :       // Oops, this function signature allows casting const to
    1490                 :       // non-const.  (Then again, so does GetChildAt(0)->GetParent().)
    1491               0 :       return const_cast<nsIContent*>(content);
    1492                 :     }
    1493                 :   }
    1494               0 :   return nsnull;
    1495                 : }
    1496                 : 
    1497                 : nsIContent*
    1498               0 : nsIContent::GetFlattenedTreeParent() const
    1499                 : {
    1500               0 :   nsIContent *parent = GetParent();
    1501               0 :   if (parent && parent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
    1502               0 :     nsIDocument *doc = parent->OwnerDoc();
    1503                 :     nsIContent* insertionElement =
    1504               0 :       doc->BindingManager()->GetNestedInsertionPoint(parent, this);
    1505               0 :     if (insertionElement) {
    1506               0 :       parent = insertionElement;
    1507                 :     }
    1508                 :   }
    1509               0 :   return parent;
    1510                 : }
    1511                 : 
    1512                 : nsIContent::IMEState
    1513               0 : nsIContent::GetDesiredIMEState()
    1514                 : {
    1515               0 :   if (!IsEditableInternal()) {
    1516               0 :     return IMEState(IMEState::DISABLED);
    1517                 :   }
    1518                 :   // NOTE: The content for independent editors (e.g., input[type=text],
    1519                 :   // textarea) must override this method, so, we don't need to worry about
    1520                 :   // that here.
    1521               0 :   nsIContent *editableAncestor = GetEditingHost();
    1522                 : 
    1523                 :   // This is in another editable content, use the result of it.
    1524               0 :   if (editableAncestor && editableAncestor != this) {
    1525               0 :     return editableAncestor->GetDesiredIMEState();
    1526                 :   }
    1527               0 :   nsIDocument* doc = GetCurrentDoc();
    1528               0 :   if (!doc) {
    1529               0 :     return IMEState(IMEState::DISABLED);
    1530                 :   }
    1531               0 :   nsIPresShell* ps = doc->GetShell();
    1532               0 :   if (!ps) {
    1533               0 :     return IMEState(IMEState::DISABLED);
    1534                 :   }
    1535               0 :   nsPresContext* pc = ps->GetPresContext();
    1536               0 :   if (!pc) {
    1537               0 :     return IMEState(IMEState::DISABLED);
    1538                 :   }
    1539               0 :   nsIEditor* editor = GetHTMLEditor(pc);
    1540               0 :   nsCOMPtr<nsIEditorIMESupport> imeEditor = do_QueryInterface(editor);
    1541               0 :   if (!imeEditor) {
    1542               0 :     return IMEState(IMEState::DISABLED);
    1543                 :   }
    1544               0 :   IMEState state;
    1545               0 :   imeEditor->GetPreferredIMEState(&state);
    1546               0 :   return state;
    1547                 : }
    1548                 : 
    1549                 : bool
    1550               0 : nsIContent::HasIndependentSelection()
    1551                 : {
    1552               0 :   nsIFrame* frame = GetPrimaryFrame();
    1553               0 :   return (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
    1554                 : }
    1555                 : 
    1556                 : nsIContent*
    1557               0 : nsIContent::GetEditingHost()
    1558                 : {
    1559                 :   // If this isn't editable, return NULL.
    1560               0 :   NS_ENSURE_TRUE(IsEditableInternal(), nsnull);
    1561                 : 
    1562               0 :   nsIDocument* doc = GetCurrentDoc();
    1563               0 :   NS_ENSURE_TRUE(doc, nsnull);
    1564                 :   // If this is in designMode, we should return <body>
    1565               0 :   if (doc->HasFlag(NODE_IS_EDITABLE)) {
    1566               0 :     return doc->GetBodyElement();
    1567                 :   }
    1568                 : 
    1569               0 :   nsIContent* content = this;
    1570               0 :   for (nsIContent* parent = GetParent();
    1571               0 :        parent && parent->HasFlag(NODE_IS_EDITABLE);
    1572               0 :        parent = content->GetParent()) {
    1573               0 :     content = parent;
    1574                 :   }
    1575               0 :   return content;
    1576                 : }
    1577                 : 
    1578                 : nsresult
    1579               0 : nsIContent::LookupNamespaceURIInternal(const nsAString& aNamespacePrefix,
    1580                 :                                        nsAString& aNamespaceURI) const
    1581                 : {
    1582               0 :   if (aNamespacePrefix.EqualsLiteral("xml")) {
    1583                 :     // Special-case for xml prefix
    1584               0 :     aNamespaceURI.AssignLiteral("http://www.w3.org/XML/1998/namespace");
    1585               0 :     return NS_OK;
    1586                 :   }
    1587                 : 
    1588               0 :   if (aNamespacePrefix.EqualsLiteral("xmlns")) {
    1589                 :     // Special-case for xmlns prefix
    1590               0 :     aNamespaceURI.AssignLiteral("http://www.w3.org/2000/xmlns/");
    1591               0 :     return NS_OK;
    1592                 :   }
    1593                 : 
    1594               0 :   nsCOMPtr<nsIAtom> name;
    1595               0 :   if (!aNamespacePrefix.IsEmpty()) {
    1596               0 :     name = do_GetAtom(aNamespacePrefix);
    1597               0 :     NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
    1598                 :   }
    1599                 :   else {
    1600               0 :     name = nsGkAtoms::xmlns;
    1601                 :   }
    1602                 :   // Trace up the content parent chain looking for the namespace
    1603                 :   // declaration that declares aNamespacePrefix.
    1604               0 :   const nsIContent* content = this;
    1605               0 :   do {
    1606               0 :     if (content->GetAttr(kNameSpaceID_XMLNS, name, aNamespaceURI))
    1607               0 :       return NS_OK;
    1608               0 :   } while ((content = content->GetParent()));
    1609               0 :   return NS_ERROR_FAILURE;
    1610                 : }
    1611                 : 
    1612                 : already_AddRefed<nsIURI>
    1613               0 : nsIContent::GetBaseURI() const
    1614                 : {
    1615               0 :   nsIDocument* doc = OwnerDoc();
    1616                 :   // Start with document base
    1617               0 :   nsCOMPtr<nsIURI> base = doc->GetDocBaseURI();
    1618                 : 
    1619                 :   // Collect array of xml:base attribute values up the parent chain. This
    1620                 :   // is slightly slower for the case when there are xml:base attributes, but
    1621                 :   // faster for the far more common case of there not being any such
    1622                 :   // attributes.
    1623                 :   // Also check for SVG elements which require special handling
    1624               0 :   nsAutoTArray<nsString, 5> baseAttrs;
    1625               0 :   nsString attr;
    1626               0 :   const nsIContent *elem = this;
    1627               0 :   do {
    1628                 :     // First check for SVG specialness (why is this SVG specific?)
    1629               0 :     if (elem->IsSVG()) {
    1630               0 :       nsIContent* bindingParent = elem->GetBindingParent();
    1631               0 :       if (bindingParent) {
    1632                 :         nsXBLBinding* binding =
    1633               0 :           bindingParent->OwnerDoc()->BindingManager()->GetBinding(bindingParent);
    1634               0 :         if (binding) {
    1635                 :           // XXX sXBL/XBL2 issue
    1636                 :           // If this is an anonymous XBL element use the binding
    1637                 :           // document for the base URI. 
    1638                 :           // XXX Will fail with xml:base
    1639               0 :           base = binding->PrototypeBinding()->DocURI();
    1640               0 :           break;
    1641                 :         }
    1642                 :       }
    1643                 :     }
    1644                 : 
    1645               0 :     nsIURI* explicitBaseURI = elem->GetExplicitBaseURI();
    1646               0 :     if (explicitBaseURI) {
    1647               0 :       base = explicitBaseURI;
    1648               0 :       break;
    1649                 :     }
    1650                 :     
    1651                 :     // Otherwise check for xml:base attribute
    1652               0 :     elem->GetAttr(kNameSpaceID_XML, nsGkAtoms::base, attr);
    1653               0 :     if (!attr.IsEmpty()) {
    1654               0 :       baseAttrs.AppendElement(attr);
    1655                 :     }
    1656               0 :     elem = elem->GetParent();
    1657                 :   } while(elem);
    1658                 :   
    1659                 :   // Now resolve against all xml:base attrs
    1660               0 :   for (PRUint32 i = baseAttrs.Length() - 1; i != PRUint32(-1); --i) {
    1661               0 :     nsCOMPtr<nsIURI> newBase;
    1662               0 :     nsresult rv = NS_NewURI(getter_AddRefs(newBase), baseAttrs[i],
    1663               0 :                             doc->GetDocumentCharacterSet().get(), base);
    1664                 :     // Do a security check, almost the same as nsDocument::SetBaseURL()
    1665                 :     // Only need to do this on the final uri
    1666               0 :     if (NS_SUCCEEDED(rv) && i == 0) {
    1667               0 :       rv = nsContentUtils::GetSecurityManager()->
    1668                 :         CheckLoadURIWithPrincipal(NodePrincipal(), newBase,
    1669               0 :                                   nsIScriptSecurityManager::STANDARD);
    1670                 :     }
    1671               0 :     if (NS_SUCCEEDED(rv)) {
    1672               0 :       base.swap(newBase);
    1673                 :     }
    1674                 :   }
    1675                 : 
    1676               0 :   return base.forget();
    1677                 : }
    1678                 : 
    1679                 : static void
    1680               0 : ReleaseURI(void*, /* aObject*/
    1681                 :            nsIAtom*, /* aPropertyName */
    1682                 :            void* aPropertyValue,
    1683                 :            void* /* aData */)
    1684                 : {
    1685               0 :   nsIURI* uri = static_cast<nsIURI*>(aPropertyValue);
    1686               0 :   NS_RELEASE(uri);
    1687               0 : }
    1688                 : 
    1689                 : nsresult
    1690               0 : nsINode::SetExplicitBaseURI(nsIURI* aURI)
    1691                 : {
    1692               0 :   nsresult rv = SetProperty(nsGkAtoms::baseURIProperty, aURI, ReleaseURI);
    1693               0 :   if (NS_SUCCEEDED(rv)) {
    1694               0 :     SetHasExplicitBaseURI();
    1695               0 :     NS_ADDREF(aURI);
    1696                 :   }
    1697               0 :   return rv;
    1698                 : }
    1699                 : 
    1700                 : //----------------------------------------------------------------------
    1701                 : 
    1702                 : static JSObject*
    1703           95931 : GetJSObjectChild(nsWrapperCache* aCache)
    1704                 : {
    1705           95931 :   if (aCache->PreservingWrapper()) {
    1706               0 :     return aCache->GetWrapperPreserveColor();
    1707                 :   }
    1708           95931 :   return aCache->GetExpandoObjectPreserveColor();
    1709                 : }
    1710                 : 
    1711                 : static bool
    1712           36539 : NeedsScriptTraverse(nsWrapperCache* aCache)
    1713                 : {
    1714           36539 :   JSObject* o = GetJSObjectChild(aCache);
    1715           36539 :   return o && xpc_IsGrayGCThing(o);
    1716                 : }
    1717                 : 
    1718                 : //----------------------------------------------------------------------
    1719                 : 
    1720           22937 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsChildContentList)
    1721           24464 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsChildContentList)
    1722                 : 
    1723                 : // If nsChildContentList is changed so that any additional fields are
    1724                 : // traversed by the cycle collector, then CAN_SKIP must be updated.
    1725            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsChildContentList)
    1726            1527 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsChildContentList)
    1727            1527 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
    1728            1527 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1729            1527 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsChildContentList)
    1730            1527 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
    1731            1527 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    1732            1527 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsChildContentList)
    1733            1527 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
    1734            1527 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
    1735                 : 
    1736                 : // nsChildContentList only ever has a single child, its wrapper, so if
    1737                 : // the wrapper is black, the list can't be part of a garbage cycle.
    1738            1063 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsChildContentList)
    1739            1063 :   return !NeedsScriptTraverse(tmp);
    1740                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
    1741                 : 
    1742             727 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsChildContentList)
    1743             727 :   return !NeedsScriptTraverse(tmp);
    1744                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
    1745                 : 
    1746                 : // CanSkipThis returns false to avoid problems with incomplete unlinking.
    1747            1527 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsChildContentList)
    1748            1527 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
    1749                 : 
    1750           42157 : NS_INTERFACE_TABLE_HEAD(nsChildContentList)
    1751           42157 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    1752                 :   NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsChildContentList)
    1753                 :     NS_INTERFACE_TABLE_ENTRY(nsChildContentList, nsINodeList)
    1754                 :     NS_INTERFACE_TABLE_ENTRY(nsChildContentList, nsIDOMNodeList)
    1755           40630 :   NS_OFFSET_AND_INTERFACE_TABLE_END
    1756           40630 :   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
    1757           26863 :   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsChildContentList)
    1758               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(NodeList)
    1759               0 : NS_INTERFACE_MAP_END
    1760                 : 
    1761                 : JSObject*
    1762            1527 : nsChildContentList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
    1763                 :                                bool *triedToWrap)
    1764                 : {
    1765            1527 :   return mozilla::dom::binding::NodeList::create(cx, scope, this, triedToWrap);
    1766                 : }
    1767                 : 
    1768                 : NS_IMETHODIMP
    1769            5684 : nsChildContentList::GetLength(PRUint32* aLength)
    1770                 : {
    1771            5684 :   *aLength = mNode ? mNode->GetChildCount() : 0;
    1772                 : 
    1773            5684 :   return NS_OK;
    1774                 : }
    1775                 : 
    1776                 : NS_IMETHODIMP
    1777               0 : nsChildContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
    1778                 : {
    1779               0 :   nsINode* node = GetNodeAt(aIndex);
    1780               0 :   if (!node) {
    1781               0 :     *aReturn = nsnull;
    1782                 : 
    1783               0 :     return NS_OK;
    1784                 :   }
    1785                 : 
    1786               0 :   return CallQueryInterface(node, aReturn);
    1787                 : }
    1788                 : 
    1789                 : nsIContent*
    1790            4224 : nsChildContentList::GetNodeAt(PRUint32 aIndex)
    1791                 : {
    1792            4224 :   if (mNode) {
    1793            4224 :     return mNode->GetChildAt(aIndex);
    1794                 :   }
    1795                 : 
    1796               0 :   return nsnull;
    1797                 : }
    1798                 : 
    1799                 : PRInt32
    1800               0 : nsChildContentList::IndexOf(nsIContent* aContent)
    1801                 : {
    1802               0 :   if (mNode) {
    1803               0 :     return mNode->IndexOf(aContent);
    1804                 :   }
    1805                 : 
    1806               0 :   return -1;
    1807                 : }
    1808                 : 
    1809                 : //----------------------------------------------------------------------
    1810                 : 
    1811            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsNode3Tearoff, mNode)
    1812                 : 
    1813               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNode3Tearoff)
    1814               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMXPathNSResolver)
    1815               0 : NS_INTERFACE_MAP_END_AGGREGATED(mNode)
    1816                 : 
    1817               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNode3Tearoff)
    1818               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNode3Tearoff)
    1819                 : 
    1820                 : NS_IMETHODIMP
    1821               0 : nsNode3Tearoff::LookupNamespaceURI(const nsAString& aNamespacePrefix,
    1822                 :                                    nsAString& aNamespaceURI)
    1823                 : {
    1824               0 :   return mNode->LookupNamespaceURI(aNamespacePrefix, aNamespaceURI);
    1825                 : }
    1826                 : 
    1827                 : nsIContent*
    1828               4 : nsGenericElement::GetFirstElementChild()
    1829                 : {
    1830               4 :   nsAttrAndChildArray& children = mAttrsAndChildren;
    1831               4 :   PRUint32 i, count = children.ChildCount();
    1832               8 :   for (i = 0; i < count; ++i) {
    1833               8 :     nsIContent* child = children.ChildAt(i);
    1834               8 :     if (child->IsElement()) {
    1835               4 :       return child;
    1836                 :     }
    1837                 :   }
    1838                 :   
    1839               0 :   return nsnull;
    1840                 : }
    1841                 : 
    1842                 : nsIContent*
    1843               0 : nsGenericElement::GetLastElementChild()
    1844                 : {
    1845               0 :   nsAttrAndChildArray& children = mAttrsAndChildren;
    1846               0 :   PRUint32 i = children.ChildCount();
    1847               0 :   while (i > 0) {
    1848               0 :     nsIContent* child = children.ChildAt(--i);
    1849               0 :     if (child->IsElement()) {
    1850               0 :       return child;
    1851                 :     }
    1852                 :   }
    1853                 :   
    1854               0 :   return nsnull;
    1855                 : }
    1856                 : 
    1857                 : nsIContent*
    1858               0 : nsGenericElement::GetPreviousElementSibling()
    1859                 : {
    1860               0 :   nsIContent* parent = GetParent();
    1861               0 :   if (!parent) {
    1862               0 :     return nsnull;
    1863                 :   }
    1864                 : 
    1865               0 :   NS_ASSERTION(parent->IsElement() ||
    1866                 :                parent->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT),
    1867                 :                "Parent content must be an element or a doc fragment");
    1868                 : 
    1869                 :   nsAttrAndChildArray& children =
    1870               0 :     static_cast<nsGenericElement*>(parent)->mAttrsAndChildren;
    1871               0 :   PRInt32 index = children.IndexOfChild(this);
    1872               0 :   if (index < 0) {
    1873               0 :     return nsnull;
    1874                 :   }
    1875                 : 
    1876               0 :   PRUint32 i = index;
    1877               0 :   while (i > 0) {
    1878               0 :     nsIContent* child = children.ChildAt((PRUint32)--i);
    1879               0 :     if (child->IsElement()) {
    1880               0 :       return child;
    1881                 :     }
    1882                 :   }
    1883                 :   
    1884               0 :   return nsnull;
    1885                 : }
    1886                 : 
    1887                 : nsIContent*
    1888               0 : nsGenericElement::GetNextElementSibling()
    1889                 : {
    1890               0 :   nsIContent* parent = GetParent();
    1891               0 :   if (!parent) {
    1892               0 :     return nsnull;
    1893                 :   }
    1894                 : 
    1895               0 :   NS_ASSERTION(parent->IsElement() ||
    1896                 :                parent->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT),
    1897                 :                "Parent content must be an element or a doc fragment");
    1898                 : 
    1899                 :   nsAttrAndChildArray& children =
    1900               0 :     static_cast<nsGenericElement*>(parent)->mAttrsAndChildren;
    1901               0 :   PRInt32 index = children.IndexOfChild(this);
    1902               0 :   if (index < 0) {
    1903               0 :     return nsnull;
    1904                 :   }
    1905                 : 
    1906               0 :   PRUint32 i, count = children.ChildCount();
    1907               0 :   for (i = (PRUint32)index + 1; i < count; ++i) {
    1908               0 :     nsIContent* child = children.ChildAt(i);
    1909               0 :     if (child->IsElement()) {
    1910               0 :       return child;
    1911                 :     }
    1912                 :   }
    1913                 :   
    1914               0 :   return nsnull;
    1915                 : }
    1916                 : 
    1917                 : NS_IMETHODIMP
    1918               2 : nsNSElementTearoff::GetFirstElementChild(nsIDOMElement** aResult)
    1919                 : {
    1920               2 :   *aResult = nsnull;
    1921                 : 
    1922               2 :   nsIContent *result = mContent->GetFirstElementChild();
    1923                 : 
    1924               2 :   return result ? CallQueryInterface(result, aResult) : NS_OK;
    1925                 : }
    1926                 : 
    1927                 : NS_IMETHODIMP
    1928               0 : nsNSElementTearoff::GetLastElementChild(nsIDOMElement** aResult)
    1929                 : {
    1930               0 :   *aResult = nsnull;
    1931                 : 
    1932               0 :   nsIContent *result = mContent->GetLastElementChild();
    1933                 : 
    1934               0 :   return result ? CallQueryInterface(result, aResult) : NS_OK;
    1935                 : }
    1936                 : 
    1937                 : NS_IMETHODIMP
    1938               0 : nsNSElementTearoff::GetPreviousElementSibling(nsIDOMElement** aResult)
    1939                 : {
    1940               0 :   *aResult = nsnull;
    1941                 : 
    1942               0 :   nsIContent *result = mContent->GetPreviousElementSibling();
    1943                 : 
    1944               0 :   return result ? CallQueryInterface(result, aResult) : NS_OK;
    1945                 : }
    1946                 : 
    1947                 : NS_IMETHODIMP
    1948               0 : nsNSElementTearoff::GetNextElementSibling(nsIDOMElement** aResult)
    1949                 : {
    1950               0 :   *aResult = nsnull;
    1951                 : 
    1952               0 :   nsIContent *result = mContent->GetNextElementSibling();
    1953                 : 
    1954               0 :   return result ? CallQueryInterface(result, aResult) : NS_OK;
    1955                 : }
    1956                 : 
    1957                 : nsContentList*
    1958             167 : nsGenericElement::GetChildrenList()
    1959                 : {
    1960             167 :   nsGenericElement::nsDOMSlots *slots = DOMSlots();
    1961                 : 
    1962             167 :   if (!slots->mChildrenList) {
    1963                 :     slots->mChildrenList = new nsContentList(this, kNameSpaceID_Wildcard, 
    1964                 :                                              nsGkAtoms::_asterix, nsGkAtoms::_asterix,
    1965              75 :                                              false);
    1966                 :   }
    1967                 : 
    1968             167 :   return slots->mChildrenList;
    1969                 : }
    1970                 : 
    1971                 : NS_IMETHODIMP
    1972               0 : nsNSElementTearoff::GetChildElementCount(PRUint32* aResult)
    1973                 : {
    1974               0 :   return mContent->GetChildElementCount(aResult);
    1975                 : }
    1976                 : 
    1977                 : NS_IMETHODIMP
    1978               0 : nsNSElementTearoff::GetChildren(nsIDOMNodeList** aResult)
    1979                 : {
    1980               0 :   return mContent->GetChildren(aResult);
    1981                 : }
    1982                 : 
    1983                 : nsDOMTokenList*
    1984               0 : nsGenericElement::GetClassList(nsresult *aResult)
    1985                 : {
    1986               0 :   *aResult = NS_ERROR_OUT_OF_MEMORY;
    1987                 : 
    1988               0 :   nsGenericElement::nsDOMSlots *slots = DOMSlots();
    1989                 : 
    1990               0 :   if (!slots->mClassList) {
    1991               0 :     nsCOMPtr<nsIAtom> classAttr = GetClassAttributeName();
    1992               0 :     if (!classAttr) {
    1993               0 :       *aResult = NS_OK;
    1994                 : 
    1995               0 :       return nsnull;
    1996                 :     }
    1997                 : 
    1998               0 :     slots->mClassList = new nsDOMTokenList(this, classAttr);
    1999               0 :     NS_ENSURE_TRUE(slots->mClassList, nsnull);
    2000                 :   }
    2001                 : 
    2002               0 :   *aResult = NS_OK;
    2003                 : 
    2004               0 :   return slots->mClassList;
    2005                 : }
    2006                 : 
    2007                 : NS_IMETHODIMP
    2008               0 : nsNSElementTearoff::GetClassList(nsIDOMDOMTokenList** aResult)
    2009                 : {
    2010               0 :   *aResult = nsnull;
    2011                 : 
    2012                 :   nsresult rv;
    2013               0 :   nsIDOMDOMTokenList* list = mContent->GetClassList(&rv);
    2014               0 :   NS_ENSURE_TRUE(list, rv);
    2015                 : 
    2016               0 :   NS_ADDREF(*aResult = list);
    2017                 : 
    2018               0 :   return NS_OK;
    2019                 : }
    2020                 : 
    2021                 : void
    2022               0 : nsGenericElement::SetCapture(bool aRetargetToElement)
    2023                 : {
    2024                 :   // If there is already an active capture, ignore this request. This would
    2025                 :   // occur if a splitter, frame resizer, etc had already captured and we don't
    2026                 :   // want to override those.
    2027               0 :   if (nsIPresShell::GetCapturingContent())
    2028               0 :     return;
    2029                 : 
    2030                 :   nsIPresShell::SetCapturingContent(this, CAPTURE_PREVENTDRAG |
    2031               0 :     (aRetargetToElement ? CAPTURE_RETARGETTOELEMENT : 0));
    2032                 : }
    2033                 : 
    2034                 : NS_IMETHODIMP
    2035               0 : nsNSElementTearoff::SetCapture(bool aRetargetToElement)
    2036                 : {
    2037               0 :   mContent->SetCapture(aRetargetToElement);
    2038                 : 
    2039               0 :   return NS_OK;
    2040                 : }
    2041                 : 
    2042                 : void
    2043               0 : nsGenericElement::ReleaseCapture()
    2044                 : {
    2045               0 :   if (nsIPresShell::GetCapturingContent() == this) {
    2046               0 :     nsIPresShell::SetCapturingContent(nsnull, 0);
    2047                 :   }
    2048               0 : }
    2049                 : 
    2050                 : NS_IMETHODIMP
    2051               0 : nsNSElementTearoff::ReleaseCapture()
    2052                 : {
    2053               0 :   mContent->ReleaseCapture();
    2054                 : 
    2055               0 :   return NS_OK;
    2056                 : }
    2057                 : 
    2058                 : //----------------------------------------------------------------------
    2059                 : 
    2060                 : 
    2061            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsNSElementTearoff, mContent)
    2062                 : 
    2063               4 : NS_INTERFACE_MAP_BEGIN(nsNSElementTearoff)
    2064               4 :   NS_INTERFACE_MAP_ENTRY(nsIDOMNSElement)
    2065               2 :   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsNSElementTearoff)
    2066               0 : NS_INTERFACE_MAP_END_AGGREGATED(mContent)
    2067                 : 
    2068               4 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNSElementTearoff)
    2069               6 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNSElementTearoff)
    2070                 : 
    2071                 : NS_IMETHODIMP
    2072               0 : nsNSElementTearoff::GetElementsByClassName(const nsAString& aClasses,
    2073                 :                                            nsIDOMNodeList** aReturn)
    2074                 : {
    2075               0 :   return mContent->GetElementsByClassName(aClasses, aReturn);
    2076                 : }
    2077                 : 
    2078                 : nsIFrame*
    2079               0 : nsGenericElement::GetStyledFrame()
    2080                 : {
    2081               0 :   nsIFrame *frame = GetPrimaryFrame(Flush_Layout);
    2082               0 :   return frame ? nsLayoutUtils::GetStyleFrame(frame) : nsnull;
    2083                 : }
    2084                 : 
    2085                 : void
    2086               0 : nsGenericElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent)
    2087                 : {
    2088               0 :   *aOffsetParent = nsnull;
    2089               0 :   aRect = nsRect();
    2090                 : 
    2091               0 :   nsIFrame* frame = GetStyledFrame();
    2092               0 :   if (!frame) {
    2093               0 :     return;
    2094                 :   }
    2095                 : 
    2096               0 :   nsPoint origin = frame->GetPosition();
    2097               0 :   aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
    2098               0 :   aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
    2099                 : 
    2100                 :   // Get the union of all rectangles in this and continuation frames.
    2101                 :   // It doesn't really matter what we use as aRelativeTo here, since
    2102                 :   // we only care about the size. Using 'parent' might make things
    2103                 :   // a bit faster by speeding up the internal GetOffsetTo operations.
    2104               0 :   nsIFrame* parent = frame->GetParent() ? frame->GetParent() : frame;
    2105               0 :   nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, parent);
    2106               0 :   aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
    2107               0 :   aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
    2108                 : }
    2109                 : 
    2110                 : nsIScrollableFrame*
    2111               0 : nsGenericElement::GetScrollFrame(nsIFrame **aStyledFrame)
    2112                 : {
    2113                 :   // it isn't clear what to return for SVG nodes, so just return nothing
    2114               0 :   if (IsSVG()) {
    2115               0 :     if (aStyledFrame) {
    2116               0 :       *aStyledFrame = nsnull;
    2117                 :     }
    2118               0 :     return nsnull;
    2119                 :   }
    2120                 : 
    2121               0 :   nsIFrame* frame = GetStyledFrame();
    2122                 : 
    2123               0 :   if (aStyledFrame) {
    2124               0 :     *aStyledFrame = frame;
    2125                 :   }
    2126               0 :   if (!frame) {
    2127               0 :     return nsnull;
    2128                 :   }
    2129                 : 
    2130                 :   // menu frames implement GetScrollTargetFrame but we don't want
    2131                 :   // to use it here.  Similar for comboboxes.
    2132               0 :   if (frame->GetType() != nsGkAtoms::menuFrame &&
    2133               0 :       frame->GetType() != nsGkAtoms::comboboxControlFrame) {
    2134               0 :     nsIScrollableFrame *scrollFrame = frame->GetScrollTargetFrame();
    2135               0 :     if (scrollFrame)
    2136               0 :       return scrollFrame;
    2137                 :   }
    2138                 : 
    2139               0 :   nsIDocument* doc = OwnerDoc();
    2140               0 :   bool quirksMode = doc->GetCompatibilityMode() == eCompatibility_NavQuirks;
    2141                 :   Element* elementWithRootScrollInfo =
    2142               0 :     quirksMode ? doc->GetBodyElement() : doc->GetRootElement();
    2143               0 :   if (this == elementWithRootScrollInfo) {
    2144                 :     // In quirks mode, the scroll info for the body element should map to the
    2145                 :     // root scrollable frame.
    2146                 :     // In strict mode, the scroll info for the root element should map to the
    2147                 :     // the root scrollable frame.
    2148               0 :     return frame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
    2149                 :   }
    2150                 : 
    2151               0 :   return nsnull;
    2152                 : }
    2153                 : 
    2154                 : PRInt32
    2155               0 : nsGenericElement::GetScrollTop()
    2156                 : {
    2157               0 :   nsIScrollableFrame* sf = GetScrollFrame();
    2158                 : 
    2159                 :   return sf ?
    2160               0 :          nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollPosition().y) :
    2161               0 :          0;
    2162                 : }
    2163                 : 
    2164                 : NS_IMETHODIMP
    2165               0 : nsNSElementTearoff::GetScrollTop(PRInt32* aScrollTop)
    2166                 : {
    2167               0 :   *aScrollTop = mContent->GetScrollTop();
    2168                 : 
    2169               0 :   return NS_OK;
    2170                 : }
    2171                 : 
    2172                 : void
    2173               0 : nsGenericElement::SetScrollTop(PRInt32 aScrollTop)
    2174                 : {
    2175               0 :   nsIScrollableFrame* sf = GetScrollFrame();
    2176               0 :   if (sf) {
    2177               0 :     nsPoint pt = sf->GetScrollPosition();
    2178               0 :     pt.y = nsPresContext::CSSPixelsToAppUnits(aScrollTop);
    2179               0 :     sf->ScrollTo(pt, nsIScrollableFrame::INSTANT);
    2180                 :   }
    2181               0 : }
    2182                 : 
    2183                 : NS_IMETHODIMP
    2184               0 : nsNSElementTearoff::SetScrollTop(PRInt32 aScrollTop)
    2185                 : {
    2186               0 :   mContent->SetScrollTop(aScrollTop);
    2187                 : 
    2188               0 :   return NS_OK;
    2189                 : }
    2190                 : 
    2191                 : PRInt32
    2192               0 : nsGenericElement::GetScrollLeft()
    2193                 : {
    2194               0 :   nsIScrollableFrame* sf = GetScrollFrame();
    2195                 : 
    2196                 :   return sf ?
    2197               0 :          nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollPosition().x) :
    2198               0 :          0;
    2199                 : }
    2200                 : 
    2201                 : NS_IMETHODIMP
    2202               0 : nsNSElementTearoff::GetScrollLeft(PRInt32* aScrollLeft)
    2203                 : {
    2204               0 :   *aScrollLeft = mContent->GetScrollLeft();
    2205                 : 
    2206               0 :   return NS_OK;
    2207                 : }
    2208                 : 
    2209                 : void
    2210               0 : nsGenericElement::SetScrollLeft(PRInt32 aScrollLeft)
    2211                 : {
    2212               0 :   nsIScrollableFrame* sf = GetScrollFrame();
    2213               0 :   if (sf) {
    2214               0 :     nsPoint pt = sf->GetScrollPosition();
    2215               0 :     pt.x = nsPresContext::CSSPixelsToAppUnits(aScrollLeft);
    2216               0 :     sf->ScrollTo(pt, nsIScrollableFrame::INSTANT);
    2217                 :   }
    2218               0 : }
    2219                 : 
    2220                 : NS_IMETHODIMP
    2221               0 : nsNSElementTearoff::SetScrollLeft(PRInt32 aScrollLeft)
    2222                 : {
    2223               0 :   mContent->SetScrollLeft(aScrollLeft);
    2224                 : 
    2225               0 :   return NS_OK;
    2226                 : }
    2227                 : 
    2228                 : PRInt32
    2229               0 : nsGenericElement::GetScrollHeight()
    2230                 : {
    2231               0 :   if (IsSVG())
    2232               0 :     return 0;
    2233                 : 
    2234               0 :   nsIScrollableFrame* sf = GetScrollFrame();
    2235               0 :   if (!sf) {
    2236               0 :     nsRect rcFrame;
    2237               0 :     nsCOMPtr<nsIContent> parent;
    2238               0 :     GetOffsetRect(rcFrame, getter_AddRefs(parent));
    2239               0 :     return rcFrame.height;
    2240                 :   }
    2241                 : 
    2242               0 :   nscoord height = sf->GetScrollRange().height + sf->GetScrollPortRect().height;
    2243               0 :   return nsPresContext::AppUnitsToIntCSSPixels(height);
    2244                 : }
    2245                 : 
    2246                 : NS_IMETHODIMP
    2247               0 : nsNSElementTearoff::GetScrollHeight(PRInt32* aScrollHeight)
    2248                 : {
    2249               0 :   *aScrollHeight = mContent->GetScrollHeight();
    2250                 : 
    2251               0 :   return NS_OK;
    2252                 : }
    2253                 : 
    2254                 : PRInt32
    2255               0 : nsGenericElement::GetScrollWidth()
    2256                 : {
    2257               0 :   if (IsSVG())
    2258               0 :     return 0;
    2259                 : 
    2260               0 :   nsIScrollableFrame* sf = GetScrollFrame();
    2261               0 :   if (!sf) {
    2262               0 :     nsRect rcFrame;
    2263               0 :     nsCOMPtr<nsIContent> parent;
    2264               0 :     GetOffsetRect(rcFrame, getter_AddRefs(parent));
    2265               0 :     return rcFrame.width;
    2266                 :   }
    2267                 : 
    2268               0 :   nscoord width = sf->GetScrollRange().width + sf->GetScrollPortRect().width;
    2269               0 :   return nsPresContext::AppUnitsToIntCSSPixels(width);
    2270                 : }
    2271                 : 
    2272                 : NS_IMETHODIMP
    2273               0 : nsNSElementTearoff::GetScrollWidth(PRInt32 *aScrollWidth)
    2274                 : {
    2275               0 :   *aScrollWidth = mContent->GetScrollWidth();
    2276                 : 
    2277               0 :   return NS_OK;
    2278                 : }
    2279                 : 
    2280                 : nsRect
    2281               0 : nsGenericElement::GetClientAreaRect()
    2282                 : {
    2283                 :   nsIFrame* styledFrame;
    2284               0 :   nsIScrollableFrame* sf = GetScrollFrame(&styledFrame);
    2285                 : 
    2286               0 :   if (sf) {
    2287               0 :     return sf->GetScrollPortRect();
    2288                 :   }
    2289                 : 
    2290               0 :   if (styledFrame &&
    2291               0 :       (styledFrame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE ||
    2292               0 :        styledFrame->IsFrameOfType(nsIFrame::eReplaced))) {
    2293                 :     // Special case code to make client area work even when there isn't
    2294                 :     // a scroll view, see bug 180552, bug 227567.
    2295               0 :     return styledFrame->GetPaddingRect() - styledFrame->GetPositionIgnoringScrolling();
    2296                 :   }
    2297                 : 
    2298                 :   // SVG nodes reach here and just return 0
    2299               0 :   return nsRect(0, 0, 0, 0);
    2300                 : }
    2301                 : 
    2302                 : NS_IMETHODIMP
    2303               0 : nsNSElementTearoff::GetClientTop(PRInt32 *aClientTop)
    2304                 : {
    2305               0 :   *aClientTop = mContent->GetClientTop();
    2306               0 :   return NS_OK;
    2307                 : }
    2308                 : 
    2309                 : NS_IMETHODIMP
    2310               0 : nsNSElementTearoff::GetClientLeft(PRInt32 *aClientLeft)
    2311                 : {
    2312               0 :   *aClientLeft = mContent->GetClientLeft();
    2313               0 :   return NS_OK;
    2314                 : }
    2315                 : 
    2316                 : NS_IMETHODIMP
    2317               0 : nsNSElementTearoff::GetClientHeight(PRInt32 *aClientHeight)
    2318                 : {
    2319               0 :   *aClientHeight = mContent->GetClientHeight();
    2320               0 :   return NS_OK;
    2321                 : }
    2322                 : 
    2323                 : NS_IMETHODIMP
    2324               0 : nsNSElementTearoff::GetClientWidth(PRInt32 *aClientWidth)
    2325                 : {
    2326               0 :   *aClientWidth = mContent->GetClientWidth();
    2327               0 :   return NS_OK;
    2328                 : }
    2329                 : 
    2330                 : nsresult
    2331               0 : nsGenericElement::GetBoundingClientRect(nsIDOMClientRect** aResult)
    2332                 : {
    2333                 :   // Weak ref, since we addref it below
    2334               0 :   nsClientRect* rect = new nsClientRect();
    2335               0 :   if (!rect)
    2336               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2337                 : 
    2338               0 :   NS_ADDREF(*aResult = rect);
    2339                 :   
    2340               0 :   nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
    2341               0 :   if (!frame) {
    2342                 :     // display:none, perhaps? Return the empty rect
    2343               0 :     return NS_OK;
    2344                 :   }
    2345                 : 
    2346                 :   nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(frame,
    2347                 :           nsLayoutUtils::GetContainingBlockForClientRect(frame),
    2348               0 :           nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
    2349               0 :   rect->SetLayoutRect(r);
    2350               0 :   return NS_OK;
    2351                 : }
    2352                 : 
    2353                 : NS_IMETHODIMP
    2354               0 : nsNSElementTearoff::GetBoundingClientRect(nsIDOMClientRect** aResult)
    2355                 : {
    2356               0 :   return mContent->GetBoundingClientRect(aResult);
    2357                 : }
    2358                 : 
    2359                 : nsresult
    2360               0 : nsGenericElement::GetElementsByClassName(const nsAString& aClasses,
    2361                 :                                          nsIDOMNodeList** aReturn)
    2362                 : {
    2363               0 :   return nsContentUtils::GetElementsByClassName(this, aClasses, aReturn);
    2364                 : }
    2365                 : 
    2366                 : nsresult
    2367               0 : nsGenericElement::GetClientRects(nsIDOMClientRectList** aResult)
    2368                 : {
    2369               0 :   *aResult = nsnull;
    2370                 : 
    2371               0 :   nsRefPtr<nsClientRectList> rectList = new nsClientRectList(this);
    2372                 : 
    2373               0 :   nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
    2374               0 :   if (!frame) {
    2375                 :     // display:none, perhaps? Return an empty list
    2376               0 :     *aResult = rectList.forget().get();
    2377               0 :     return NS_OK;
    2378                 :   }
    2379                 : 
    2380               0 :   nsLayoutUtils::RectListBuilder builder(rectList);
    2381                 :   nsLayoutUtils::GetAllInFlowRects(frame,
    2382                 :           nsLayoutUtils::GetContainingBlockForClientRect(frame), &builder,
    2383               0 :           nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
    2384               0 :   if (NS_FAILED(builder.mRV))
    2385               0 :     return builder.mRV;
    2386               0 :   *aResult = rectList.forget().get();
    2387               0 :   return NS_OK;
    2388                 : }
    2389                 : 
    2390                 : NS_IMETHODIMP
    2391               0 : nsNSElementTearoff::GetClientRects(nsIDOMClientRectList** aResult)
    2392                 : {
    2393               0 :   return mContent->GetClientRects(aResult);
    2394                 : }
    2395                 : 
    2396                 : //----------------------------------------------------------------------
    2397                 : 
    2398                 : 
    2399             233 : NS_IMPL_ISUPPORTS1(nsNodeWeakReference,
    2400                 :                    nsIWeakReference)
    2401                 : 
    2402              23 : nsNodeWeakReference::~nsNodeWeakReference()
    2403                 : {
    2404              23 :   if (mNode) {
    2405              23 :     NS_ASSERTION(mNode->GetSlots() &&
    2406                 :                  mNode->GetSlots()->mWeakReference == this,
    2407                 :                  "Weak reference has wrong value");
    2408              23 :     mNode->GetSlots()->mWeakReference = nsnull;
    2409                 :   }
    2410              23 : }
    2411                 : 
    2412                 : NS_IMETHODIMP
    2413               0 : nsNodeWeakReference::QueryReferent(const nsIID& aIID, void** aInstancePtr)
    2414                 : {
    2415               0 :   return mNode ? mNode->QueryInterface(aIID, aInstancePtr) :
    2416               0 :                  NS_ERROR_NULL_POINTER;
    2417                 : }
    2418                 : 
    2419                 : 
    2420            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsNodeSupportsWeakRefTearoff, mNode)
    2421                 : 
    2422               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNodeSupportsWeakRefTearoff)
    2423               0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    2424               0 : NS_INTERFACE_MAP_END_AGGREGATED(mNode)
    2425                 : 
    2426              42 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeSupportsWeakRefTearoff)
    2427              84 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNodeSupportsWeakRefTearoff)
    2428                 : 
    2429                 : NS_IMETHODIMP
    2430              42 : nsNodeSupportsWeakRefTearoff::GetWeakReference(nsIWeakReference** aInstancePtr)
    2431                 : {
    2432              42 :   nsINode::nsSlots* slots = mNode->GetSlots();
    2433              42 :   NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY);
    2434                 : 
    2435              42 :   if (!slots->mWeakReference) {
    2436              46 :     slots->mWeakReference = new nsNodeWeakReference(mNode);
    2437              23 :     NS_ENSURE_TRUE(slots->mWeakReference, NS_ERROR_OUT_OF_MEMORY);
    2438                 :   }
    2439                 : 
    2440              42 :   NS_ADDREF(*aInstancePtr = slots->mWeakReference);
    2441                 : 
    2442              42 :   return NS_OK;
    2443                 : }
    2444                 : 
    2445                 : //----------------------------------------------------------------------
    2446                 : 
    2447            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsNodeSelectorTearoff, mNode)
    2448                 : 
    2449               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNodeSelectorTearoff)
    2450               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMNodeSelector)
    2451               0 : NS_INTERFACE_MAP_END_AGGREGATED(mNode)
    2452                 : 
    2453               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeSelectorTearoff)
    2454               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNodeSelectorTearoff)
    2455                 : 
    2456                 : NS_IMETHODIMP
    2457               0 : nsNodeSelectorTearoff::QuerySelector(const nsAString& aSelector,
    2458                 :                                      nsIDOMElement **aReturn)
    2459                 : {
    2460                 :   nsresult rv;
    2461               0 :   nsIContent* result = nsGenericElement::doQuerySelector(mNode, aSelector, &rv);
    2462               0 :   return result ? CallQueryInterface(result, aReturn) : rv;
    2463                 : }
    2464                 : 
    2465                 : NS_IMETHODIMP
    2466               0 : nsNodeSelectorTearoff::QuerySelectorAll(const nsAString& aSelector,
    2467                 :                                         nsIDOMNodeList **aReturn)
    2468                 : {
    2469               0 :   return nsGenericElement::doQuerySelectorAll(mNode, aSelector, aReturn);
    2470                 : }
    2471                 : 
    2472                 : //----------------------------------------------------------------------
    2473                 : 
    2474            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsTouchEventReceiverTearoff, mElement)
    2475                 : 
    2476               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTouchEventReceiverTearoff)
    2477               0 :   NS_INTERFACE_MAP_ENTRY(nsITouchEventReceiver)
    2478               0 : NS_INTERFACE_MAP_END_AGGREGATED(mElement)
    2479                 : 
    2480               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTouchEventReceiverTearoff)
    2481               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTouchEventReceiverTearoff)
    2482                 : 
    2483                 : //----------------------------------------------------------------------
    2484                 : 
    2485            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsInlineEventHandlersTearoff, mElement)
    2486                 : 
    2487               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsInlineEventHandlersTearoff)
    2488               0 :   NS_INTERFACE_MAP_ENTRY(nsIInlineEventHandlers)
    2489               0 : NS_INTERFACE_MAP_END_AGGREGATED(mElement)
    2490                 : 
    2491               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsInlineEventHandlersTearoff)
    2492               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsInlineEventHandlersTearoff)
    2493                 : 
    2494                 : //----------------------------------------------------------------------
    2495            3315 : nsGenericElement::nsDOMSlots::nsDOMSlots()
    2496                 :   : nsINode::nsSlots(),
    2497                 :     mDataset(nsnull),
    2498            3315 :     mBindingParent(nsnull)
    2499                 : {
    2500            3315 : }
    2501                 : 
    2502            9936 : nsGenericElement::nsDOMSlots::~nsDOMSlots()
    2503                 : {
    2504            3315 :   if (mAttributeMap) {
    2505               0 :     mAttributeMap->DropReference();
    2506                 :   }
    2507                 : 
    2508            3315 :   if (mClassList) {
    2509               0 :     mClassList->DropReference();
    2510                 :   }
    2511           13242 : }
    2512                 : 
    2513                 : void
    2514            3503 : nsGenericElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL)
    2515                 : {
    2516            3503 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mStyle");
    2517            3503 :   cb.NoteXPCOMChild(mStyle.get());
    2518                 : 
    2519            3503 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mSMILOverrideStyle");
    2520            3503 :   cb.NoteXPCOMChild(mSMILOverrideStyle.get());
    2521                 : 
    2522            3503 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mAttributeMap");
    2523            3503 :   cb.NoteXPCOMChild(mAttributeMap.get());
    2524                 : 
    2525            3503 :   if (aIsXUL) {
    2526               9 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mControllers");
    2527               9 :     cb.NoteXPCOMChild(mControllers);
    2528                 :   }
    2529                 : 
    2530            3503 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
    2531            3503 :   cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
    2532                 : 
    2533            3503 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
    2534            3503 :   cb.NoteXPCOMChild(mClassList.get());
    2535            3503 : }
    2536                 : 
    2537                 : void
    2538            3315 : nsGenericElement::nsDOMSlots::Unlink(bool aIsXUL)
    2539                 : {
    2540            3315 :   mStyle = nsnull;
    2541            3315 :   mSMILOverrideStyle = nsnull;
    2542            3315 :   if (mAttributeMap) {
    2543             232 :     mAttributeMap->DropReference();
    2544             232 :     mAttributeMap = nsnull;
    2545                 :   }
    2546            3315 :   if (aIsXUL)
    2547               9 :     NS_IF_RELEASE(mControllers);
    2548            3315 :   mChildrenList = nsnull;
    2549            3315 :   if (mClassList) {
    2550               0 :     mClassList->DropReference();
    2551               0 :     mClassList = nsnull;
    2552                 :   }
    2553            3315 : }
    2554                 : 
    2555           38033 : nsGenericElement::nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo)
    2556           38033 :   : Element(aNodeInfo)
    2557                 : {
    2558           38033 :   NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE ||
    2559                 :                     (mNodeInfo->NodeType() ==
    2560                 :                        nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
    2561                 :                      mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
    2562                 :                                        kNameSpaceID_None)),
    2563                 :                     "Bad NodeType in aNodeInfo");
    2564                 : 
    2565                 :   // Set the default scriptID to JS - but skip SetScriptTypeID as it
    2566                 :   // does extra work we know isn't necessary here...
    2567           38033 :   SetFlags((nsIProgrammingLanguage::JAVASCRIPT << NODE_SCRIPT_TYPE_OFFSET));
    2568           38033 :   SetIsElement();
    2569           38033 : }
    2570                 : 
    2571           76062 : nsGenericElement::~nsGenericElement()
    2572                 : {
    2573           38031 :   NS_PRECONDITION(!IsInDoc(),
    2574                 :                   "Please remove this from the document properly");
    2575           38031 :   if (GetParent()) {
    2576               0 :     NS_RELEASE(mParent);
    2577                 :   }
    2578           76062 : }
    2579                 : 
    2580                 : NS_IMETHODIMP
    2581             127 : nsGenericElement::GetNodeName(nsAString& aNodeName)
    2582                 : {
    2583             127 :   aNodeName = NodeName();
    2584             127 :   return NS_OK;
    2585                 : }
    2586                 : 
    2587                 : NS_IMETHODIMP
    2588            4187 : nsGenericElement::GetLocalName(nsAString& aLocalName)
    2589                 : {
    2590            4187 :   aLocalName = LocalName();
    2591            4187 :   return NS_OK;
    2592                 : }
    2593                 : 
    2594                 : NS_IMETHODIMP
    2595               0 : nsGenericElement::GetNodeValue(nsAString& aNodeValue)
    2596                 : {
    2597               0 :   SetDOMStringToNull(aNodeValue);
    2598                 : 
    2599               0 :   return NS_OK;
    2600                 : }
    2601                 : 
    2602                 : NS_IMETHODIMP
    2603               0 : nsGenericElement::SetNodeValue(const nsAString& aNodeValue)
    2604                 : {
    2605                 :   // The DOM spec says that when nodeValue is defined to be null "setting it
    2606                 :   // has no effect", so we don't throw an exception.
    2607               0 :   return NS_OK;
    2608                 : }
    2609                 : 
    2610                 : NS_IMETHODIMP
    2611             215 : nsGenericElement::GetNodeType(PRUint16* aNodeType)
    2612                 : {
    2613             215 :   *aNodeType = NodeType();
    2614             215 :   return NS_OK;
    2615                 : }
    2616                 : 
    2617                 : NS_IMETHODIMP
    2618             984 : nsGenericElement::GetNamespaceURI(nsAString& aNamespaceURI)
    2619                 : {
    2620             984 :   return mNodeInfo->GetNamespaceURI(aNamespaceURI);
    2621                 : }
    2622                 : 
    2623                 : NS_IMETHODIMP
    2624               0 : nsGenericElement::GetPrefix(nsAString& aPrefix)
    2625                 : {
    2626               0 :   mNodeInfo->GetPrefix(aPrefix);
    2627               0 :   return NS_OK;
    2628                 : }
    2629                 : 
    2630                 : nsresult
    2631               0 : nsGenericElement::InternalIsSupported(nsISupports* aObject,
    2632                 :                                       const nsAString& aFeature,
    2633                 :                                       const nsAString& aVersion,
    2634                 :                                       bool* aReturn)
    2635                 : {
    2636               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    2637               0 :   *aReturn = false;
    2638                 : 
    2639                 :   // Convert the incoming UTF16 strings to raw char*'s to save us some
    2640                 :   // code when doing all those string compares.
    2641               0 :   NS_ConvertUTF16toUTF8 feature(aFeature);
    2642               0 :   NS_ConvertUTF16toUTF8 version(aVersion);
    2643                 : 
    2644               0 :   const char *f = feature.get();
    2645               0 :   const char *v = version.get();
    2646                 : 
    2647               0 :   if (PL_strcasecmp(f, "XML") == 0 ||
    2648               0 :       PL_strcasecmp(f, "HTML") == 0) {
    2649               0 :     if (aVersion.IsEmpty() ||
    2650               0 :         PL_strcmp(v, "1.0") == 0 ||
    2651               0 :         PL_strcmp(v, "2.0") == 0) {
    2652               0 :       *aReturn = true;
    2653                 :     }
    2654               0 :   } else if (PL_strcasecmp(f, "Views") == 0 ||
    2655               0 :              PL_strcasecmp(f, "StyleSheets") == 0 ||
    2656               0 :              PL_strcasecmp(f, "Core") == 0 ||
    2657               0 :              PL_strcasecmp(f, "CSS") == 0 ||
    2658               0 :              PL_strcasecmp(f, "CSS2") == 0 ||
    2659               0 :              PL_strcasecmp(f, "Events") == 0 ||
    2660               0 :              PL_strcasecmp(f, "UIEvents") == 0 ||
    2661               0 :              PL_strcasecmp(f, "MouseEvents") == 0 ||
    2662                 :              // Non-standard!
    2663               0 :              PL_strcasecmp(f, "MouseScrollEvents") == 0 ||
    2664               0 :              PL_strcasecmp(f, "HTMLEvents") == 0 ||
    2665               0 :              PL_strcasecmp(f, "Range") == 0 ||
    2666               0 :              PL_strcasecmp(f, "XHTML") == 0) {
    2667               0 :     if (aVersion.IsEmpty() ||
    2668               0 :         PL_strcmp(v, "2.0") == 0) {
    2669               0 :       *aReturn = true;
    2670                 :     }
    2671               0 :   } else if (PL_strcasecmp(f, "XPath") == 0) {
    2672               0 :     if (aVersion.IsEmpty() ||
    2673               0 :         PL_strcmp(v, "3.0") == 0) {
    2674               0 :       *aReturn = true;
    2675                 :     }
    2676               0 :   } else if (PL_strcasecmp(f, "SVGEvents") == 0 ||
    2677               0 :              PL_strcasecmp(f, "SVGZoomEvents") == 0 ||
    2678               0 :              nsSVGFeatures::HasFeature(aObject, aFeature)) {
    2679               0 :     if (aVersion.IsEmpty() ||
    2680               0 :         PL_strcmp(v, "1.0") == 0 ||
    2681               0 :         PL_strcmp(v, "1.1") == 0) {
    2682               0 :       *aReturn = true;
    2683                 :     }
    2684                 :   }
    2685               0 :   else if (NS_SMILEnabled() && PL_strcasecmp(f, "TimeControl") == 0) {
    2686               0 :     if (aVersion.IsEmpty() || PL_strcmp(v, "1.0") == 0) {
    2687               0 :       *aReturn = true;
    2688                 :     }
    2689                 :   }
    2690                 : 
    2691               0 :   return NS_OK;
    2692                 : }
    2693                 : 
    2694                 : NS_IMETHODIMP
    2695               0 : nsGenericElement::IsSupported(const nsAString& aFeature,
    2696                 :                               const nsAString& aVersion,
    2697                 :                               bool* aReturn)
    2698                 : {
    2699               0 :   return InternalIsSupported(this, aFeature, aVersion, aReturn);
    2700                 : }
    2701                 : 
    2702                 : NS_IMETHODIMP
    2703               0 : nsGenericElement::HasAttributes(bool* aReturn)
    2704                 : {
    2705               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    2706                 : 
    2707               0 :   *aReturn = GetAttrCount() > 0;
    2708                 : 
    2709               0 :   return NS_OK;
    2710                 : }
    2711                 : 
    2712                 : NS_IMETHODIMP
    2713            1900 : nsGenericElement::GetAttributes(nsIDOMNamedNodeMap** aAttributes)
    2714                 : {
    2715            1900 :   if (!IsElement()) {
    2716               0 :     *aAttributes = nsnull;
    2717               0 :     return NS_OK;
    2718                 :   }
    2719                 : 
    2720            1900 :   nsDOMSlots *slots = DOMSlots();
    2721                 : 
    2722            1900 :   if (!slots->mAttributeMap) {
    2723             232 :     slots->mAttributeMap = new nsDOMAttributeMap(this);
    2724             232 :     if (!slots->mAttributeMap->Init()) {
    2725               0 :       slots->mAttributeMap = nsnull;
    2726               0 :       return NS_ERROR_FAILURE;
    2727                 :     }
    2728                 :   }
    2729                 : 
    2730            1900 :   NS_ADDREF(*aAttributes = slots->mAttributeMap);
    2731                 : 
    2732            1900 :   return NS_OK;
    2733                 : }
    2734                 : 
    2735                 : nsresult
    2736              11 : nsGenericElement::HasChildNodes(bool* aReturn)
    2737                 : {
    2738              11 :   *aReturn = mAttrsAndChildren.ChildCount() > 0;
    2739                 : 
    2740              11 :   return NS_OK;
    2741                 : }
    2742                 : 
    2743                 : NS_IMETHODIMP
    2744             433 : nsGenericElement::GetTagName(nsAString& aTagName)
    2745                 : {
    2746             433 :   aTagName = NodeName();
    2747             433 :   return NS_OK;
    2748                 : }
    2749                 : 
    2750                 : nsresult
    2751            3386 : nsGenericElement::GetAttribute(const nsAString& aName,
    2752                 :                                nsAString& aReturn)
    2753                 : {
    2754            3386 :   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
    2755                 : 
    2756            3386 :   if (!name) {
    2757             851 :     if (mNodeInfo->NamespaceID() == kNameSpaceID_XUL) {
    2758                 :       // XXX should be SetDOMStringToNull(aReturn);
    2759                 :       // See bug 232598
    2760               0 :       aReturn.Truncate();
    2761                 :     }
    2762                 :     else {
    2763             851 :       SetDOMStringToNull(aReturn);
    2764                 :     }
    2765                 : 
    2766             851 :     return NS_OK;
    2767                 :   }
    2768                 : 
    2769            2535 :   GetAttr(name->NamespaceID(), name->LocalName(), aReturn);
    2770                 : 
    2771            2535 :   return NS_OK;
    2772                 : }
    2773                 : 
    2774                 : nsresult
    2775            1847 : nsGenericElement::SetAttribute(const nsAString& aName,
    2776                 :                                const nsAString& aValue)
    2777                 : {
    2778            1847 :   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
    2779                 : 
    2780            1847 :   if (!name) {
    2781            1845 :     nsresult rv = nsContentUtils::CheckQName(aName, false);
    2782            1845 :     NS_ENSURE_SUCCESS(rv, rv);
    2783                 : 
    2784            3690 :     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
    2785            1845 :     NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
    2786                 : 
    2787            1845 :     return SetAttr(kNameSpaceID_None, nameAtom, aValue, true);
    2788                 :   }
    2789                 : 
    2790                 :   return SetAttr(name->NamespaceID(), name->LocalName(), name->GetPrefix(),
    2791               2 :                  aValue, true);
    2792                 : }
    2793                 : 
    2794                 : nsresult
    2795               0 : nsGenericElement::RemoveAttribute(const nsAString& aName)
    2796                 : {
    2797               0 :   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
    2798                 : 
    2799               0 :   if (!name) {
    2800                 :     // If there is no canonical nsAttrName for this attribute name, then the
    2801                 :     // attribute does not exist and we can't get its namespace ID and
    2802                 :     // local name below, so we return early.
    2803               0 :     return NS_OK;
    2804                 :   }
    2805                 : 
    2806                 :   // Hold a strong reference here so that the atom or nodeinfo doesn't go
    2807                 :   // away during UnsetAttr. If it did UnsetAttr would be left with a
    2808                 :   // dangling pointer as argument without knowing it.
    2809               0 :   nsAttrName tmp(*name);
    2810                 : 
    2811               0 :   return UnsetAttr(name->NamespaceID(), name->LocalName(), true);
    2812                 : }
    2813                 : 
    2814                 : nsresult
    2815               0 : nsGenericElement::GetAttributeNode(const nsAString& aName,
    2816                 :                                    nsIDOMAttr** aReturn)
    2817                 : {
    2818               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    2819               0 :   *aReturn = nsnull;
    2820                 : 
    2821               0 :   nsIDocument* document = OwnerDoc();
    2822               0 :   if (document) {
    2823               0 :     document->WarnOnceAbout(nsIDocument::eGetAttributeNode);
    2824                 :   }
    2825                 : 
    2826               0 :   nsCOMPtr<nsIDOMNamedNodeMap> map;
    2827               0 :   nsresult rv = GetAttributes(getter_AddRefs(map));
    2828               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2829                 : 
    2830               0 :   nsCOMPtr<nsIDOMNode> node;
    2831               0 :   rv = map->GetNamedItem(aName, getter_AddRefs(node));
    2832                 : 
    2833               0 :   if (NS_SUCCEEDED(rv) && node) {
    2834               0 :     rv = CallQueryInterface(node, aReturn);
    2835                 :   }
    2836                 : 
    2837               0 :   return rv;
    2838                 : }
    2839                 : 
    2840                 : nsresult
    2841               2 : nsGenericElement::SetAttributeNode(nsIDOMAttr* aAttribute,
    2842                 :                                    nsIDOMAttr** aReturn)
    2843                 : {
    2844               2 :   NS_ENSURE_ARG_POINTER(aReturn);
    2845               2 :   NS_ENSURE_ARG_POINTER(aAttribute);
    2846                 : 
    2847               2 :   *aReturn = nsnull;
    2848                 : 
    2849               2 :   OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNode);
    2850                 : 
    2851               4 :   nsCOMPtr<nsIDOMNamedNodeMap> map;
    2852               2 :   nsresult rv = GetAttributes(getter_AddRefs(map));
    2853               2 :   NS_ENSURE_SUCCESS(rv, rv);
    2854                 : 
    2855               4 :   nsCOMPtr<nsIDOMNode> returnNode;
    2856               2 :   rv = map->SetNamedItem(aAttribute, getter_AddRefs(returnNode));
    2857               2 :   NS_ENSURE_SUCCESS(rv, rv);
    2858                 : 
    2859               2 :   if (returnNode) {
    2860               0 :     rv = CallQueryInterface(returnNode, aReturn);
    2861                 :   }
    2862                 : 
    2863               2 :   return rv;
    2864                 : }
    2865                 : 
    2866                 : nsresult
    2867               0 : nsGenericElement::RemoveAttributeNode(nsIDOMAttr* aAttribute,
    2868                 :                                       nsIDOMAttr** aReturn)
    2869                 : {
    2870               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    2871               0 :   NS_ENSURE_ARG_POINTER(aAttribute);
    2872                 : 
    2873               0 :   *aReturn = nsnull;
    2874                 : 
    2875               0 :   OwnerDoc()->WarnOnceAbout(nsIDocument::eRemoveAttributeNode);
    2876                 : 
    2877               0 :   nsCOMPtr<nsIDOMNamedNodeMap> map;
    2878               0 :   nsresult rv = GetAttributes(getter_AddRefs(map));
    2879               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2880                 : 
    2881               0 :   nsAutoString name;
    2882                 : 
    2883               0 :   rv = aAttribute->GetName(name);
    2884               0 :   if (NS_SUCCEEDED(rv)) {
    2885               0 :     nsCOMPtr<nsIDOMNode> node;
    2886               0 :     rv = map->RemoveNamedItem(name, getter_AddRefs(node));
    2887                 : 
    2888               0 :     if (NS_SUCCEEDED(rv) && node) {
    2889               0 :       rv = CallQueryInterface(node, aReturn);
    2890                 :     }
    2891                 :   }
    2892                 : 
    2893               0 :   return rv;
    2894                 : }
    2895                 : 
    2896                 : nsresult
    2897            3103 : nsGenericElement::GetElementsByTagName(const nsAString& aTagname,
    2898                 :                                        nsIDOMNodeList** aReturn)
    2899                 : {
    2900                 :   nsContentList *list = NS_GetContentList(this, kNameSpaceID_Unknown, 
    2901            3103 :                                           aTagname).get();
    2902                 : 
    2903                 :   // transfer ref to aReturn
    2904            3103 :   *aReturn = list;
    2905            3103 :   return NS_OK;
    2906                 : }
    2907                 : 
    2908                 : nsresult
    2909               0 : nsGenericElement::GetAttributeNS(const nsAString& aNamespaceURI,
    2910                 :                                  const nsAString& aLocalName,
    2911                 :                                  nsAString& aReturn)
    2912                 : {
    2913                 :   PRInt32 nsid =
    2914               0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
    2915                 : 
    2916               0 :   if (nsid == kNameSpaceID_Unknown) {
    2917                 :     // Unknown namespace means no attribute.
    2918               0 :     SetDOMStringToNull(aReturn);
    2919               0 :     return NS_OK;
    2920                 :   }
    2921                 : 
    2922               0 :   nsCOMPtr<nsIAtom> name = do_GetAtom(aLocalName);
    2923               0 :   bool hasAttr = GetAttr(nsid, name, aReturn);
    2924               0 :   if (!hasAttr) {
    2925               0 :     SetDOMStringToNull(aReturn);
    2926                 :   }
    2927                 : 
    2928               0 :   return NS_OK;
    2929                 : }
    2930                 : 
    2931                 : nsresult
    2932              26 : nsGenericElement::SetAttributeNS(const nsAString& aNamespaceURI,
    2933                 :                                  const nsAString& aQualifiedName,
    2934                 :                                  const nsAString& aValue)
    2935                 : {
    2936              52 :   nsCOMPtr<nsINodeInfo> ni;
    2937                 :   nsresult rv =
    2938                 :     nsContentUtils::GetNodeInfoFromQName(aNamespaceURI, aQualifiedName,
    2939                 :                                          mNodeInfo->NodeInfoManager(),
    2940                 :                                          nsIDOMNode::ATTRIBUTE_NODE,
    2941              26 :                                          getter_AddRefs(ni));
    2942              26 :   NS_ENSURE_SUCCESS(rv, rv);
    2943                 : 
    2944                 :   return SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(),
    2945              26 :                  aValue, true);
    2946                 : }
    2947                 : 
    2948                 : nsresult
    2949               0 : nsGenericElement::RemoveAttributeNS(const nsAString& aNamespaceURI,
    2950                 :                                     const nsAString& aLocalName)
    2951                 : {
    2952               0 :   nsCOMPtr<nsIAtom> name = do_GetAtom(aLocalName);
    2953                 :   PRInt32 nsid =
    2954               0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
    2955                 : 
    2956               0 :   if (nsid == kNameSpaceID_Unknown) {
    2957                 :     // If the namespace ID is unknown, it means there can't possibly be an
    2958                 :     // existing attribute. We would need a known namespace ID to pass into
    2959                 :     // UnsetAttr, so we return early if we don't have one.
    2960               0 :     return NS_OK;
    2961                 :   }
    2962                 : 
    2963               0 :   UnsetAttr(nsid, name, true);
    2964                 : 
    2965               0 :   return NS_OK;
    2966                 : }
    2967                 : 
    2968                 : nsresult
    2969               0 : nsGenericElement::GetAttributeNodeNS(const nsAString& aNamespaceURI,
    2970                 :                                      const nsAString& aLocalName,
    2971                 :                                      nsIDOMAttr** aReturn)
    2972                 : {
    2973               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    2974               0 :   *aReturn = nsnull;
    2975                 : 
    2976               0 :   OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNodeNS);
    2977                 : 
    2978               0 :   return GetAttributeNodeNSInternal(aNamespaceURI, aLocalName, aReturn);
    2979                 : }
    2980                 : 
    2981                 : nsresult
    2982               0 : nsGenericElement::GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
    2983                 :                                              const nsAString& aLocalName,
    2984                 :                                              nsIDOMAttr** aReturn)
    2985                 : {
    2986               0 :   nsCOMPtr<nsIDOMNamedNodeMap> map;
    2987               0 :   nsresult rv = GetAttributes(getter_AddRefs(map));
    2988               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2989                 : 
    2990               0 :   nsCOMPtr<nsIDOMNode> node;
    2991               0 :   rv = map->GetNamedItemNS(aNamespaceURI, aLocalName, getter_AddRefs(node));
    2992                 : 
    2993               0 :   if (NS_SUCCEEDED(rv) && node) {
    2994               0 :     rv = CallQueryInterface(node, aReturn);
    2995                 :   }
    2996                 : 
    2997               0 :   return rv;
    2998                 : }
    2999                 : 
    3000                 : nsresult
    3001               0 : nsGenericElement::SetAttributeNodeNS(nsIDOMAttr* aNewAttr,
    3002                 :                                      nsIDOMAttr** aReturn)
    3003                 : {
    3004               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    3005               0 :   NS_ENSURE_ARG_POINTER(aNewAttr);
    3006               0 :   *aReturn = nsnull;
    3007                 : 
    3008               0 :   OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNodeNS);
    3009                 : 
    3010               0 :   nsCOMPtr<nsIDOMNamedNodeMap> map;
    3011               0 :   nsresult rv = GetAttributes(getter_AddRefs(map));
    3012               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3013                 : 
    3014               0 :   nsCOMPtr<nsIDOMNode> returnNode;
    3015               0 :   rv = map->SetNamedItemNS(aNewAttr, getter_AddRefs(returnNode));
    3016               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3017                 : 
    3018               0 :   if (returnNode) {
    3019               0 :     rv = CallQueryInterface(returnNode, aReturn);
    3020                 :   }
    3021                 : 
    3022               0 :   return rv;
    3023                 : }
    3024                 : 
    3025                 : nsresult
    3026              10 : nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
    3027                 :                                          const nsAString& aLocalName,
    3028                 :                                          nsIDOMNodeList** aReturn)
    3029                 : {
    3030              10 :   PRInt32 nameSpaceId = kNameSpaceID_Wildcard;
    3031                 : 
    3032              10 :   if (!aNamespaceURI.EqualsLiteral("*")) {
    3033                 :     nsresult rv =
    3034               6 :       nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
    3035               6 :                                                             nameSpaceId);
    3036               6 :     NS_ENSURE_SUCCESS(rv, rv);
    3037                 :   }
    3038                 : 
    3039              10 :   NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
    3040                 : 
    3041              10 :   nsContentList *list = NS_GetContentList(this, nameSpaceId, aLocalName).get();
    3042                 : 
    3043                 :   // transfer ref to aReturn
    3044              10 :   *aReturn = list;
    3045              10 :   return NS_OK;
    3046                 : }
    3047                 : 
    3048                 : nsresult
    3049            2560 : nsGenericElement::HasAttribute(const nsAString& aName, bool* aReturn)
    3050                 : {
    3051            2560 :   NS_ENSURE_ARG_POINTER(aReturn);
    3052                 : 
    3053            2560 :   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
    3054            2560 :   *aReturn = (name != nsnull);
    3055                 : 
    3056            2560 :   return NS_OK;
    3057                 : }
    3058                 : 
    3059                 : nsresult
    3060               0 : nsGenericElement::HasAttributeNS(const nsAString& aNamespaceURI,
    3061                 :                                  const nsAString& aLocalName,
    3062                 :                                  bool* aReturn)
    3063                 : {
    3064               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    3065                 : 
    3066                 :   PRInt32 nsid =
    3067               0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
    3068                 : 
    3069               0 :   if (nsid == kNameSpaceID_Unknown) {
    3070                 :     // Unknown namespace means no attr...
    3071                 : 
    3072               0 :     *aReturn = false;
    3073                 : 
    3074               0 :     return NS_OK;
    3075                 :   }
    3076                 : 
    3077               0 :   nsCOMPtr<nsIAtom> name = do_GetAtom(aLocalName);
    3078               0 :   *aReturn = HasAttr(nsid, name);
    3079                 : 
    3080               0 :   return NS_OK;
    3081                 : }
    3082                 : 
    3083                 : static nsXBLBinding*
    3084               0 : GetFirstBindingWithContent(nsBindingManager* aBmgr, nsIContent* aBoundElem)
    3085                 : {
    3086               0 :   nsXBLBinding* binding = aBmgr->GetBinding(aBoundElem);
    3087               0 :   while (binding) {
    3088               0 :     if (binding->GetAnonymousContent()) {
    3089               0 :       return binding;
    3090                 :     }
    3091               0 :     binding = binding->GetBaseBinding();
    3092                 :   }
    3093                 :   
    3094               0 :   return nsnull;
    3095                 : }
    3096                 : 
    3097                 : static nsresult
    3098               0 : BindNodesInInsertPoints(nsXBLBinding* aBinding, nsIContent* aInsertParent,
    3099                 :                         nsIDocument* aDocument)
    3100                 : {
    3101               0 :   NS_PRECONDITION(aBinding && aInsertParent, "Missing arguments");
    3102                 : 
    3103                 :   nsresult rv;
    3104                 :   // These should be refcounted or otherwise protectable.
    3105                 :   nsInsertionPointList* inserts =
    3106               0 :     aBinding->GetExistingInsertionPointsFor(aInsertParent);
    3107               0 :   if (inserts) {
    3108               0 :     bool allowScripts = aBinding->AllowScripts();
    3109                 : #ifdef MOZ_XUL
    3110               0 :     nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(aDocument);
    3111                 : #endif
    3112                 :     PRUint32 i;
    3113               0 :     for (i = 0; i < inserts->Length(); ++i) {
    3114                 :       nsCOMPtr<nsIContent> insertRoot =
    3115               0 :         inserts->ElementAt(i)->GetDefaultContent();
    3116               0 :       if (insertRoot) {
    3117               0 :         for (nsCOMPtr<nsIContent> child = insertRoot->GetFirstChild();
    3118               0 :              child;
    3119               0 :              child = child->GetNextSibling()) {
    3120               0 :           rv = child->BindToTree(aDocument, aInsertParent,
    3121               0 :                                  aBinding->GetBoundElement(), allowScripts);
    3122               0 :           NS_ENSURE_SUCCESS(rv, rv);
    3123                 : 
    3124                 : #ifdef MOZ_XUL
    3125               0 :           if (xulDoc) {
    3126               0 :             xulDoc->AddSubtreeToDocument(child);
    3127                 :           }
    3128                 : #endif
    3129                 :         }
    3130                 :       }
    3131                 :     }
    3132                 :   }
    3133                 : 
    3134               0 :   return NS_OK;
    3135                 : }
    3136                 : 
    3137                 : nsresult
    3138           38038 : nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
    3139                 :                              nsIContent* aBindingParent,
    3140                 :                              bool aCompileEventHandlers)
    3141                 : {
    3142           38038 :   NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
    3143           38038 :   NS_PRECONDITION(HasSameOwnerDoc(NODE_FROM(aParent, aDocument)),
    3144                 :                   "Must have the same owner document");
    3145           38038 :   NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
    3146                 :                   "aDocument must be current doc of aParent");
    3147           38038 :   NS_PRECONDITION(!GetCurrentDoc(), "Already have a document.  Unbind first!");
    3148                 :   // Note that as we recurse into the kids, they'll have a non-null parent.  So
    3149                 :   // only assert if our parent is _changing_ while we have a parent.
    3150           38038 :   NS_PRECONDITION(!GetParent() || aParent == GetParent(),
    3151                 :                   "Already have a parent.  Unbind first!");
    3152           38038 :   NS_PRECONDITION(!GetBindingParent() ||
    3153                 :                   aBindingParent == GetBindingParent() ||
    3154                 :                   (!aBindingParent && aParent &&
    3155                 :                    aParent->GetBindingParent() == GetBindingParent()),
    3156                 :                   "Already have a binding parent.  Unbind first!");
    3157           38038 :   NS_PRECONDITION(!aParent || !aDocument ||
    3158                 :                   !aParent->HasFlag(NODE_FORCE_XBL_BINDINGS),
    3159                 :                   "Parent in document but flagged as forcing XBL");
    3160           38038 :   NS_PRECONDITION(aBindingParent != this,
    3161                 :                   "Content must not be its own binding parent");
    3162           38038 :   NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() ||
    3163                 :                   aBindingParent == aParent,
    3164                 :                   "Native anonymous content must have its parent as its "
    3165                 :                   "own binding parent");
    3166                 : 
    3167           38038 :   if (!aBindingParent && aParent) {
    3168           36755 :     aBindingParent = aParent->GetBindingParent();
    3169                 :   }
    3170                 : 
    3171                 : #ifdef MOZ_XUL
    3172                 :   // First set the binding parent
    3173           38038 :   nsXULElement* xulElem = nsXULElement::FromContent(this);
    3174           38038 :   if (xulElem) {
    3175             144 :     xulElem->SetXULBindingParent(aBindingParent);
    3176                 :   }
    3177                 :   else 
    3178                 : #endif
    3179                 :   {
    3180           37894 :     if (aBindingParent) {
    3181               0 :       nsDOMSlots *slots = DOMSlots();
    3182                 : 
    3183               0 :       slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
    3184                 :     }
    3185                 :   }
    3186           38038 :   NS_ASSERTION(!aBindingParent || IsRootOfNativeAnonymousSubtree() ||
    3187                 :                !HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE) ||
    3188                 :                (aParent && aParent->IsInNativeAnonymousSubtree()),
    3189                 :                "Trying to re-bind content from native anonymous subtree to "
    3190                 :                "non-native anonymous parent!");
    3191           38038 :   if (aParent && aParent->IsInNativeAnonymousSubtree()) {
    3192               0 :     SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
    3193                 :   }
    3194                 : 
    3195           38038 :   bool hadForceXBL = HasFlag(NODE_FORCE_XBL_BINDINGS);
    3196                 : 
    3197                 :   // Now set the parent and set the "Force attach xbl" flag if needed.
    3198           38038 :   if (aParent) {
    3199           36755 :     if (!GetParent()) {
    3200           36675 :       NS_ADDREF(aParent);
    3201                 :     }
    3202           36755 :     mParent = aParent;
    3203                 : 
    3204           36755 :     if (aParent->HasFlag(NODE_FORCE_XBL_BINDINGS)) {
    3205               0 :       SetFlags(NODE_FORCE_XBL_BINDINGS);
    3206                 :     }
    3207                 :   }
    3208                 :   else {
    3209            1283 :     mParent = aDocument;
    3210                 :   }
    3211           38038 :   SetParentIsContent(aParent);
    3212                 : 
    3213                 :   // XXXbz sXBL/XBL2 issue!
    3214                 : 
    3215                 :   // Finally, set the document
    3216           38038 :   if (aDocument) {
    3217                 :     // Notify XBL- & nsIAnonymousContentCreator-generated
    3218                 :     // anonymous content that the document is changing.
    3219                 :     // XXXbz ordering issues here?  Probably not, since ChangeDocumentFor is
    3220                 :     // just pretty broken anyway....  Need to get it working.
    3221                 :     // XXXbz XBL doesn't handle this (asserts), and we don't really want
    3222                 :     // to be doing this during parsing anyway... sort this out.    
    3223                 :     //    aDocument->BindingManager()->ChangeDocumentFor(this, nsnull,
    3224                 :     //                                                   aDocument);
    3225                 : 
    3226                 :     // Being added to a document.
    3227           37848 :     SetInDocument();
    3228                 : 
    3229                 :     // Unset this flag since we now really are in a document.
    3230                 :     UnsetFlags(NODE_FORCE_XBL_BINDINGS |
    3231                 :                // And clear the lazy frame construction bits.
    3232                 :                NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES |
    3233                 :                // And the restyle bits
    3234           37848 :                ELEMENT_ALL_RESTYLE_FLAGS);
    3235                 :   }
    3236                 : 
    3237                 :   // If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children
    3238                 :   // that also need to be told that they are moving.
    3239                 :   nsresult rv;
    3240           38038 :   if (hadForceXBL) {
    3241               0 :     nsBindingManager* bmgr = OwnerDoc()->BindingManager();
    3242                 : 
    3243                 :     // First check if we have a binding...
    3244                 :     nsXBLBinding* contBinding =
    3245               0 :       GetFirstBindingWithContent(bmgr, this);
    3246               0 :     if (contBinding) {
    3247               0 :       nsCOMPtr<nsIContent> anonRoot = contBinding->GetAnonymousContent();
    3248               0 :       bool allowScripts = contBinding->AllowScripts();
    3249               0 :       for (nsCOMPtr<nsIContent> child = anonRoot->GetFirstChild();
    3250               0 :            child;
    3251               0 :            child = child->GetNextSibling()) {
    3252               0 :         rv = child->BindToTree(aDocument, this, this, allowScripts);
    3253               0 :         NS_ENSURE_SUCCESS(rv, rv);
    3254                 :       }
    3255                 : 
    3256                 :       // ...then check if we have content in insertion points that are
    3257                 :       // direct children of the <content>
    3258               0 :       rv = BindNodesInInsertPoints(contBinding, this, aDocument);
    3259               0 :       NS_ENSURE_SUCCESS(rv, rv);
    3260                 :     }
    3261                 : 
    3262                 :     // ...and finally check if we're in a binding where we have content in
    3263                 :     // insertion points.
    3264               0 :     if (aBindingParent) {
    3265               0 :       nsXBLBinding* binding = bmgr->GetBinding(aBindingParent);
    3266               0 :       if (binding) {
    3267               0 :         rv = BindNodesInInsertPoints(binding, this, aDocument);
    3268               0 :         NS_ENSURE_SUCCESS(rv, rv);
    3269                 :       }
    3270                 :     }
    3271                 :   }
    3272                 : 
    3273           38038 :   UpdateEditableState(false);
    3274                 : 
    3275                 :   // Now recurse into our kids
    3276           38125 :   for (nsIContent* child = GetFirstChild(); child;
    3277              87 :        child = child->GetNextSibling()) {
    3278                 :     rv = child->BindToTree(aDocument, this, aBindingParent,
    3279              87 :                            aCompileEventHandlers);
    3280              87 :     NS_ENSURE_SUCCESS(rv, rv);
    3281                 :   }
    3282                 : 
    3283           38038 :   nsNodeUtils::ParentChainChanged(this);
    3284                 : 
    3285                 :   // XXXbz script execution during binding can trigger some of these
    3286                 :   // postcondition asserts....  But we do want that, since things will
    3287                 :   // generally be quite broken when that happens.
    3288           38038 :   NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
    3289           38038 :   NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
    3290           38038 :   NS_POSTCONDITION(aBindingParent == GetBindingParent(),
    3291                 :                    "Bound to wrong binding parent");
    3292                 : 
    3293           38038 :   return NS_OK;
    3294                 : }
    3295                 : 
    3296                 : void
    3297          118643 : nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
    3298                 : {
    3299          118643 :   NS_PRECONDITION(aDeep || (!GetCurrentDoc() && !GetBindingParent()),
    3300                 :                   "Shallow unbind won't clear document and binding parent on "
    3301                 :                   "kids!");
    3302                 :   // Make sure to unbind this node before doing the kids
    3303                 :   nsIDocument *document =
    3304          118643 :     HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetCurrentDoc();
    3305                 : 
    3306          118643 :   if (aNullParent) {
    3307           37956 :     if (IsFullScreenAncestor()) {
    3308                 :       // The element being removed is an ancestor of the full-screen element,
    3309                 :       // exit full-screen state.
    3310                 :       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    3311                 :                                       "DOM", OwnerDoc(),
    3312                 :                                       nsContentUtils::eDOM_PROPERTIES,
    3313               0 :                                       "RemovedFullScreenElement");
    3314                 :       // Fully exit full-screen.
    3315               0 :       nsIDocument::ExitFullScreen(false);
    3316                 :     }
    3317           37956 :     if (GetParent()) {
    3318           36675 :       NS_RELEASE(mParent);
    3319                 :     } else {
    3320            1281 :       mParent = nsnull;
    3321                 :     }
    3322           37956 :     SetParentIsContent(false);
    3323                 :   }
    3324          118643 :   ClearInDocument();
    3325                 : 
    3326          118643 :   if (document) {
    3327                 :     // Notify XBL- & nsIAnonymousContentCreator-generated
    3328                 :     // anonymous content that the document is changing.
    3329           37846 :     document->BindingManager()->RemovedFromDocument(this, document);
    3330                 : 
    3331           37846 :     document->ClearBoxObjectFor(this);
    3332                 :   }
    3333                 : 
    3334                 :   // Ensure that CSS transitions don't continue on an element at a
    3335                 :   // different place in the tree (even if reinserted before next
    3336                 :   // animation refresh).
    3337                 :   // FIXME (Bug 522599): Need a test for this.
    3338          118643 :   if (HasFlag(NODE_HAS_PROPERTIES)) {
    3339               0 :     DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty);
    3340               0 :     DeleteProperty(nsGkAtoms::transitionsOfAfterProperty);
    3341               0 :     DeleteProperty(nsGkAtoms::transitionsProperty);
    3342               0 :     DeleteProperty(nsGkAtoms::animationsOfBeforeProperty);
    3343               0 :     DeleteProperty(nsGkAtoms::animationsOfAfterProperty);
    3344               0 :     DeleteProperty(nsGkAtoms::animationsProperty);
    3345                 :   }
    3346                 : 
    3347                 :   // Unset this since that's what the old code effectively did.
    3348          118643 :   UnsetFlags(NODE_FORCE_XBL_BINDINGS);
    3349                 :   
    3350                 : #ifdef MOZ_XUL
    3351          118643 :   nsXULElement* xulElem = nsXULElement::FromContent(this);
    3352          118643 :   if (xulElem) {
    3353             435 :     xulElem->SetXULBindingParent(nsnull);
    3354                 :   }
    3355                 :   else
    3356                 : #endif
    3357                 :   {
    3358          118208 :     nsDOMSlots *slots = GetExistingDOMSlots();
    3359          118208 :     if (slots) {
    3360            7798 :       slots->mBindingParent = nsnull;
    3361                 :     }
    3362                 :   }
    3363                 : 
    3364          118643 :   if (aDeep) {
    3365                 :     // Do the kids. Don't call GetChildCount() here since that'll force
    3366                 :     // XUL to generate template children, which there is no need for since
    3367                 :     // all we're going to do is unbind them anyway.
    3368          118643 :     PRUint32 i, n = mAttrsAndChildren.ChildCount();
    3369                 : 
    3370          376281 :     for (i = 0; i < n; ++i) {
    3371                 :       // Note that we pass false for aNullParent here, since we don't want
    3372                 :       // the kids to forget us.  We _do_ want them to forget their binding
    3373                 :       // parent, though, since this only walks non-anonymous kids.
    3374          257638 :       mAttrsAndChildren.ChildAt(i)->UnbindFromTree(true, false);
    3375                 :     }
    3376                 :   }
    3377                 : 
    3378          118643 :   nsNodeUtils::ParentChainChanged(this);
    3379          118643 : }
    3380                 : 
    3381                 : already_AddRefed<nsINodeList>
    3382               0 : nsGenericElement::GetChildren(PRUint32 aFilter)
    3383                 : {
    3384               0 :   nsRefPtr<nsSimpleContentList> list = new nsSimpleContentList(this);
    3385               0 :   if (!list) {
    3386               0 :     return nsnull;
    3387                 :   }
    3388                 : 
    3389               0 :   nsIFrame *frame = GetPrimaryFrame();
    3390                 : 
    3391                 :   // Append :before generated content.
    3392               0 :   if (frame) {
    3393               0 :     nsIFrame *beforeFrame = nsLayoutUtils::GetBeforeFrame(frame);
    3394               0 :     if (beforeFrame) {
    3395               0 :       list->AppendElement(beforeFrame->GetContent());
    3396                 :     }
    3397                 :   }
    3398                 : 
    3399                 :   // If XBL is bound to this node then append XBL anonymous content including
    3400                 :   // explict content altered by insertion point if we were requested for XBL
    3401                 :   // anonymous content, otherwise append explicit content with respect to
    3402                 :   // insertion point if any.
    3403               0 :   nsINodeList *childList = nsnull;
    3404                 : 
    3405               0 :   nsIDocument* document = OwnerDoc();
    3406               0 :   if (!(aFilter & eAllButXBL)) {
    3407               0 :     childList = document->BindingManager()->GetXBLChildNodesFor(this);
    3408               0 :     if (!childList) {
    3409               0 :       childList = GetChildNodesList();
    3410                 :     }
    3411                 : 
    3412                 :   } else {
    3413               0 :     childList = document->BindingManager()->GetContentListFor(this);
    3414                 :   }
    3415                 : 
    3416               0 :   if (childList) {
    3417               0 :     PRUint32 length = 0;
    3418               0 :     childList->GetLength(&length);
    3419               0 :     for (PRUint32 idx = 0; idx < length; idx++) {
    3420               0 :       nsIContent* child = childList->GetNodeAt(idx);
    3421               0 :       list->AppendElement(child);
    3422                 :     }
    3423                 :   }
    3424                 : 
    3425               0 :   if (frame) {
    3426                 :     // Append native anonymous content to the end.
    3427               0 :     nsIAnonymousContentCreator* creator = do_QueryFrame(frame);
    3428               0 :     if (creator) {
    3429               0 :       creator->AppendAnonymousContentTo(*list, aFilter);
    3430                 :     }
    3431                 : 
    3432                 :     // Append :after generated content.
    3433               0 :     nsIFrame *afterFrame = nsLayoutUtils::GetAfterFrame(frame);
    3434               0 :     if (afterFrame) {
    3435               0 :       list->AppendElement(afterFrame->GetContent());
    3436                 :     }
    3437                 :   }
    3438                 : 
    3439               0 :   nsINodeList* returnList = nsnull;
    3440               0 :   list.forget(&returnList);
    3441               0 :   return returnList;
    3442                 : }
    3443                 : 
    3444                 : static nsIContent*
    3445               0 : FindNativeAnonymousSubtreeOwner(nsIContent* aContent)
    3446                 : {
    3447               0 :   if (aContent->IsInNativeAnonymousSubtree()) {
    3448               0 :     bool isNativeAnon = false;
    3449               0 :     while (aContent && !isNativeAnon) {
    3450               0 :       isNativeAnon = aContent->IsRootOfNativeAnonymousSubtree();
    3451               0 :       aContent = aContent->GetParent();
    3452                 :     }
    3453                 :   }
    3454               0 :   return aContent;
    3455                 : }
    3456                 : 
    3457                 : nsresult
    3458              60 : nsIContent::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
    3459                 : {
    3460                 :   //FIXME! Document how this event retargeting works, Bug 329124.
    3461              60 :   aVisitor.mCanHandle = true;
    3462              60 :   aVisitor.mMayHaveListenerManager = HasListenerManager();
    3463                 : 
    3464                 :   // Don't propagate mouseover and mouseout events when mouse is moving
    3465                 :   // inside native anonymous content.
    3466              60 :   bool isAnonForEvents = IsRootOfNativeAnonymousSubtree();
    3467              60 :   if ((aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH ||
    3468                 :        aVisitor.mEvent->message == NS_MOUSE_EXIT_SYNTH) &&
    3469                 :       // Check if we should stop event propagation when event has just been
    3470                 :       // dispatched or when we're about to propagate from
    3471                 :       // native anonymous subtree.
    3472               0 :       ((this == aVisitor.mEvent->originalTarget &&
    3473               0 :         !IsInNativeAnonymousSubtree()) || isAnonForEvents)) {
    3474                 :      nsCOMPtr<nsIContent> relatedTarget =
    3475                 :        do_QueryInterface(static_cast<nsMouseEvent*>
    3476               0 :                                     (aVisitor.mEvent)->relatedTarget);
    3477               0 :     if (relatedTarget &&
    3478               0 :         relatedTarget->OwnerDoc() == OwnerDoc()) {
    3479                 : 
    3480                 :       // If current target is anonymous for events or we know that related
    3481                 :       // target is descendant of an element which is anonymous for events,
    3482                 :       // we may want to stop event propagation.
    3483                 :       // If this is the original target, aVisitor.mRelatedTargetIsInAnon
    3484                 :       // must be updated.
    3485               0 :       if (isAnonForEvents || aVisitor.mRelatedTargetIsInAnon ||
    3486               0 :           (aVisitor.mEvent->originalTarget == this &&
    3487                 :            (aVisitor.mRelatedTargetIsInAnon =
    3488               0 :             relatedTarget->IsInNativeAnonymousSubtree()))) {
    3489               0 :         nsIContent* anonOwner = FindNativeAnonymousSubtreeOwner(this);
    3490               0 :         if (anonOwner) {
    3491                 :           nsIContent* anonOwnerRelated =
    3492               0 :             FindNativeAnonymousSubtreeOwner(relatedTarget);
    3493               0 :           if (anonOwnerRelated) {
    3494                 :             // Note, anonOwnerRelated may still be inside some other
    3495                 :             // native anonymous subtree. The case where anonOwner is still
    3496                 :             // inside native anonymous subtree will be handled when event
    3497                 :             // propagates up in the DOM tree.
    3498               0 :             while (anonOwner != anonOwnerRelated &&
    3499               0 :                    anonOwnerRelated->IsInNativeAnonymousSubtree()) {
    3500               0 :               anonOwnerRelated = FindNativeAnonymousSubtreeOwner(anonOwnerRelated);
    3501                 :             }
    3502               0 :             if (anonOwner == anonOwnerRelated) {
    3503                 : #ifdef DEBUG_smaug
    3504                 :               nsCOMPtr<nsIContent> originalTarget =
    3505                 :                 do_QueryInterface(aVisitor.mEvent->originalTarget);
    3506                 :               nsAutoString ot, ct, rt;
    3507                 :               if (originalTarget) {
    3508                 :                 originalTarget->Tag()->ToString(ot);
    3509                 :               }
    3510                 :               Tag()->ToString(ct);
    3511                 :               relatedTarget->Tag()->ToString(rt);
    3512                 :               printf("Stopping %s propagation:"
    3513                 :                      "\n\toriginalTarget=%s \n\tcurrentTarget=%s %s"
    3514                 :                      "\n\trelatedTarget=%s %s \n%s",
    3515                 :                      (aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH)
    3516                 :                        ? "mouseover" : "mouseout",
    3517                 :                      NS_ConvertUTF16toUTF8(ot).get(),
    3518                 :                      NS_ConvertUTF16toUTF8(ct).get(),
    3519                 :                      isAnonForEvents
    3520                 :                        ? "(is native anonymous)"
    3521                 :                        : (IsInNativeAnonymousSubtree()
    3522                 :                            ? "(is in native anonymous subtree)" : ""),
    3523                 :                      NS_ConvertUTF16toUTF8(rt).get(),
    3524                 :                      relatedTarget->IsInNativeAnonymousSubtree()
    3525                 :                        ? "(is in native anonymous subtree)" : "",
    3526                 :                      (originalTarget && relatedTarget->FindFirstNonNativeAnonymous() ==
    3527                 :                        originalTarget->FindFirstNonNativeAnonymous())
    3528                 :                        ? "" : "Wrong event propagation!?!\n");
    3529                 : #endif
    3530               0 :               aVisitor.mParentTarget = nsnull;
    3531                 :               // Event should not propagate to non-anon content.
    3532               0 :               aVisitor.mCanHandle = isAnonForEvents;
    3533               0 :               return NS_OK;
    3534                 :             }
    3535                 :           }
    3536                 :         }
    3537                 :       }
    3538                 :     }
    3539                 :   }
    3540                 : 
    3541              60 :   nsIContent* parent = GetParent();
    3542                 :   // Event may need to be retargeted if this is the root of a native
    3543                 :   // anonymous content subtree or event is dispatched somewhere inside XBL.
    3544              60 :   if (isAnonForEvents) {
    3545                 :     // If a DOM event is explicitly dispatched using node.dispatchEvent(), then
    3546                 :     // all the events are allowed even in the native anonymous content..
    3547               0 :     NS_ASSERTION(aVisitor.mEvent->eventStructType != NS_MUTATION_EVENT ||
    3548                 :                  aVisitor.mDOMEvent,
    3549                 :                  "Mutation event dispatched in native anonymous content!?!");
    3550               0 :     aVisitor.mEventTargetAtParent = parent;
    3551              60 :   } else if (parent && aVisitor.mOriginalTargetIsInAnon) {
    3552               0 :     nsCOMPtr<nsIContent> content(do_QueryInterface(aVisitor.mEvent->target));
    3553               0 :     if (content && content->GetBindingParent() == parent) {
    3554               0 :       aVisitor.mEventTargetAtParent = parent;
    3555                 :     }
    3556                 :   }
    3557                 : 
    3558                 :   // check for an anonymous parent
    3559                 :   // XXX XBL2/sXBL issue
    3560              60 :   if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
    3561                 :     nsIContent* insertionParent = OwnerDoc()->BindingManager()->
    3562               0 :       GetInsertionParent(this);
    3563               0 :     NS_ASSERTION(!(aVisitor.mEventTargetAtParent && insertionParent &&
    3564                 :                    aVisitor.mEventTargetAtParent != insertionParent),
    3565                 :                  "Retargeting and having insertion parent!");
    3566               0 :     if (insertionParent) {
    3567               0 :       parent = insertionParent;
    3568                 :     }
    3569                 :   }
    3570                 : 
    3571              60 :   if (parent) {
    3572              16 :     aVisitor.mParentTarget = parent;
    3573                 :   } else {
    3574              44 :     aVisitor.mParentTarget = GetCurrentDoc();
    3575                 :   }
    3576              60 :   return NS_OK;
    3577                 : }
    3578                 : 
    3579                 : const nsAttrValue*
    3580               0 : nsGenericElement::DoGetClasses() const
    3581                 : {
    3582               0 :   NS_NOTREACHED("Shouldn't ever be called");
    3583               0 :   return nsnull;
    3584                 : }
    3585                 : 
    3586                 : NS_IMETHODIMP
    3587               0 : nsGenericElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
    3588                 : {
    3589               0 :   return NS_OK;
    3590                 : }
    3591                 : 
    3592                 : nsIDOMCSSStyleDeclaration*
    3593               0 : nsGenericElement::GetSMILOverrideStyle()
    3594                 : {
    3595               0 :   nsGenericElement::nsDOMSlots *slots = DOMSlots();
    3596                 : 
    3597               0 :   if (!slots->mSMILOverrideStyle) {
    3598               0 :     slots->mSMILOverrideStyle = new nsDOMCSSAttributeDeclaration(this, true);
    3599                 :   }
    3600                 : 
    3601               0 :   return slots->mSMILOverrideStyle;
    3602                 : }
    3603                 : 
    3604                 : css::StyleRule*
    3605               0 : nsGenericElement::GetSMILOverrideStyleRule()
    3606                 : {
    3607               0 :   nsGenericElement::nsDOMSlots *slots = GetExistingDOMSlots();
    3608               0 :   return slots ? slots->mSMILOverrideStyleRule.get() : nsnull;
    3609                 : }
    3610                 : 
    3611                 : nsresult
    3612               0 : nsGenericElement::SetSMILOverrideStyleRule(css::StyleRule* aStyleRule,
    3613                 :                                            bool aNotify)
    3614                 : {
    3615               0 :   nsGenericElement::nsDOMSlots *slots = DOMSlots();
    3616                 : 
    3617               0 :   slots->mSMILOverrideStyleRule = aStyleRule;
    3618                 : 
    3619               0 :   if (aNotify) {
    3620               0 :     nsIDocument* doc = GetCurrentDoc();
    3621                 :     // Only need to request a restyle if we're in a document.  (We might not
    3622                 :     // be in a document, if we're clearing animation effects on a target node
    3623                 :     // that's been detached since the previous animation sample.)
    3624               0 :     if (doc) {
    3625               0 :       nsCOMPtr<nsIPresShell> shell = doc->GetShell();
    3626               0 :       if (shell) {
    3627               0 :         shell->RestyleForAnimation(this, eRestyle_Self);
    3628                 :       }
    3629                 :     }
    3630                 :   }
    3631                 : 
    3632               0 :   return NS_OK;
    3633                 : }
    3634                 : 
    3635                 : css::StyleRule*
    3636               0 : nsGenericElement::GetInlineStyleRule()
    3637                 : {
    3638               0 :   return nsnull;
    3639                 : }
    3640                 : 
    3641                 : NS_IMETHODIMP
    3642               0 : nsGenericElement::SetInlineStyleRule(css::StyleRule* aStyleRule,
    3643                 :                                      bool aNotify)
    3644                 : {
    3645               0 :   NS_NOTYETIMPLEMENTED("nsGenericElement::SetInlineStyleRule");
    3646               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    3647                 : }
    3648                 : 
    3649                 : NS_IMETHODIMP_(bool)
    3650            9705 : nsGenericElement::IsAttributeMapped(const nsIAtom* aAttribute) const
    3651                 : {
    3652            9705 :   return false;
    3653                 : }
    3654                 : 
    3655                 : nsChangeHint
    3656               0 : nsGenericElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
    3657                 :                                          PRInt32 aModType) const
    3658                 : {
    3659               0 :   return nsChangeHint(0);
    3660                 : }
    3661                 : 
    3662                 : nsIAtom *
    3663               0 : nsGenericElement::GetClassAttributeName() const
    3664                 : {
    3665               0 :   return nsnull;
    3666                 : }
    3667                 : 
    3668                 : bool
    3669               0 : nsGenericElement::FindAttributeDependence(const nsIAtom* aAttribute,
    3670                 :                                           const MappedAttributeEntry* const aMaps[],
    3671                 :                                           PRUint32 aMapCount)
    3672                 : {
    3673               0 :   for (PRUint32 mapindex = 0; mapindex < aMapCount; ++mapindex) {
    3674               0 :     for (const MappedAttributeEntry* map = aMaps[mapindex];
    3675                 :          map->attribute; ++map) {
    3676               0 :       if (aAttribute == *map->attribute) {
    3677               0 :         return true;
    3678                 :       }
    3679                 :     }
    3680                 :   }
    3681                 : 
    3682               0 :   return false;
    3683                 : }
    3684                 : 
    3685                 : already_AddRefed<nsINodeInfo>
    3686               2 : nsGenericElement::GetExistingAttrNameFromQName(const nsAString& aStr) const
    3687                 : {
    3688               2 :   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aStr);
    3689               2 :   if (!name) {
    3690               2 :     return nsnull;
    3691                 :   }
    3692                 : 
    3693                 :   nsINodeInfo* nodeInfo;
    3694               0 :   if (name->IsAtom()) {
    3695                 :     nodeInfo = mNodeInfo->NodeInfoManager()->
    3696                 :       GetNodeInfo(name->Atom(), nsnull, kNameSpaceID_None,
    3697               0 :                   nsIDOMNode::ATTRIBUTE_NODE).get();
    3698                 :   }
    3699                 :   else {
    3700               0 :     NS_ADDREF(nodeInfo = name->NodeInfo());
    3701                 :   }
    3702                 : 
    3703               0 :   return nodeInfo;
    3704                 : }
    3705                 : 
    3706                 : bool
    3707               0 : nsGenericElement::IsLink(nsIURI** aURI) const
    3708                 : {
    3709               0 :   *aURI = nsnull;
    3710               0 :   return false;
    3711                 : }
    3712                 : 
    3713                 : // static
    3714                 : bool
    3715               0 : nsGenericElement::ShouldBlur(nsIContent *aContent)
    3716                 : {
    3717                 :   // Determine if the current element is focused, if it is not focused
    3718                 :   // then we should not try to blur
    3719               0 :   nsIDocument *document = aContent->GetDocument();
    3720               0 :   if (!document)
    3721               0 :     return false;
    3722                 : 
    3723               0 :   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(document->GetWindow());
    3724               0 :   if (!window)
    3725               0 :     return false;
    3726                 : 
    3727               0 :   nsCOMPtr<nsPIDOMWindow> focusedFrame;
    3728                 :   nsIContent* contentToBlur =
    3729               0 :     nsFocusManager::GetFocusedDescendant(window, false, getter_AddRefs(focusedFrame));
    3730               0 :   if (contentToBlur == aContent)
    3731               0 :     return true;
    3732                 : 
    3733                 :   // if focus on this element would get redirected, then check the redirected
    3734                 :   // content as well when blurring.
    3735               0 :   return (contentToBlur && nsFocusManager::GetRedirectedFocus(aContent) == contentToBlur);
    3736                 : }
    3737                 : 
    3738                 : nsIContent*
    3739          234926 : nsGenericElement::GetBindingParent() const
    3740                 : {
    3741          234926 :   nsDOMSlots *slots = GetExistingDOMSlots();
    3742                 : 
    3743          234926 :   if (slots) {
    3744             249 :     return slots->mBindingParent;
    3745                 :   }
    3746          234677 :   return nsnull;
    3747                 : }
    3748                 : 
    3749                 : bool
    3750          273164 : nsGenericElement::IsNodeOfType(PRUint32 aFlags) const
    3751                 : {
    3752          273164 :   return !(aFlags & ~eCONTENT);
    3753                 : }
    3754                 : 
    3755                 : //----------------------------------------------------------------------
    3756                 : 
    3757                 : PRUint32
    3758               0 : nsGenericElement::GetScriptTypeID() const
    3759                 : {
    3760               0 :     PtrBits flags = GetFlags();
    3761                 : 
    3762               0 :     return (flags >> NODE_SCRIPT_TYPE_OFFSET) & NODE_SCRIPT_TYPE_MASK;
    3763                 : }
    3764                 : 
    3765                 : NS_IMETHODIMP
    3766               0 : nsGenericElement::SetScriptTypeID(PRUint32 aLang)
    3767                 : {
    3768               0 :     if ((aLang & NODE_SCRIPT_TYPE_MASK) != aLang) {
    3769               0 :         NS_ERROR("script ID too large!");
    3770               0 :         return NS_ERROR_FAILURE;
    3771                 :     }
    3772                 :     /* SetFlags will just mask in the specific flags set, leaving existing
    3773                 :        ones alone.  So we must clear all the bits first */
    3774               0 :     UnsetFlags(NODE_SCRIPT_TYPE_MASK << NODE_SCRIPT_TYPE_OFFSET);
    3775               0 :     SetFlags(aLang << NODE_SCRIPT_TYPE_OFFSET);
    3776               0 :     return NS_OK;
    3777                 : }
    3778                 : 
    3779                 : nsresult
    3780          110572 : nsGenericElement::InsertChildAt(nsIContent* aKid,
    3781                 :                                 PRUint32 aIndex,
    3782                 :                                 bool aNotify)
    3783                 : {
    3784          110572 :   NS_PRECONDITION(aKid, "null ptr");
    3785                 : 
    3786          110572 :   return doInsertChildAt(aKid, aIndex, aNotify, mAttrsAndChildren);
    3787                 : }
    3788                 : 
    3789                 : static nsresult
    3790               0 : AdoptNodeIntoOwnerDoc(nsINode *aParent, nsINode *aNode)
    3791                 : {
    3792               0 :   NS_ASSERTION(!aNode->GetNodeParent(),
    3793                 :                "Should have removed from parent already");
    3794                 : 
    3795               0 :   nsIDocument *doc = aParent->OwnerDoc();
    3796                 : 
    3797                 :   nsresult rv;
    3798               0 :   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc, &rv);
    3799               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3800                 : 
    3801               0 :   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode, &rv);
    3802               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3803                 : 
    3804               0 :   nsCOMPtr<nsIDOMNode> adoptedNode;
    3805               0 :   rv = domDoc->AdoptNode(node, getter_AddRefs(adoptedNode));
    3806               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3807                 : 
    3808               0 :   NS_ASSERTION(aParent->OwnerDoc() == doc,
    3809                 :                "ownerDoc chainged while adopting");
    3810               0 :   NS_ASSERTION(adoptedNode == node, "Uh, adopt node changed nodes?");
    3811               0 :   NS_ASSERTION(aParent->HasSameOwnerDoc(aNode),
    3812                 :                "ownerDocument changed again after adopting!");
    3813                 : 
    3814               0 :   return NS_OK;
    3815                 : }
    3816                 : 
    3817                 : nsresult
    3818          111957 : nsINode::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
    3819                 :                          bool aNotify, nsAttrAndChildArray& aChildArray)
    3820                 : {
    3821          111957 :   NS_PRECONDITION(!aKid->GetNodeParent(),
    3822                 :                   "Inserting node that already has parent");
    3823                 :   nsresult rv;
    3824                 : 
    3825                 :   // The id-handling code, and in the future possibly other code, need to
    3826                 :   // react to unexpected attribute changes.
    3827          111957 :   nsMutationGuard::DidMutate();
    3828                 : 
    3829                 :   // Do this before checking the child-count since this could cause mutations
    3830          111957 :   nsIDocument* doc = GetCurrentDoc();
    3831          223914 :   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
    3832                 : 
    3833          111957 :   if (!HasSameOwnerDoc(aKid)) {
    3834               0 :     rv = AdoptNodeIntoOwnerDoc(this, aKid);
    3835               0 :     NS_ENSURE_SUCCESS(rv, rv);
    3836                 :   }
    3837                 : 
    3838          111957 :   PRUint32 childCount = aChildArray.ChildCount();
    3839          111957 :   NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE);
    3840          111957 :   bool isAppend = (aIndex == childCount);
    3841                 : 
    3842          111957 :   rv = aChildArray.InsertChildAt(aKid, aIndex);
    3843          111957 :   NS_ENSURE_SUCCESS(rv, rv);
    3844          111957 :   if (aIndex == 0) {
    3845           37132 :     mFirstChild = aKid;
    3846                 :   }
    3847                 : 
    3848                 :   nsIContent* parent =
    3849          111957 :     IsNodeOfType(eDOCUMENT) ? nsnull : static_cast<nsIContent*>(this);
    3850                 : 
    3851          111957 :   rv = aKid->BindToTree(doc, parent, nsnull, true);
    3852          111957 :   if (NS_FAILED(rv)) {
    3853               0 :     if (GetFirstChild() == aKid) {
    3854               0 :       mFirstChild = aKid->GetNextSibling();
    3855                 :     }
    3856               0 :     aChildArray.RemoveChildAt(aIndex);
    3857               0 :     aKid->UnbindFromTree();
    3858               0 :     return rv;
    3859                 :   }
    3860                 : 
    3861          111957 :   NS_ASSERTION(aKid->GetNodeParent() == this,
    3862                 :                "Did we run script inappropriately?");
    3863                 : 
    3864          111957 :   if (aNotify) {
    3865                 :     // Note that we always want to call ContentInserted when things are added
    3866                 :     // as kids to documents
    3867            1470 :     if (parent && isAppend) {
    3868             409 :       nsNodeUtils::ContentAppended(parent, aKid, aIndex);
    3869                 :     } else {
    3870            1061 :       nsNodeUtils::ContentInserted(this, aKid, aIndex);
    3871                 :     }
    3872                 : 
    3873            1470 :     if (nsContentUtils::HasMutationListeners(aKid,
    3874            1470 :           NS_EVENT_BITS_MUTATION_NODEINSERTED, this)) {
    3875               4 :       nsMutationEvent mutation(true, NS_MUTATION_NODEINSERTED);
    3876               2 :       mutation.mRelatedNode = do_QueryInterface(this);
    3877                 : 
    3878               4 :       mozAutoSubtreeModified subtree(OwnerDoc(), this);
    3879               2 :       (new nsAsyncDOMEvent(aKid, mutation))->RunDOMEventWhenSafe();
    3880                 :     }
    3881                 :   }
    3882                 : 
    3883          111957 :   return NS_OK;
    3884                 : }
    3885                 : 
    3886                 : nsresult
    3887             229 : nsGenericElement::RemoveChildAt(PRUint32 aIndex, bool aNotify)
    3888                 : {
    3889             458 :   nsCOMPtr<nsIContent> oldKid = mAttrsAndChildren.GetSafeChildAt(aIndex);
    3890             229 :   NS_ASSERTION(oldKid == GetChildAt(aIndex), "Unexpected child in RemoveChildAt");
    3891                 : 
    3892             229 :   if (oldKid) {
    3893             229 :     return doRemoveChildAt(aIndex, aNotify, oldKid, mAttrsAndChildren);
    3894                 :   }
    3895                 : 
    3896               0 :   return NS_OK;
    3897                 : }
    3898                 : 
    3899                 : nsresult
    3900             239 : nsINode::doRemoveChildAt(PRUint32 aIndex, bool aNotify,
    3901                 :                          nsIContent* aKid, nsAttrAndChildArray& aChildArray)
    3902                 : {
    3903             239 :   NS_PRECONDITION(aKid && aKid->GetNodeParent() == this &&
    3904                 :                   aKid == GetChildAt(aIndex) &&
    3905                 :                   IndexOf(aKid) == (PRInt32)aIndex, "Bogus aKid");
    3906                 : 
    3907             239 :   nsMutationGuard::DidMutate();
    3908                 : 
    3909             239 :   nsIDocument* doc = GetCurrentDoc();
    3910                 : 
    3911             478 :   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
    3912                 : 
    3913             239 :   nsIContent* previousSibling = aKid->GetPreviousSibling();
    3914                 : 
    3915             239 :   if (GetFirstChild() == aKid) {
    3916             119 :     mFirstChild = aKid->GetNextSibling();
    3917                 :   }
    3918                 : 
    3919             239 :   aChildArray.RemoveChildAt(aIndex);
    3920                 : 
    3921             239 :   if (aNotify) {
    3922             239 :     nsNodeUtils::ContentRemoved(this, aKid, aIndex, previousSibling);
    3923                 :   }
    3924                 : 
    3925             239 :   aKid->UnbindFromTree();
    3926                 : 
    3927             239 :   return NS_OK;
    3928                 : }
    3929                 : 
    3930                 : NS_IMETHODIMP
    3931            3875 : nsGenericElement::GetTextContent(nsAString &aTextContent)
    3932                 : {
    3933            3875 :   nsContentUtils::GetNodeTextContent(this, true, aTextContent);
    3934            3875 :   return NS_OK;
    3935                 : }
    3936                 : 
    3937                 : NS_IMETHODIMP
    3938               1 : nsGenericElement::SetTextContent(const nsAString& aTextContent)
    3939                 : {
    3940               1 :   return nsContentUtils::SetNodeTextContent(this, aTextContent, false);
    3941                 : }
    3942                 : 
    3943                 : /* static */
    3944                 : nsresult
    3945               0 : nsGenericElement::DispatchEvent(nsPresContext* aPresContext,
    3946                 :                                 nsEvent* aEvent,
    3947                 :                                 nsIContent* aTarget,
    3948                 :                                 bool aFullDispatch,
    3949                 :                                 nsEventStatus* aStatus)
    3950                 : {
    3951               0 :   NS_PRECONDITION(aTarget, "Must have target");
    3952               0 :   NS_PRECONDITION(aEvent, "Must have source event");
    3953               0 :   NS_PRECONDITION(aStatus, "Null out param?");
    3954                 : 
    3955               0 :   if (!aPresContext) {
    3956               0 :     return NS_OK;
    3957                 :   }
    3958                 : 
    3959               0 :   nsCOMPtr<nsIPresShell> shell = aPresContext->GetPresShell();
    3960               0 :   if (!shell) {
    3961               0 :     return NS_OK;
    3962                 :   }
    3963                 : 
    3964               0 :   if (aFullDispatch) {
    3965               0 :     return shell->HandleEventWithTarget(aEvent, nsnull, aTarget, aStatus);
    3966                 :   }
    3967                 : 
    3968               0 :   return shell->HandleDOMEventWithTarget(aTarget, aEvent, aStatus);
    3969                 : }
    3970                 : 
    3971                 : /* static */
    3972                 : nsresult
    3973               0 : nsGenericElement::DispatchClickEvent(nsPresContext* aPresContext,
    3974                 :                                      nsInputEvent* aSourceEvent,
    3975                 :                                      nsIContent* aTarget,
    3976                 :                                      bool aFullDispatch,
    3977                 :                                      PRUint32 aFlags,
    3978                 :                                      nsEventStatus* aStatus)
    3979                 : {
    3980               0 :   NS_PRECONDITION(aTarget, "Must have target");
    3981               0 :   NS_PRECONDITION(aSourceEvent, "Must have source event");
    3982               0 :   NS_PRECONDITION(aStatus, "Null out param?");
    3983                 : 
    3984                 :   nsMouseEvent event(NS_IS_TRUSTED_EVENT(aSourceEvent), NS_MOUSE_CLICK,
    3985               0 :                      aSourceEvent->widget, nsMouseEvent::eReal);
    3986               0 :   event.refPoint = aSourceEvent->refPoint;
    3987               0 :   PRUint32 clickCount = 1;
    3988               0 :   float pressure = 0;
    3989               0 :   PRUint16 inputSource = 0;
    3990               0 :   if (aSourceEvent->eventStructType == NS_MOUSE_EVENT) {
    3991               0 :     clickCount = static_cast<nsMouseEvent*>(aSourceEvent)->clickCount;
    3992               0 :     pressure = static_cast<nsMouseEvent*>(aSourceEvent)->pressure;
    3993               0 :     inputSource = static_cast<nsMouseEvent*>(aSourceEvent)->inputSource;
    3994               0 :   } else if (aSourceEvent->eventStructType == NS_KEY_EVENT) {
    3995               0 :     inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
    3996                 :   }
    3997               0 :   event.pressure = pressure;
    3998               0 :   event.clickCount = clickCount;
    3999               0 :   event.inputSource = inputSource;
    4000               0 :   event.isShift = aSourceEvent->isShift;
    4001               0 :   event.isControl = aSourceEvent->isControl;
    4002               0 :   event.isAlt = aSourceEvent->isAlt;
    4003               0 :   event.isMeta = aSourceEvent->isMeta;
    4004               0 :   event.flags |= aFlags; // Be careful not to overwrite existing flags!
    4005                 : 
    4006               0 :   return DispatchEvent(aPresContext, &event, aTarget, aFullDispatch, aStatus);
    4007                 : }
    4008                 : 
    4009                 : nsIFrame*
    4010               0 : nsGenericElement::GetPrimaryFrame(mozFlushType aType)
    4011                 : {
    4012               0 :   nsIDocument* doc = GetCurrentDoc();
    4013               0 :   if (!doc) {
    4014               0 :     return nsnull;
    4015                 :   }
    4016                 : 
    4017                 :   // Cause a flush, so we get up-to-date frame
    4018                 :   // information
    4019               0 :   doc->FlushPendingNotifications(aType);
    4020                 : 
    4021               0 :   return GetPrimaryFrame();
    4022                 : }
    4023                 : 
    4024                 : void
    4025               0 : nsGenericElement::DestroyContent()
    4026                 : {
    4027               0 :   nsIDocument *document = OwnerDoc();
    4028               0 :   document->BindingManager()->RemovedFromDocument(this, document);
    4029               0 :   document->ClearBoxObjectFor(this);
    4030                 : 
    4031                 :   // XXX We really should let cycle collection do this, but that currently still
    4032                 :   //     leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
    4033               0 :   nsContentUtils::ReleaseWrapper(this, this);
    4034                 : 
    4035               0 :   PRUint32 i, count = mAttrsAndChildren.ChildCount();
    4036               0 :   for (i = 0; i < count; ++i) {
    4037                 :     // The child can remove itself from the parent in BindToTree.
    4038               0 :     mAttrsAndChildren.ChildAt(i)->DestroyContent();
    4039                 :   }
    4040               0 : }
    4041                 : 
    4042                 : void
    4043               0 : nsGenericElement::SaveSubtreeState()
    4044                 : {
    4045               0 :   PRUint32 i, count = mAttrsAndChildren.ChildCount();
    4046               0 :   for (i = 0; i < count; ++i) {
    4047               0 :     mAttrsAndChildren.ChildAt(i)->SaveSubtreeState();
    4048                 :   }
    4049               0 : }
    4050                 : 
    4051                 : //----------------------------------------------------------------------
    4052                 : 
    4053                 : // Generic DOMNode implementations
    4054                 : 
    4055                 : // When replacing, aRefChild is the content being replaced; when
    4056                 : // inserting it's the content before which we're inserting.  In the
    4057                 : // latter case it may be null.
    4058                 : static
    4059             417 : bool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
    4060                 :                         bool aIsReplace, nsINode* aRefChild)
    4061                 : {
    4062             417 :   NS_PRECONDITION(aNewChild, "Must have new child");
    4063             417 :   NS_PRECONDITION(!aIsReplace || aRefChild,
    4064                 :                   "Must have ref content for replace");
    4065             417 :   NS_PRECONDITION(aParent->IsNodeOfType(nsINode::eDOCUMENT) ||
    4066                 :                   aParent->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT) ||
    4067                 :                   aParent->IsElement(),
    4068                 :                   "Nodes that are not documents, document fragments or "
    4069                 :                   "elements can't be parents!");
    4070                 : 
    4071             417 :   if (aParent && nsContentUtils::ContentIsDescendantOf(aParent, aNewChild)) {
    4072               0 :     return false;
    4073                 :   }
    4074                 : 
    4075                 :   // The allowed child nodes differ for documents and elements
    4076             417 :   switch (aNewChild->NodeType()) {
    4077                 :   case nsIDOMNode::COMMENT_NODE :
    4078                 :   case nsIDOMNode::PROCESSING_INSTRUCTION_NODE :
    4079                 :     // OK in both cases
    4080              30 :     return true;
    4081                 :   case nsIDOMNode::TEXT_NODE :
    4082                 :   case nsIDOMNode::CDATA_SECTION_NODE :
    4083                 :   case nsIDOMNode::ENTITY_REFERENCE_NODE :
    4084                 :     // Only allowed under elements
    4085             103 :     return aParent != nsnull;
    4086                 :   case nsIDOMNode::ELEMENT_NODE :
    4087                 :     {
    4088             284 :       if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
    4089                 :         // Always ok to have elements under other elements or document fragments
    4090             283 :         return true;
    4091                 :       }
    4092                 : 
    4093                 :       Element* rootElement =
    4094               1 :         static_cast<nsIDocument*>(aParent)->GetRootElement();
    4095               1 :       if (rootElement) {
    4096                 :         // Already have a documentElement, so this is only OK if we're
    4097                 :         // replacing it.
    4098               0 :         return aIsReplace && rootElement == aRefChild;
    4099                 :       }
    4100                 : 
    4101                 :       // We don't have a documentElement yet.  Our one remaining constraint is
    4102                 :       // that the documentElement must come after the doctype.
    4103               1 :       if (!aRefChild) {
    4104                 :         // Appending is just fine.
    4105               1 :         return true;
    4106                 :       }
    4107                 : 
    4108                 :       // Now grovel for a doctype
    4109               0 :       nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aParent);
    4110               0 :       NS_ASSERTION(doc, "Shouldn't happen");
    4111               0 :       nsCOMPtr<nsIDOMDocumentType> docType;
    4112               0 :       doc->GetDoctype(getter_AddRefs(docType));
    4113               0 :       nsCOMPtr<nsIContent> docTypeContent = do_QueryInterface(docType);
    4114                 :       
    4115               0 :       if (!docTypeContent) {
    4116                 :         // It's all good.
    4117               0 :         return true;
    4118                 :       }
    4119                 : 
    4120               0 :       PRInt32 doctypeIndex = aParent->IndexOf(docTypeContent);
    4121               0 :       PRInt32 insertIndex = aParent->IndexOf(aRefChild);
    4122                 : 
    4123                 :       // Now we're OK in the following two cases only:
    4124                 :       // 1) We're replacing something that's not before the doctype
    4125                 :       // 2) We're inserting before something that comes after the doctype 
    4126                 :       return aIsReplace ? (insertIndex >= doctypeIndex) :
    4127               0 :         insertIndex > doctypeIndex;
    4128                 :     }
    4129                 :   case nsIDOMNode::DOCUMENT_TYPE_NODE :
    4130                 :     {
    4131               0 :       if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
    4132                 :         // doctypes only allowed under documents
    4133               0 :         return false;
    4134                 :       }
    4135                 : 
    4136               0 :       nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aParent);
    4137               0 :       NS_ASSERTION(doc, "Shouldn't happen");
    4138               0 :       nsCOMPtr<nsIDOMDocumentType> docType;
    4139               0 :       doc->GetDoctype(getter_AddRefs(docType));
    4140               0 :       nsCOMPtr<nsIContent> docTypeContent = do_QueryInterface(docType);
    4141               0 :       if (docTypeContent) {
    4142                 :         // Already have a doctype, so this is only OK if we're replacing it
    4143               0 :         return aIsReplace && docTypeContent == aRefChild;
    4144                 :       }
    4145                 : 
    4146                 :       // We don't have a doctype yet.  Our one remaining constraint is
    4147                 :       // that the doctype must come before the documentElement.
    4148                 :       Element* rootElement =
    4149               0 :         static_cast<nsIDocument*>(aParent)->GetRootElement();
    4150               0 :       if (!rootElement) {
    4151                 :         // It's all good
    4152               0 :         return true;
    4153                 :       }
    4154                 : 
    4155               0 :       if (!aRefChild) {
    4156                 :         // Trying to append a doctype, but have a documentElement
    4157               0 :         return false;
    4158                 :       }
    4159                 : 
    4160               0 :       PRInt32 rootIndex = aParent->IndexOf(rootElement);
    4161               0 :       PRInt32 insertIndex = aParent->IndexOf(aRefChild);
    4162                 : 
    4163                 :       // Now we're OK if and only if insertIndex <= rootIndex.  Indeed, either
    4164                 :       // we end up replacing aRefChild or we end up before it.  Either one is
    4165                 :       // ok as long as aRefChild is not after rootElement.
    4166               0 :       return insertIndex <= rootIndex;
    4167                 :     }
    4168                 :   case nsIDOMNode::DOCUMENT_FRAGMENT_NODE :
    4169                 :     {
    4170                 :       // Note that for now we only allow nodes inside document fragments if
    4171                 :       // they're allowed inside elements.  If we ever change this to allow
    4172                 :       // doctype nodes in document fragments, we'll need to update this code
    4173               0 :       if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
    4174                 :         // All good here
    4175               0 :         return true;
    4176                 :       }
    4177                 : 
    4178               0 :       bool sawElement = false;
    4179               0 :       for (nsIContent* child = aNewChild->GetFirstChild();
    4180                 :            child;
    4181               0 :            child = child->GetNextSibling()) {
    4182               0 :         if (child->IsElement()) {
    4183               0 :           if (sawElement) {
    4184                 :             // Can't put two elements into a document
    4185               0 :             return false;
    4186                 :           }
    4187               0 :           sawElement = true;
    4188                 :         }
    4189                 :         // If we can put this content at the the right place, we might be ok;
    4190                 :         // if not, we bail out.
    4191               0 :         if (!IsAllowedAsChild(child, aParent, aIsReplace, aRefChild)) {
    4192               0 :           return false;
    4193                 :         }
    4194                 :       }
    4195                 : 
    4196                 :       // Everything in the fragment checked out ok, so we can stick it in here
    4197               0 :       return true;
    4198                 :     }
    4199                 :   default:
    4200                 :     /*
    4201                 :      * aNewChild is of invalid type.
    4202                 :      */
    4203                 :     break;
    4204                 :   }
    4205                 : 
    4206               0 :   return false;
    4207                 : }
    4208                 : 
    4209                 : void
    4210               0 : nsGenericElement::FireNodeInserted(nsIDocument* aDoc,
    4211                 :                                    nsINode* aParent,
    4212                 :                                    nsTArray<nsCOMPtr<nsIContent> >& aNodes)
    4213                 : {
    4214               0 :   PRUint32 count = aNodes.Length();
    4215               0 :   for (PRUint32 i = 0; i < count; ++i) {
    4216               0 :     nsIContent* childContent = aNodes[i];
    4217                 : 
    4218               0 :     if (nsContentUtils::HasMutationListeners(childContent,
    4219               0 :           NS_EVENT_BITS_MUTATION_NODEINSERTED, aParent)) {
    4220               0 :       nsMutationEvent mutation(true, NS_MUTATION_NODEINSERTED);
    4221               0 :       mutation.mRelatedNode = do_QueryInterface(aParent);
    4222                 : 
    4223               0 :       mozAutoSubtreeModified subtree(aDoc, aParent);
    4224               0 :       (new nsAsyncDOMEvent(childContent, mutation))->RunDOMEventWhenSafe();
    4225                 :     }
    4226                 :   }
    4227               0 : }
    4228                 : 
    4229                 : nsresult
    4230             417 : nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
    4231                 :                                nsINode* aRefChild)
    4232                 : {
    4233             417 :   if (!aNewChild || (aReplace && !aRefChild)) {
    4234               0 :     return NS_ERROR_NULL_POINTER;
    4235                 :   }
    4236                 : 
    4237            1521 :   if ((!IsNodeOfType(eDOCUMENT) &&
    4238             416 :        !IsNodeOfType(eDOCUMENT_FRAGMENT) &&
    4239             271 :        !IsElement()) ||
    4240             417 :       !aNewChild->IsNodeOfType(eCONTENT)){
    4241               0 :     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    4242                 :   }
    4243                 : 
    4244             417 :   PRUint16 nodeType = aNewChild->NodeType();
    4245                 : 
    4246                 :   // Before we do anything else, fire all DOMNodeRemoved mutation events
    4247                 :   // We do this up front as to avoid having to deal with script running
    4248                 :   // at random places further down.
    4249                 :   // Scope firing mutation events so that we don't carry any state that
    4250                 :   // might be stale
    4251                 :   {
    4252                 :     // This check happens again further down (though then using IndexOf).
    4253                 :     // We're only checking this here to avoid firing mutation events when
    4254                 :     // none should be fired.
    4255                 :     // It's ok that we do the check twice in the case when firing mutation
    4256                 :     // events as we need to recheck after running script anyway.
    4257             417 :     if (aRefChild && aRefChild->GetNodeParent() != this) {
    4258               0 :       return NS_ERROR_DOM_NOT_FOUND_ERR;
    4259                 :     }
    4260                 : 
    4261                 :     // If we're replacing, fire for node-to-be-replaced.
    4262                 :     // If aRefChild == aNewChild then we'll fire for it in check below
    4263             417 :     if (aReplace && aRefChild != aNewChild) {
    4264               0 :       nsContentUtils::MaybeFireNodeRemoved(aRefChild, this, OwnerDoc());
    4265                 :     }
    4266                 : 
    4267                 :     // If the new node already has a parent, fire for removing from old
    4268                 :     // parent
    4269             417 :     nsINode* oldParent = aNewChild->GetNodeParent();
    4270             417 :     if (oldParent) {
    4271                 :       nsContentUtils::MaybeFireNodeRemoved(aNewChild, oldParent,
    4272              80 :                                            aNewChild->OwnerDoc());
    4273                 :     }
    4274                 : 
    4275                 :     // If we're inserting a fragment, fire for all the children of the
    4276                 :     // fragment
    4277             417 :     if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
    4278               0 :       static_cast<nsGenericElement*>(aNewChild)->FireNodeRemovedForChildren();
    4279                 :     }
    4280                 :   }
    4281                 : 
    4282             417 :   nsIDocument* doc = OwnerDoc();
    4283             417 :   nsIContent* newContent = static_cast<nsIContent*>(aNewChild);
    4284                 :   PRInt32 insPos;
    4285                 : 
    4286             834 :   mozAutoDocUpdate batch(GetCurrentDoc(), UPDATE_CONTENT_MODEL, true);
    4287                 : 
    4288                 :   // Figure out which index to insert at
    4289             417 :   if (aRefChild) {
    4290               8 :     insPos = IndexOf(aRefChild);
    4291               8 :     if (insPos < 0) {
    4292               0 :       return NS_ERROR_DOM_NOT_FOUND_ERR;
    4293                 :     }
    4294                 :   }
    4295                 :   else {
    4296             409 :     insPos = GetChildCount();
    4297                 :   }
    4298                 : 
    4299                 :   // Make sure that the inserted node is allowed as a child of its new parent.
    4300             417 :   if (!IsAllowedAsChild(newContent, this, aReplace, aRefChild)) {
    4301               0 :     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    4302                 :   }
    4303                 : 
    4304                 :   nsresult res;
    4305                 : 
    4306                 :   // If we're replacing
    4307             417 :   if (aReplace) {
    4308               0 :     res = RemoveChildAt(insPos, true);
    4309               0 :     NS_ENSURE_SUCCESS(res, res);
    4310                 :   }
    4311                 : 
    4312             417 :   if (newContent->IsRootOfAnonymousSubtree()) {
    4313                 :     // This is anonymous content.  Don't allow its insertion
    4314                 :     // anywhere, since it might have UnbindFromTree calls coming
    4315                 :     // its way.
    4316               0 :     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    4317                 :   }
    4318                 : 
    4319                 :   // Remove the new child from the old parent if one exists
    4320             834 :   nsCOMPtr<nsINode> oldParent = newContent->GetNodeParent();
    4321             417 :   if (oldParent) {
    4322              80 :     PRInt32 removeIndex = oldParent->IndexOf(newContent);
    4323              80 :     if (removeIndex < 0) {
    4324                 :       // newContent is anonymous.  We can't deal with this, so just bail
    4325               0 :       NS_ERROR("How come our flags didn't catch this?");
    4326               0 :       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    4327                 :     }
    4328                 : 
    4329              80 :     res = oldParent->RemoveChildAt(removeIndex, true);
    4330              80 :     NS_ENSURE_SUCCESS(res, res);
    4331                 : 
    4332                 :     // Adjust insert index if the node we ripped out was a sibling
    4333                 :     // of the node we're inserting before
    4334              80 :     if (oldParent == this && removeIndex < insPos) {
    4335              73 :       --insPos;
    4336                 :     }
    4337                 :   }
    4338                 : 
    4339                 :   // Move new child over to our document if needed. Do this after removing
    4340                 :   // it from its parent so that AdoptNode doesn't fire DOMNodeRemoved
    4341                 :   // DocumentType nodes are the only nodes that can have a null
    4342                 :   // ownerDocument according to the DOM spec, and we need to allow
    4343                 :   // inserting them w/o calling AdoptNode().
    4344             417 :   if (!HasSameOwnerDoc(newContent)) {
    4345               0 :     res = AdoptNodeIntoOwnerDoc(this, aNewChild);
    4346               0 :     NS_ENSURE_SUCCESS(res, res);
    4347                 :   }
    4348                 : 
    4349                 :   /*
    4350                 :    * Check if we're inserting a document fragment. If we are, we need
    4351                 :    * to remove the children of the document fragment and add them
    4352                 :    * individually (i.e. we don't add the actual document fragment).
    4353                 :    */
    4354             417 :   if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
    4355               0 :     PRUint32 count = newContent->GetChildCount();
    4356                 : 
    4357               0 :     if (!count) {
    4358               0 :       return NS_OK;
    4359                 :     }
    4360                 : 
    4361                 :     // Copy the children into a separate array to avoid having to deal with
    4362                 :     // mutations to the fragment while we're inserting.
    4363               0 :     nsAutoTArray<nsCOMPtr<nsIContent>, 50> fragChildren;
    4364               0 :     fragChildren.SetCapacity(count);
    4365               0 :     for (nsIContent* child = newContent->GetFirstChild();
    4366                 :          child;
    4367               0 :          child = child->GetNextSibling()) {
    4368               0 :       NS_ASSERTION(child->GetCurrentDoc() == nsnull,
    4369                 :                    "How did we get a child with a current doc?");
    4370               0 :       fragChildren.AppendElement(child);
    4371                 :     }
    4372                 : 
    4373                 :     // Remove the children from the fragment.
    4374               0 :     for (PRUint32 i = count; i > 0;) {
    4375               0 :       newContent->RemoveChildAt(--i, true);
    4376                 :     }
    4377                 : 
    4378                 :     bool appending =
    4379               0 :       !IsNodeOfType(eDOCUMENT) && PRUint32(insPos) == GetChildCount();
    4380               0 :     PRInt32 firstInsPos = insPos;
    4381               0 :     nsIContent* firstInsertedContent = fragChildren[0];
    4382                 : 
    4383                 :     // Iterate through the fragment's children, and insert them in the new
    4384                 :     // parent
    4385               0 :     for (PRUint32 i = 0; i < count; ++i, ++insPos) {
    4386                 :       // XXXbz how come no reparenting here?  That seems odd...
    4387                 :       // Insert the child.
    4388               0 :       res = InsertChildAt(fragChildren[i], insPos, !appending);
    4389               0 :       if (NS_FAILED(res)) {
    4390                 :         // Make sure to notify on any children that we did succeed to insert
    4391               0 :         if (appending && i != 0) {
    4392                 :           nsNodeUtils::ContentAppended(static_cast<nsIContent*>(this),
    4393                 :                                        firstInsertedContent,
    4394               0 :                                        firstInsPos);
    4395                 :         }
    4396               0 :         return res;
    4397                 :       }
    4398                 :     }
    4399                 : 
    4400                 :     // Notify and fire mutation events when appending
    4401               0 :     if (appending) {
    4402                 :       nsNodeUtils::ContentAppended(static_cast<nsIContent*>(this),
    4403               0 :                                    firstInsertedContent, firstInsPos);
    4404                 :       // Optimize for the case when there are no listeners
    4405               0 :       if (nsContentUtils::
    4406                 :             HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
    4407               0 :         nsGenericElement::FireNodeInserted(doc, this, fragChildren);
    4408                 :       }
    4409                 :     }
    4410                 :   }
    4411                 :   else {
    4412                 :     // Not inserting a fragment but rather a single node.
    4413                 : 
    4414                 :     // FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=544654
    4415                 :     //       We need to reparent here for nodes for which the parent of their
    4416                 :     //       wrapper is not the wrapper for their ownerDocument (XUL elements,
    4417                 :     //       form controls, ...). Also applies in the fragment code above.
    4418                 : 
    4419             417 :     res = InsertChildAt(newContent, insPos, true);
    4420             417 :     NS_ENSURE_SUCCESS(res, res);
    4421                 :   }
    4422                 : 
    4423             417 :   return NS_OK;
    4424                 : }
    4425                 : 
    4426                 : nsresult
    4427               0 : nsINode::CompareDocumentPosition(nsIDOMNode* aOther, PRUint16* aReturn)
    4428                 : {
    4429               0 :   nsCOMPtr<nsINode> other = do_QueryInterface(aOther);
    4430               0 :   if (!other) {
    4431               0 :     return NS_ERROR_NULL_POINTER;
    4432                 :   }
    4433               0 :   *aReturn = CompareDocPosition(other);
    4434               0 :   return NS_OK;
    4435                 : }
    4436                 : 
    4437                 : nsresult
    4438               0 : nsINode::IsEqualNode(nsIDOMNode* aOther, bool* aReturn)
    4439                 : {
    4440               0 :   nsCOMPtr<nsINode> other = do_QueryInterface(aOther);
    4441               0 :   *aReturn = IsEqualTo(other);
    4442               0 :   return NS_OK;
    4443                 : }
    4444                 : 
    4445                 : //----------------------------------------------------------------------
    4446                 : 
    4447                 : // nsISupports implementation
    4448                 : 
    4449            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericElement)
    4450                 : 
    4451                 : #define SUBTREE_UNBINDINGS_PER_RUNNABLE 500
    4452                 : 
    4453                 : class ContentUnbinder : public nsRunnable
    4454                 : {
    4455                 : public:
    4456              21 :   ContentUnbinder()
    4457              21 :   {
    4458              21 :     nsLayoutStatics::AddRef();
    4459              21 :     mLast = this;
    4460              21 :   }
    4461                 : 
    4462              42 :   ~ContentUnbinder()
    4463              42 :   {
    4464              21 :     Run();
    4465              21 :     nsLayoutStatics::Release();
    4466              84 :   }
    4467                 : 
    4468           32364 :   void UnbindSubtree(nsIContent* aNode)
    4469                 :   {
    4470           53982 :     if (aNode->NodeType() != nsIDOMNode::ELEMENT_NODE &&
    4471           21618 :         aNode->NodeType() != nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
    4472           21618 :       return;  
    4473                 :     }
    4474           10746 :     nsGenericElement* container = static_cast<nsGenericElement*>(aNode);
    4475           10746 :     PRUint32 childCount = container->mAttrsAndChildren.ChildCount();
    4476           10746 :     if (childCount) {
    4477           53429 :       while (childCount-- > 0) {
    4478                 :         // Hold a strong ref to the node when we remove it, because we may be
    4479                 :         // the last reference to it.  We need to call TakeChildAt() and
    4480                 :         // update mFirstChild before calling UnbindFromTree, since this last
    4481                 :         // can notify various observers and they should really see consistent
    4482                 :         // tree state.
    4483                 :         nsCOMPtr<nsIContent> child =
    4484           64370 :           container->mAttrsAndChildren.TakeChildAt(childCount);
    4485           32185 :         if (childCount == 0) {
    4486           10622 :           container->mFirstChild = nsnull;
    4487                 :         }
    4488           32185 :         UnbindSubtree(child);
    4489           32185 :         child->UnbindFromTree();
    4490                 :       }
    4491                 :     }
    4492                 :   }
    4493                 : 
    4494              42 :   NS_IMETHOD Run()
    4495                 :   {
    4496              84 :     nsAutoScriptBlocker scriptBlocker;
    4497              42 :     PRUint32 len = mSubtreeRoots.Length();
    4498              42 :     if (len) {
    4499              21 :       PRTime start = PR_Now();
    4500             200 :       for (PRUint32 i = 0; i < len; ++i) {
    4501             179 :         UnbindSubtree(mSubtreeRoots[i]);
    4502                 :       }
    4503              21 :       mSubtreeRoots.Clear();
    4504                 :       Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_CONTENT_UNBIND,
    4505              21 :                             PRUint32(PR_Now() - start) / PR_USEC_PER_MSEC);
    4506                 :     }
    4507              42 :     if (this == sContentUnbinder) {
    4508              21 :       sContentUnbinder = nsnull;
    4509              21 :       if (mNext) {
    4510               0 :         nsRefPtr<ContentUnbinder> next;
    4511               0 :         next.swap(mNext);
    4512               0 :         sContentUnbinder = next;
    4513               0 :         next->mLast = mLast;
    4514               0 :         mLast = nsnull;
    4515               0 :         NS_DispatchToMainThread(next);
    4516                 :       }
    4517                 :     }
    4518              42 :     return NS_OK;
    4519                 :   }
    4520                 : 
    4521             179 :   static void Append(nsIContent* aSubtreeRoot)
    4522                 :   {
    4523             179 :     if (!sContentUnbinder) {
    4524              21 :       sContentUnbinder = new ContentUnbinder();
    4525              42 :       nsCOMPtr<nsIRunnable> e = sContentUnbinder;
    4526              21 :       NS_DispatchToMainThread(e);
    4527                 :     }
    4528                 : 
    4529             179 :     if (sContentUnbinder->mLast->mSubtreeRoots.Length() >=
    4530                 :         SUBTREE_UNBINDINGS_PER_RUNNABLE) {
    4531               0 :       sContentUnbinder->mLast->mNext = new ContentUnbinder();
    4532               0 :       sContentUnbinder->mLast = sContentUnbinder->mLast->mNext;
    4533                 :     }
    4534             179 :     sContentUnbinder->mLast->mSubtreeRoots.AppendElement(aSubtreeRoot);
    4535             179 :   }
    4536                 : 
    4537                 : private:
    4538                 :   nsAutoTArray<nsCOMPtr<nsIContent>,
    4539                 :                SUBTREE_UNBINDINGS_PER_RUNNABLE> mSubtreeRoots;
    4540                 :   nsRefPtr<ContentUnbinder>                     mNext;
    4541                 :   ContentUnbinder*                              mLast;
    4542                 :   static ContentUnbinder*                       sContentUnbinder;
    4543                 : };
    4544                 : 
    4545                 : ContentUnbinder* ContentUnbinder::sContentUnbinder = nsnull;
    4546                 : 
    4547           37985 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericElement)
    4548           37985 :   nsINode::Unlink(tmp);
    4549                 : 
    4550           37985 :   if (tmp->HasProperties() && tmp->IsXUL()) {
    4551               0 :     tmp->DeleteProperty(nsGkAtoms::contextmenulistener);
    4552               0 :     tmp->DeleteProperty(nsGkAtoms::popuplistener);
    4553                 :   }
    4554                 : 
    4555                 :   // Unlink child content (and unbind our subtree).
    4556           37985 :   if (UnoptimizableCCNode(tmp) || !nsCCUncollectableMarker::sGeneration) {
    4557           27231 :     PRUint32 childCount = tmp->mAttrsAndChildren.ChildCount();
    4558           27231 :     if (childCount) {
    4559                 :       // Don't allow script to run while we're unbinding everything.
    4560           50282 :       nsAutoScriptBlocker scriptBlocker;
    4561          128438 :       while (childCount-- > 0) {
    4562                 :         // Hold a strong ref to the node when we remove it, because we may be
    4563                 :         // the last reference to it.  We need to call TakeChildAt() and
    4564                 :         // update mFirstChild before calling UnbindFromTree, since this last
    4565                 :         // can notify various observers and they should really see consistent
    4566                 :         // tree state.
    4567          156312 :         nsCOMPtr<nsIContent> child = tmp->mAttrsAndChildren.TakeChildAt(childCount);
    4568           78156 :         if (childCount == 0) {
    4569           25141 :           tmp->mFirstChild = nsnull;
    4570                 :         }
    4571           78156 :         child->UnbindFromTree();
    4572                 :       }
    4573                 :     }
    4574           10754 :   } else if (!tmp->GetParent() && tmp->mAttrsAndChildren.ChildCount()) {
    4575             179 :     ContentUnbinder::Append(tmp);
    4576                 :   } /* else {
    4577                 :     The subtree root will end up to a ContentUnbinder, and that will
    4578                 :     unbind the child nodes.
    4579                 :   } */
    4580                 : 
    4581                 :   // Unlink any DOM slots of interest.
    4582                 :   {
    4583           37985 :     nsDOMSlots *slots = tmp->GetExistingDOMSlots();
    4584           37985 :     if (slots) {
    4585            3315 :       slots->Unlink(tmp->IsXUL());
    4586                 :     }
    4587                 :   }
    4588                 : 
    4589                 :   {
    4590                 :     nsIDocument *doc;
    4591           37985 :     if (!tmp->GetNodeParent() && (doc = tmp->OwnerDoc())) {
    4592           22127 :       doc->BindingManager()->RemovedFromDocument(tmp, doc);
    4593                 :     }
    4594                 :   }
    4595           37985 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    4596                 : 
    4597           45891 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGenericElement)
    4598           45891 :   nsINode::Trace(tmp, aCallback, aClosure);
    4599           45891 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
    4600                 : 
    4601                 : void
    4602               0 : nsGenericElement::MarkUserData(void* aObject, nsIAtom* aKey, void* aChild,
    4603                 :                                void* aData)
    4604                 : {
    4605               0 :   PRUint32* gen = static_cast<PRUint32*>(aData);
    4606               0 :   xpc_MarkInCCGeneration(static_cast<nsISupports*>(aChild), *gen);
    4607               0 : }
    4608                 : 
    4609                 : void
    4610               0 : nsGenericElement::MarkUserDataHandler(void* aObject, nsIAtom* aKey,
    4611                 :                                       void* aChild, void* aData)
    4612                 : {
    4613                 :   nsCOMPtr<nsIXPConnectWrappedJS> wjs =
    4614               0 :     do_QueryInterface(static_cast<nsISupports*>(aChild));
    4615               0 :   xpc_UnmarkGrayObject(wjs);
    4616               0 : }
    4617                 : 
    4618                 : void
    4619           22838 : nsGenericElement::MarkNodeChildren(nsINode* aNode)
    4620                 : {
    4621           22838 :   JSObject* o = GetJSObjectChild(aNode);
    4622           22838 :   xpc_UnmarkGrayObject(o);
    4623                 : 
    4624           22838 :   nsEventListenerManager* elm = aNode->GetListenerManager(false);
    4625           22838 :   if (elm) {
    4626               0 :     elm->UnmarkGrayJSListeners();
    4627                 :   }
    4628                 : 
    4629           22838 :   if (aNode->HasProperties()) {
    4630               0 :     nsIDocument* ownerDoc = aNode->OwnerDoc();
    4631                 :     ownerDoc->PropertyTable(DOM_USER_DATA)->
    4632                 :       Enumerate(aNode, nsGenericElement::MarkUserData,
    4633               0 :                 &nsCCUncollectableMarker::sGeneration);
    4634                 :     ownerDoc->PropertyTable(DOM_USER_DATA_HANDLER)->
    4635                 :       Enumerate(aNode, nsGenericElement::MarkUserDataHandler,
    4636               0 :                 &nsCCUncollectableMarker::sGeneration);
    4637                 :   }
    4638           22838 : }
    4639                 : 
    4640                 : nsINode*
    4641            1935 : FindOptimizableSubtreeRoot(nsINode* aNode)
    4642                 : {
    4643                 :   nsINode* p;
    4644            7470 :   while ((p = aNode->GetNodeParent())) {
    4645            3600 :     if (UnoptimizableCCNode(aNode)) {
    4646               0 :       return nsnull;
    4647                 :     }
    4648            3600 :     aNode = p;
    4649                 :   }
    4650                 :   
    4651            1935 :   if (UnoptimizableCCNode(aNode)) {
    4652               0 :     return nsnull;
    4653                 :   }
    4654            1935 :   return aNode;
    4655                 : }
    4656                 : 
    4657                 : nsAutoTArray<nsINode*, 1020>* gCCBlackMarkedNodes = nsnull;
    4658                 : 
    4659                 : void
    4660            1910 : ClearBlackMarkedNodes()
    4661                 : {
    4662            1910 :   if (!gCCBlackMarkedNodes) {
    4663            1889 :     return;
    4664                 :   }
    4665              21 :   PRUint32 len = gCCBlackMarkedNodes->Length();
    4666             222 :   for (PRUint32 i = 0; i < len; ++i) {
    4667             201 :     nsINode* n = gCCBlackMarkedNodes->ElementAt(i);
    4668             201 :     n->SetCCMarkedRoot(false);
    4669             201 :     n->SetInCCBlackTree(false);
    4670                 :   }
    4671              21 :   delete gCCBlackMarkedNodes;
    4672              21 :   gCCBlackMarkedNodes = nsnull;
    4673                 : }
    4674                 : 
    4675                 : // static
    4676                 : bool
    4677           97084 : nsGenericElement::CanSkipInCC(nsINode* aNode)
    4678                 : {
    4679                 :   // Don't try to optimize anything during shutdown.
    4680           97084 :   if (nsCCUncollectableMarker::sGeneration == 0) {
    4681           68968 :     return false;
    4682                 :   }
    4683                 : 
    4684                 :   // Bail out early if aNode is somewhere in anonymous content,
    4685                 :   // or otherwise unusual.
    4686           28116 :   if (UnoptimizableCCNode(aNode)) {
    4687               0 :     return false;
    4688                 :   }
    4689                 : 
    4690           28116 :   nsIDocument* currentDoc = aNode->GetCurrentDoc();
    4691           56232 :   if (currentDoc &&
    4692           28116 :       nsCCUncollectableMarker::InGeneration(currentDoc->GetMarkedCCGeneration())) {
    4693            1890 :     return !NeedsScriptTraverse(aNode);
    4694                 :   }
    4695                 : 
    4696                 :   nsINode* root =
    4697                 :     currentDoc ? static_cast<nsINode*>(currentDoc) :
    4698           26226 :                  FindOptimizableSubtreeRoot(aNode);
    4699           26226 :   if (!root) {
    4700               0 :     return false;
    4701                 :   }
    4702                 :   
    4703                 :   // Subtree has been traversed already.
    4704           26226 :   if (root->CCMarkedRoot()) {
    4705           26025 :     return root->InCCBlackTree() && !NeedsScriptTraverse(aNode);
    4706                 :   }
    4707                 : 
    4708             201 :   if (!gCCBlackMarkedNodes) {
    4709              21 :     gCCBlackMarkedNodes = new nsAutoTArray<nsINode*, 1020>;
    4710                 :   }
    4711                 : 
    4712                 :   // nodesToUnpurple contains nodes which will be removed
    4713                 :   // from the purple buffer if the DOM tree is black.
    4714             402 :   nsAutoTArray<nsIContent*, 1020> nodesToUnpurple;
    4715                 :   // grayNodes need script traverse, so they aren't removed from
    4716                 :   // the purple buffer, but are marked to be in black subtree so that
    4717                 :   // traverse is faster.
    4718             402 :   nsAutoTArray<nsINode*, 1020> grayNodes;
    4719                 : 
    4720             201 :   bool foundBlack = root->IsBlack();
    4721             201 :   if (root != currentDoc) {
    4722               0 :     currentDoc = nsnull;
    4723               0 :     if (NeedsScriptTraverse(root)) {
    4724               0 :       grayNodes.AppendElement(root);
    4725               0 :     } else if (static_cast<nsIContent*>(root)->IsPurple()) {
    4726               0 :       nodesToUnpurple.AppendElement(static_cast<nsIContent*>(root));
    4727                 :     }
    4728                 :   }
    4729                 : 
    4730                 :   // Traverse the subtree and check if we could know without CC
    4731                 :   // that it is black.
    4732                 :   // Note, this traverse is non-virtual and inline, so it should be a lot faster
    4733                 :   // than CC's generic traverse.
    4734           33052 :   for (nsIContent* node = root->GetFirstChild(); node;
    4735           32851 :        node = node->GetNextNode(root)) {
    4736           32859 :     foundBlack = foundBlack || node->IsBlack();
    4737           32859 :     if (foundBlack && currentDoc) {
    4738                 :       // If we can mark the whole document black, no need to optimize
    4739                 :       // so much, since when the next purple node in the document will be
    4740                 :       // handled, it is fast to check that currentDoc is in CCGeneration.
    4741               8 :       break;
    4742                 :     }
    4743           32851 :     if (NeedsScriptTraverse(node)) {
    4744                 :       // Gray nodes need real CC traverse.
    4745               0 :       grayNodes.AppendElement(node);
    4746           32851 :     } else if (node->IsPurple()) {
    4747           26025 :       nodesToUnpurple.AppendElement(node);
    4748                 :     }
    4749                 :   }
    4750                 : 
    4751             201 :   root->SetCCMarkedRoot(true);
    4752             201 :   root->SetInCCBlackTree(foundBlack);
    4753             201 :   gCCBlackMarkedNodes->AppendElement(root);
    4754                 : 
    4755             201 :   if (!foundBlack) {
    4756             193 :     return false;
    4757                 :   }
    4758                 : 
    4759               8 :   if (currentDoc) {
    4760                 :     // Special case documents. If we know the document is black,
    4761                 :     // we can mark the document to be in CCGeneration.
    4762                 :     currentDoc->
    4763               8 :       MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration);
    4764                 :   } else {
    4765               0 :     for (PRUint32 i = 0; i < grayNodes.Length(); ++i) {
    4766               0 :       nsINode* node = grayNodes[i];
    4767               0 :       node->SetInCCBlackTree(true);
    4768                 :     }
    4769               0 :     gCCBlackMarkedNodes->AppendElements(grayNodes);
    4770                 :   }
    4771                 : 
    4772                 :   // Subtree is black, we can remove non-gray purple nodes from
    4773                 :   // purple buffer.
    4774               8 :   for (PRUint32 i = 0; i < nodesToUnpurple.Length(); ++i) {
    4775               0 :     nsIContent* purple = nodesToUnpurple[i];
    4776                 :     // Can't remove currently handled purple node.
    4777               0 :     if (purple != aNode) {
    4778               0 :       purple->RemovePurple();
    4779                 :     }
    4780                 :   }
    4781               8 :   return !NeedsScriptTraverse(aNode);
    4782                 : }
    4783                 : 
    4784                 : nsAutoTArray<nsINode*, 1020>* gPurpleRoots = nsnull;
    4785                 : 
    4786             276 : void ClearPurpleRoots()
    4787                 : {
    4788             276 :   if (!gPurpleRoots) {
    4789              56 :     return;
    4790                 :   }
    4791             220 :   PRUint32 len = gPurpleRoots->Length();
    4792            2386 :   for (PRUint32 i = 0; i < len; ++i) {
    4793            2166 :     nsINode* n = gPurpleRoots->ElementAt(i);
    4794            2166 :     n->SetIsPurpleRoot(false);
    4795                 :   }
    4796             220 :   delete gPurpleRoots;
    4797             220 :   gPurpleRoots = nsnull;
    4798                 : }
    4799                 : 
    4800                 : static bool
    4801          285388 : ShouldClearPurple(nsIContent* aContent)
    4802                 : {
    4803          285388 :   if (aContent && aContent->IsPurple()) {
    4804          248834 :     return true;
    4805                 :   }
    4806                 : 
    4807           36554 :   JSObject* o = GetJSObjectChild(aContent);
    4808           36554 :   if (o && xpc_IsGrayGCThing(o)) {
    4809               0 :     return true;
    4810                 :   }
    4811                 : 
    4812           36554 :   if (aContent->HasListenerManager()) {
    4813               0 :     return true;
    4814                 :   }
    4815                 : 
    4816           36554 :   return aContent->HasProperties();
    4817                 : }
    4818                 : 
    4819                 : // If aNode is not optimizable, but is an element
    4820                 : // with a frame in a document which has currently active presshell,
    4821                 : // we can act as if it was optimizable. When the primary frame dies, aNode
    4822                 : // will end up to the purple buffer because of the refcount change.
    4823                 : bool
    4824               0 : NodeHasActiveFrame(nsIDocument* aCurrentDoc, nsINode* aNode)
    4825                 : {
    4826               0 :   return aCurrentDoc->GetShell() && aNode->IsElement() &&
    4827               0 :          aNode->AsElement()->GetPrimaryFrame();
    4828                 : }
    4829                 : 
    4830                 : // CanSkip checks if aNode is black, and if it is, returns
    4831                 : // true. If aNode is in a black DOM tree, CanSkip may also remove other objects
    4832                 : // from purple buffer and unmark event listeners and user data.
    4833                 : // If the root of the DOM tree is a document, less optimizations are done
    4834                 : // since checking the blackness of the current document is usually fast and we
    4835                 : // don't want slow down such common cases.
    4836                 : bool
    4837          318556 : nsGenericElement::CanSkip(nsINode* aNode, bool aRemovingAllowed)
    4838                 : {
    4839                 :   // Don't try to optimize anything during shutdown.
    4840          318556 :   if (nsCCUncollectableMarker::sGeneration == 0) {
    4841             579 :     return false;
    4842                 :   }
    4843                 : 
    4844          317977 :   bool unoptimizable = UnoptimizableCCNode(aNode);
    4845          317977 :   nsIDocument* currentDoc = aNode->GetCurrentDoc();
    4846          654777 :   if (currentDoc &&
    4847          316042 :       nsCCUncollectableMarker::InGeneration(currentDoc->GetMarkedCCGeneration()) &&
    4848           20758 :       (!unoptimizable || NodeHasActiveFrame(currentDoc, aNode))) {
    4849           20758 :     MarkNodeChildren(aNode);
    4850           20758 :     return true;
    4851                 :   }
    4852          297219 :   if (unoptimizable) {
    4853               0 :     return false;
    4854                 :   }
    4855                 : 
    4856                 :   nsINode* root = currentDoc ? static_cast<nsINode*>(currentDoc) :
    4857          297219 :                                FindOptimizableSubtreeRoot(aNode);
    4858          297219 :   if (!root) {
    4859               0 :     return false;
    4860                 :   }
    4861                 :  
    4862                 :   // Subtree has been traversed already, and aNode
    4863                 :   // wasn't removed from purple buffer. No need to do more here.
    4864          297219 :   if (root->IsPurpleRoot()) {
    4865          294943 :     return false;
    4866                 :   }
    4867                 : 
    4868                 :   // nodesToClear contains nodes which are either purple or
    4869                 :   // gray.
    4870            4552 :   nsAutoTArray<nsIContent*, 1020> nodesToClear;
    4871                 : 
    4872            2276 :   bool foundBlack = root->IsBlack();
    4873            2276 :   if (root != currentDoc) {
    4874              45 :     currentDoc = nsnull;
    4875              45 :     if (ShouldClearPurple(static_cast<nsIContent*>(root))) {
    4876              45 :       nodesToClear.AppendElement(static_cast<nsIContent*>(root));
    4877                 :     }
    4878                 :   }
    4879                 : 
    4880                 :   // Traverse the subtree and check if we could know without CC
    4881                 :   // that it is black.
    4882                 :   // Note, this traverse is non-virtual and inline, so it should be a lot faster
    4883                 :   // than CC's generic traverse.
    4884          287619 :   for (nsIContent* node = root->GetFirstChild(); node;
    4885          285343 :        node = node->GetNextNode(root)) {
    4886          285453 :     foundBlack = foundBlack || node->IsBlack();
    4887          285453 :     if (foundBlack) {
    4888             110 :       if (currentDoc) {
    4889                 :         // If we can mark the whole document black, no need to optimize
    4890                 :         // so much, since when the next purple node in the document will be
    4891                 :         // handled, it is fast to check that the currentDoc is in CCGeneration.
    4892             110 :         break;
    4893                 :       }
    4894                 :       // No need to put stuff to the nodesToClear array, if we can clear it
    4895                 :       // already here.
    4896               0 :       if (node->IsPurple() && (node != aNode || aRemovingAllowed)) {
    4897               0 :         node->RemovePurple();
    4898                 :       }
    4899               0 :       MarkNodeChildren(node);
    4900          285343 :     } else if (ShouldClearPurple(node)) {
    4901                 :       // Collect interesting nodes which we can clear if we find that
    4902                 :       // they are kept alive in a black tree.
    4903          248789 :       nodesToClear.AppendElement(node);
    4904                 :     }
    4905                 :   }
    4906                 : 
    4907            2276 :   if (!currentDoc || !foundBlack) { 
    4908            2166 :     if (!gPurpleRoots) {
    4909             220 :       gPurpleRoots = new nsAutoTArray<nsINode*, 1020>();
    4910                 :     }
    4911            2166 :     root->SetIsPurpleRoot(true);
    4912            2166 :     gPurpleRoots->AppendElement(root);
    4913                 :   }
    4914                 : 
    4915            2276 :   if (!foundBlack) {
    4916            2166 :     return false;
    4917                 :   }
    4918                 : 
    4919             110 :   if (currentDoc) {
    4920                 :     // Special case documents. If we know the document is black,
    4921                 :     // we can mark the document to be in CCGeneration.
    4922                 :     currentDoc->
    4923             110 :       MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration);
    4924             110 :     MarkNodeChildren(currentDoc);
    4925                 :   }
    4926                 : 
    4927                 :   // Subtree is black, so we can remove purple nodes from
    4928                 :   // purple buffer and mark stuff that to be certainly alive.
    4929             110 :   for (PRUint32 i = 0; i < nodesToClear.Length(); ++i) {
    4930               0 :     nsIContent* n = nodesToClear[i];
    4931               0 :     MarkNodeChildren(n);
    4932                 :     // Can't remove currently handled purple node,
    4933                 :     // unless aRemovingAllowed is true. 
    4934               0 :     if ((n != aNode || aRemovingAllowed) && n->IsPurple()) {
    4935               0 :       n->RemovePurple();
    4936                 :     }
    4937                 :   }
    4938             110 :   return true;
    4939                 : }
    4940                 : 
    4941                 : bool
    4942          225591 : nsGenericElement::CanSkipThis(nsINode* aNode)
    4943                 : {
    4944          225591 :   if (nsCCUncollectableMarker::sGeneration == 0) {
    4945          159882 :     return false;
    4946                 :   }
    4947           65709 :   if (aNode->IsBlack()) {
    4948               0 :     return true;
    4949                 :   }
    4950           65709 :   nsIDocument* c = aNode->GetCurrentDoc();
    4951                 :   return 
    4952           65709 :     ((c && nsCCUncollectableMarker::InGeneration(c->GetMarkedCCGeneration())) ||
    4953          131418 :      aNode->InCCBlackTree()) && !NeedsScriptTraverse(aNode);
    4954                 : }
    4955                 : 
    4956                 : void
    4957            1404 : nsGenericElement::InitCCCallbacks()
    4958                 : {
    4959            1404 :   nsCycleCollector_setForgetSkippableCallback(ClearPurpleRoots);
    4960            1404 :   nsCycleCollector_setBeforeUnlinkCallback(ClearBlackMarkedNodes);
    4961            1404 : }
    4962                 : 
    4963          120993 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGenericElement)
    4964          120993 :   return nsGenericElement::CanSkip(tmp, aRemovingAllowed);
    4965                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
    4966                 : 
    4967           34394 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGenericElement)
    4968           34394 :   return nsGenericElement::CanSkipInCC(tmp);
    4969                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
    4970                 : 
    4971          149113 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGenericElement)
    4972          149113 :   return nsGenericElement::CanSkipThis(tmp);
    4973                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
    4974                 : 
    4975                 : static const char* kNSURIs[] = {
    4976                 :   " ([none])",
    4977                 :   " (xmlns)",
    4978                 :   " (xml)",
    4979                 :   " (xhtml)",
    4980                 :   " (XLink)",
    4981                 :   " (XSLT)",
    4982                 :   " (XBL)",
    4983                 :   " (MathML)",
    4984                 :   " (RDF)",
    4985                 :   " (XUL)",
    4986                 :   " (SVG)",
    4987                 :   " (XML Events)"
    4988                 : };
    4989                 : 
    4990           45877 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGenericElement)
    4991           45877 :   if (NS_UNLIKELY(cb.WantDebugInfo())) {
    4992                 :     char name[512];
    4993               0 :     PRUint32 nsid = tmp->GetNameSpaceID();
    4994               0 :     nsAtomCString localName(tmp->NodeInfo()->NameAtom());
    4995               0 :     nsCAutoString uri;
    4996               0 :     if (tmp->OwnerDoc()->GetDocumentURI()) {
    4997               0 :       tmp->OwnerDoc()->GetDocumentURI()->GetSpec(uri);
    4998                 :     }
    4999                 : 
    5000               0 :     nsAutoString id;
    5001               0 :     nsIAtom* idAtom = tmp->GetID();
    5002               0 :     if (idAtom) {
    5003               0 :       id.AppendLiteral(" id='");
    5004               0 :       id.Append(nsDependentAtomString(idAtom));
    5005               0 :       id.AppendLiteral("'");
    5006                 :     }
    5007                 : 
    5008               0 :     nsAutoString classes;
    5009               0 :     const nsAttrValue* classAttrValue = tmp->GetClasses();
    5010               0 :     if (classAttrValue) {
    5011               0 :       classes.AppendLiteral(" class='");
    5012               0 :       nsAutoString classString;
    5013               0 :       classAttrValue->ToString(classString);
    5014               0 :       classes.Append(classString);
    5015               0 :       classes.AppendLiteral("'");
    5016                 :     }
    5017                 : 
    5018               0 :     const char* nsuri = nsid < ArrayLength(kNSURIs) ? kNSURIs[nsid] : "";
    5019                 :     PR_snprintf(name, sizeof(name), "nsGenericElement%s %s%s%s %s",
    5020                 :                 nsuri,
    5021                 :                 localName.get(),
    5022               0 :                 NS_ConvertUTF16toUTF8(id).get(),
    5023               0 :                 NS_ConvertUTF16toUTF8(classes).get(),
    5024               0 :                 uri.get());
    5025                 :     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), sizeof(nsGenericElement),
    5026               0 :                               name);
    5027                 :   }
    5028                 :   else {
    5029           45877 :     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGenericElement, tmp->mRefCnt.get())
    5030                 :   }
    5031                 : 
    5032                 :   // Always need to traverse script objects, so do that before we check
    5033                 :   // if we're uncollectable.
    5034           45877 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
    5035                 : 
    5036           45877 :   if (!nsINode::Traverse(tmp, cb)) {
    5037               0 :     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
    5038                 :   }
    5039                 : 
    5040           45877 :   tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb);
    5041                 : 
    5042           45877 :   if (tmp->HasProperties() && tmp->IsXUL()) {
    5043                 :     nsISupports* property =
    5044                 :       static_cast<nsISupports*>
    5045               0 :                  (tmp->GetProperty(nsGkAtoms::contextmenulistener));
    5046               0 :     cb.NoteXPCOMChild(property);
    5047                 :     property = static_cast<nsISupports*>
    5048               0 :                           (tmp->GetProperty(nsGkAtoms::popuplistener));
    5049               0 :     cb.NoteXPCOMChild(property);
    5050                 :   }
    5051                 : 
    5052                 :   // Traverse attribute names and child content.
    5053                 :   {
    5054                 :     PRUint32 i;
    5055           45877 :     PRUint32 attrs = tmp->mAttrsAndChildren.AttrCount();
    5056           58439 :     for (i = 0; i < attrs; i++) {
    5057           12562 :       const nsAttrName* name = tmp->mAttrsAndChildren.AttrNameAt(i);
    5058           12562 :       if (!name->IsAtom()) {
    5059            1885 :         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
    5060                 :                                            "mAttrsAndChildren[i]->NodeInfo()");
    5061            1885 :         cb.NoteXPCOMChild(name->NodeInfo());
    5062                 :       }
    5063                 :     }
    5064                 : 
    5065           45877 :     PRUint32 kids = tmp->mAttrsAndChildren.ChildCount();
    5066          179684 :     for (i = 0; i < kids; i++) {
    5067          133807 :       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAttrsAndChildren[i]");
    5068          133807 :       cb.NoteXPCOMChild(tmp->mAttrsAndChildren.GetSafeChildAt(i));
    5069                 :     }
    5070                 :   }
    5071                 : 
    5072                 :   // Traverse any DOM slots of interest.
    5073                 :   {
    5074           45877 :     nsDOMSlots *slots = tmp->GetExistingDOMSlots();
    5075           45877 :     if (slots) {
    5076            3503 :       slots->Traverse(cb, tmp->IsXUL());
    5077                 :     }
    5078                 :   }
    5079           45877 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    5080                 : 
    5081                 : 
    5082         1857794 : NS_INTERFACE_MAP_BEGIN(nsGenericElement)
    5083         1857794 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    5084         1846872 :   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericElement)
    5085          329129 :   NS_INTERFACE_MAP_ENTRY(Element)
    5086          329129 :   NS_INTERFACE_MAP_ENTRY(nsIContent)
    5087           56825 :   NS_INTERFACE_MAP_ENTRY(nsINode)
    5088           45890 :   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
    5089           45715 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNSElement, new nsNSElementTearoff(this))
    5090           45711 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
    5091                 :                                  new nsNodeSupportsWeakRefTearoff(this))
    5092           45711 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNodeSelector,
    5093                 :                                  new nsNodeSelectorTearoff(this))
    5094           45711 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
    5095                 :                                  new nsNode3Tearoff(this))
    5096           45711 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsITouchEventReceiver,
    5097                 :                                  new nsTouchEventReceiverTearoff(this))
    5098           45711 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIInlineEventHandlers,
    5099                 :                                  new nsInlineEventHandlersTearoff(this))
    5100                 :   // nsNodeSH::PreCreate() depends on the identity pointer being the
    5101                 :   // same as nsINode (which nsIContent inherits), so if you change the
    5102                 :   // below line, make sure nsNodeSH::PreCreate() still does the right
    5103                 :   // thing!
    5104           45711 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
    5105           38918 : NS_INTERFACE_MAP_END
    5106                 : 
    5107          717438 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGenericElement)
    5108          717428 : NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsGenericElement,
    5109                 :                                               nsNodeUtils::LastRelease(this))
    5110                 : 
    5111                 : nsresult
    5112             993 : nsGenericElement::PostQueryInterface(REFNSIID aIID, void** aInstancePtr)
    5113                 : {
    5114                 :   return OwnerDoc()->BindingManager()->GetBindingImplementation(this, aIID,
    5115             993 :                                                                 aInstancePtr);
    5116                 : }
    5117                 : 
    5118                 : //----------------------------------------------------------------------
    5119                 : nsresult
    5120               0 : nsGenericElement::LeaveLink(nsPresContext* aPresContext)
    5121                 : {
    5122               0 :   nsILinkHandler *handler = aPresContext->GetLinkHandler();
    5123               0 :   if (!handler) {
    5124               0 :     return NS_OK;
    5125                 :   }
    5126                 : 
    5127               0 :   return handler->OnLeaveLink();
    5128                 : }
    5129                 : 
    5130                 : nsresult
    5131               0 : nsGenericElement::AddScriptEventListener(nsIAtom* aEventName,
    5132                 :                                          const nsAString& aValue,
    5133                 :                                          bool aDefer)
    5134                 : {
    5135               0 :   nsIDocument *ownerDoc = OwnerDoc();
    5136               0 :   if (ownerDoc->IsLoadedAsData()) {
    5137                 :     // Make this a no-op rather than throwing an error to avoid
    5138                 :     // the error causing problems setting the attribute.
    5139               0 :     return NS_OK;
    5140                 :   }
    5141                 : 
    5142               0 :   NS_PRECONDITION(aEventName, "Must have event name!");
    5143               0 :   bool defer = true;
    5144                 :   nsEventListenerManager* manager = GetEventListenerManagerForAttr(aEventName,
    5145               0 :                                                                    &defer);
    5146               0 :   if (!manager) {
    5147               0 :     return NS_OK;
    5148                 :   }
    5149                 : 
    5150               0 :   defer = defer && aDefer; // only defer if everyone agrees...
    5151               0 :   PRUint32 lang = GetScriptTypeID();
    5152                 :   manager->AddScriptEventListener(aEventName, aValue, lang, defer,
    5153               0 :                                   !nsContentUtils::IsChromeDoc(ownerDoc));
    5154               0 :   return NS_OK;
    5155                 : }
    5156                 : 
    5157                 : 
    5158                 : //----------------------------------------------------------------------
    5159                 : 
    5160                 : const nsAttrName*
    5161            7795 : nsGenericElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
    5162                 : {
    5163            7795 :   return mAttrsAndChildren.GetExistingAttrNameFromQName(aStr);
    5164                 : }
    5165                 : 
    5166                 : nsresult
    5167             258 : nsGenericElement::CopyInnerTo(nsGenericElement* aDst) const
    5168                 : {
    5169             258 :   PRUint32 i, count = mAttrsAndChildren.AttrCount();
    5170             425 :   for (i = 0; i < count; ++i) {
    5171             167 :     const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
    5172             167 :     const nsAttrValue* value = mAttrsAndChildren.AttrAt(i);
    5173             334 :     nsAutoString valStr;
    5174             167 :     value->ToString(valStr);
    5175                 :     nsresult rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
    5176             167 :                                 name->GetPrefix(), valStr, false);
    5177             167 :     NS_ENSURE_SUCCESS(rv, rv);
    5178                 :   }
    5179                 : 
    5180             258 :   return NS_OK;
    5181                 : }
    5182                 : 
    5183                 : bool
    5184           11455 : nsGenericElement::MaybeCheckSameAttrVal(PRInt32 aNamespaceID,
    5185                 :                                         nsIAtom* aName,
    5186                 :                                         nsIAtom* aPrefix,
    5187                 :                                         const nsAttrValueOrString& aValue,
    5188                 :                                         bool aNotify,
    5189                 :                                         nsAttrValue& aOldValue,
    5190                 :                                         PRUint8* aModType,
    5191                 :                                         bool* aHasListeners)
    5192                 : {
    5193           11455 :   bool modification = false;
    5194                 :   *aHasListeners = aNotify &&
    5195                 :     nsContentUtils::HasMutationListeners(this,
    5196                 :                                          NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
    5197           11455 :                                          this);
    5198                 : 
    5199                 :   // If we have no listeners and aNotify is false, we are almost certainly
    5200                 :   // coming from the content sink and will almost certainly have no previous
    5201                 :   // value.  Even if we do, setting the value is cheap when we have no
    5202                 :   // listeners and don't plan to notify.  The check for aNotify here is an
    5203                 :   // optimization, the check for *aHasListeners is a correctness issue.
    5204           11455 :   if (*aHasListeners || aNotify) {
    5205            1875 :     nsAttrInfo info(GetAttrInfo(aNamespaceID, aName));
    5206            1875 :     if (info.mValue) {
    5207                 :       // Check whether the old value is the same as the new one.  Note that we
    5208                 :       // only need to actually _get_ the old value if we have listeners.
    5209               7 :       if (*aHasListeners) {
    5210                 :         // Need to store the old value.
    5211                 :         //
    5212                 :         // If the current attribute value contains a pointer to some other data
    5213                 :         // structure that gets updated in the process of setting the attribute
    5214                 :         // we'll no longer have the old value of the attribute. Therefore, we
    5215                 :         // should serialize the attribute value now to keep a snapshot.
    5216                 :         //
    5217                 :         // We have to serialize the value anyway in order to create the
    5218                 :         // mutation event so there's no cost in doing it now.
    5219               0 :         aOldValue.SetToSerialized(*info.mValue);
    5220                 :       }
    5221               7 :       bool valueMatches = aValue.EqualsAsStrings(*info.mValue);
    5222               7 :       if (valueMatches && aPrefix == info.mName->GetPrefix()) {
    5223               1 :         return true;
    5224                 :       }
    5225               6 :       modification = true;
    5226                 :     }
    5227                 :   }
    5228                 :   *aModType = modification ?
    5229                 :     static_cast<PRUint8>(nsIDOMMutationEvent::MODIFICATION) :
    5230           11454 :     static_cast<PRUint8>(nsIDOMMutationEvent::ADDITION);
    5231           11454 :   return false;
    5232                 : }
    5233                 : 
    5234                 : nsresult
    5235           11455 : nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
    5236                 :                           nsIAtom* aPrefix, const nsAString& aValue,
    5237                 :                           bool aNotify)
    5238                 : {
    5239                 :   // Keep this in sync with SetParsedAttr below
    5240                 : 
    5241           11455 :   NS_ENSURE_ARG_POINTER(aName);
    5242           11455 :   NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
    5243                 :                "Don't call SetAttr with unknown namespace");
    5244                 : 
    5245           11455 :   if (!mAttrsAndChildren.CanFitMoreAttrs()) {
    5246               0 :     return NS_ERROR_FAILURE;
    5247                 :   }
    5248                 : 
    5249                 :   PRUint8 modType;
    5250                 :   bool hasListeners;
    5251           22910 :   nsAttrValueOrString value(aValue);
    5252           22910 :   nsAttrValue oldValue;
    5253                 : 
    5254           11455 :   if (MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, value, aNotify,
    5255           11455 :                             oldValue, &modType, &hasListeners)) {
    5256               1 :     return NS_OK;
    5257                 :   }
    5258                 : 
    5259           11454 :   nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
    5260           11454 :   NS_ENSURE_SUCCESS(rv, rv);
    5261                 : 
    5262           11454 :   if (aNotify) {
    5263            1874 :     nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType);
    5264                 :   }
    5265                 : 
    5266                 :   // Hold a script blocker while calling ParseAttribute since that can call
    5267                 :   // out to id-observers
    5268           22908 :   nsAutoScriptBlocker scriptBlocker;
    5269                 : 
    5270           22908 :   nsAttrValue attrValue;
    5271           11454 :   if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
    5272           11078 :     attrValue.SetTo(aValue);
    5273                 :   }
    5274                 : 
    5275                 :   return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
    5276                 :                           attrValue, modType, hasListeners, aNotify,
    5277           11454 :                           kCallAfterSetAttr);
    5278                 : }
    5279                 : 
    5280                 : nsresult
    5281               0 : nsGenericElement::SetParsedAttr(PRInt32 aNamespaceID, nsIAtom* aName,
    5282                 :                                 nsIAtom* aPrefix, nsAttrValue& aParsedValue,
    5283                 :                                 bool aNotify)
    5284                 : {
    5285                 :   // Keep this in sync with SetAttr above
    5286                 : 
    5287               0 :   NS_ENSURE_ARG_POINTER(aName);
    5288               0 :   NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
    5289                 :                "Don't call SetAttr with unknown namespace");
    5290                 : 
    5291               0 :   if (!mAttrsAndChildren.CanFitMoreAttrs()) {
    5292               0 :     return NS_ERROR_FAILURE;
    5293                 :   }
    5294                 : 
    5295                 : 
    5296                 :   PRUint8 modType;
    5297                 :   bool hasListeners;
    5298               0 :   nsAttrValueOrString value(aParsedValue);
    5299               0 :   nsAttrValue oldValue;
    5300                 : 
    5301               0 :   if (MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, value, aNotify,
    5302               0 :                             oldValue, &modType, &hasListeners)) {
    5303               0 :     return NS_OK;
    5304                 :   }
    5305                 : 
    5306               0 :   nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
    5307               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5308                 : 
    5309               0 :   if (aNotify) {
    5310               0 :     nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType);
    5311                 :   }
    5312                 : 
    5313                 :   return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
    5314                 :                           aParsedValue, modType, hasListeners, aNotify,
    5315               0 :                           kCallAfterSetAttr);
    5316                 : }
    5317                 : 
    5318                 : nsresult
    5319           11454 : nsGenericElement::SetAttrAndNotify(PRInt32 aNamespaceID,
    5320                 :                                    nsIAtom* aName,
    5321                 :                                    nsIAtom* aPrefix,
    5322                 :                                    const nsAttrValue& aOldValue,
    5323                 :                                    nsAttrValue& aParsedValue,
    5324                 :                                    PRUint8 aModType,
    5325                 :                                    bool aFireMutation,
    5326                 :                                    bool aNotify,
    5327                 :                                    bool aCallAfterSetAttr)
    5328                 : {
    5329                 :   nsresult rv;
    5330                 : 
    5331           11454 :   nsIDocument* document = GetCurrentDoc();
    5332           22908 :   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
    5333                 : 
    5334           11454 :   nsMutationGuard::DidMutate();
    5335                 : 
    5336                 :   // Copy aParsedValue for later use since it will be lost when we call
    5337                 :   // SetAndTakeMappedAttr below
    5338           22908 :   nsAttrValue aValueForAfterSetAttr;
    5339           11454 :   if (aCallAfterSetAttr) {
    5340           11454 :     aValueForAfterSetAttr.SetTo(aParsedValue);
    5341                 :   }
    5342                 : 
    5343           11454 :   if (aNamespaceID == kNameSpaceID_None) {
    5344                 :     // XXXbz Perhaps we should push up the attribute mapping function
    5345                 :     // stuff to nsGenericElement?
    5346            9771 :     if (!IsAttributeMapped(aName) ||
    5347               0 :         !SetMappedAttribute(document, aName, aParsedValue, &rv)) {
    5348            9771 :       rv = mAttrsAndChildren.SetAndTakeAttr(aName, aParsedValue);
    5349                 :     }
    5350                 :   }
    5351                 :   else {
    5352            3366 :     nsCOMPtr<nsINodeInfo> ni;
    5353                 :     ni = mNodeInfo->NodeInfoManager()->GetNodeInfo(aName, aPrefix,
    5354                 :                                                    aNamespaceID,
    5355            1683 :                                                    nsIDOMNode::ATTRIBUTE_NODE);
    5356            1683 :     NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
    5357                 : 
    5358            3366 :     rv = mAttrsAndChildren.SetAndTakeAttr(ni, aParsedValue);
    5359                 :   }
    5360           11454 :   NS_ENSURE_SUCCESS(rv, rv);
    5361                 : 
    5362           11454 :   if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
    5363                 :     nsRefPtr<nsXBLBinding> binding =
    5364             136 :       OwnerDoc()->BindingManager()->GetBinding(this);
    5365              68 :     if (binding) {
    5366               0 :       binding->AttributeChanged(aName, aNamespaceID, false, aNotify);
    5367                 :     }
    5368                 :   }
    5369                 : 
    5370           11454 :   UpdateState(aNotify);
    5371                 : 
    5372           11454 :   if (aNotify) {
    5373            1874 :     nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType);
    5374                 :   }
    5375                 : 
    5376           11454 :   if (aNamespaceID == kNameSpaceID_XMLEvents && 
    5377               0 :       aName == nsGkAtoms::event && mNodeInfo->GetDocument()) {
    5378               0 :     mNodeInfo->GetDocument()->AddXMLEventsContent(this);
    5379                 :   }
    5380           11454 :   if (aCallAfterSetAttr) {
    5381           11454 :     rv = AfterSetAttr(aNamespaceID, aName, &aValueForAfterSetAttr, aNotify);
    5382           11454 :     NS_ENSURE_SUCCESS(rv, rv);
    5383                 :   }
    5384                 : 
    5385           11454 :   if (aFireMutation) {
    5386               0 :     nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
    5387                 : 
    5388               0 :     nsCOMPtr<nsIDOMAttr> attrNode;
    5389               0 :     nsAutoString ns;
    5390               0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
    5391               0 :     GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
    5392               0 :                                getter_AddRefs(attrNode));
    5393               0 :     mutation.mRelatedNode = attrNode;
    5394                 : 
    5395               0 :     mutation.mAttrName = aName;
    5396               0 :     nsAutoString newValue;
    5397               0 :     GetAttr(aNamespaceID, aName, newValue);
    5398               0 :     if (!newValue.IsEmpty()) {
    5399               0 :       mutation.mNewAttrValue = do_GetAtom(newValue);
    5400                 :     }
    5401               0 :     if (!aOldValue.IsEmptyString()) {
    5402               0 :       mutation.mPrevAttrValue = aOldValue.GetAsAtom();
    5403                 :     }
    5404               0 :     mutation.mAttrChange = aModType;
    5405                 : 
    5406               0 :     mozAutoSubtreeModified subtree(OwnerDoc(), this);
    5407               0 :     (new nsAsyncDOMEvent(this, mutation))->RunDOMEventWhenSafe();
    5408                 :   }
    5409                 : 
    5410           11454 :   return NS_OK;
    5411                 : }
    5412                 : 
    5413                 : bool
    5414             185 : nsGenericElement::ParseAttribute(PRInt32 aNamespaceID,
    5415                 :                                  nsIAtom* aAttribute,
    5416                 :                                  const nsAString& aValue,
    5417                 :                                  nsAttrValue& aResult)
    5418                 : {
    5419             185 :   return false;
    5420                 : }
    5421                 : 
    5422                 : bool
    5423               0 : nsGenericElement::SetMappedAttribute(nsIDocument* aDocument,
    5424                 :                                      nsIAtom* aName,
    5425                 :                                      nsAttrValue& aValue,
    5426                 :                                      nsresult* aRetval)
    5427                 : {
    5428               0 :   *aRetval = NS_OK;
    5429               0 :   return false;
    5430                 : }
    5431                 : 
    5432                 : nsEventListenerManager*
    5433               0 : nsGenericElement::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
    5434                 :                                                  bool* aDefer)
    5435                 : {
    5436               0 :   *aDefer = true;
    5437               0 :   return GetListenerManager(true);
    5438                 : }
    5439                 : 
    5440                 : nsGenericElement::nsAttrInfo
    5441            3128 : nsGenericElement::GetAttrInfo(PRInt32 aNamespaceID, nsIAtom* aName) const
    5442                 : {
    5443            3128 :   NS_ASSERTION(nsnull != aName, "must have attribute name");
    5444            3128 :   NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
    5445                 :                "must have a real namespace ID!");
    5446                 : 
    5447            3128 :   PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNamespaceID);
    5448            3128 :   if (index >= 0) {
    5449                 :     return nsAttrInfo(mAttrsAndChildren.AttrNameAt(index),
    5450             855 :                       mAttrsAndChildren.AttrAt(index));
    5451                 :   }
    5452                 : 
    5453            2273 :   return nsAttrInfo(nsnull, nsnull);
    5454                 : }
    5455                 :   
    5456                 : 
    5457                 : bool
    5458            9367 : nsGenericElement::GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
    5459                 :                           nsAString& aResult) const
    5460                 : {
    5461            9367 :   NS_ASSERTION(nsnull != aName, "must have attribute name");
    5462            9367 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
    5463                 :                "must have a real namespace ID!");
    5464                 : 
    5465            9367 :   const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
    5466            9367 :   if (!val) {
    5467                 :     // Since we are returning a success code we'd better do
    5468                 :     // something about the out parameters (someone may have
    5469                 :     // given us a non-empty string).
    5470             283 :     aResult.Truncate();
    5471                 :     
    5472             283 :     return false;
    5473                 :   }
    5474                 : 
    5475            9084 :   val->ToString(aResult);
    5476                 : 
    5477            9084 :   return true;
    5478                 : }
    5479                 : 
    5480                 : bool
    5481            2094 : nsGenericElement::HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const
    5482                 : {
    5483            2094 :   NS_ASSERTION(nsnull != aName, "must have attribute name");
    5484            2094 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
    5485                 :                "must have a real namespace ID!");
    5486                 : 
    5487            2094 :   return mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID) >= 0;
    5488                 : }
    5489                 : 
    5490                 : bool
    5491             692 : nsGenericElement::AttrValueIs(PRInt32 aNameSpaceID,
    5492                 :                               nsIAtom* aName,
    5493                 :                               const nsAString& aValue,
    5494                 :                               nsCaseTreatment aCaseSensitive) const
    5495                 : {
    5496             692 :   NS_ASSERTION(aName, "Must have attr name");
    5497             692 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
    5498                 : 
    5499             692 :   const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
    5500             692 :   return val && val->Equals(aValue, aCaseSensitive);
    5501                 : }
    5502                 : 
    5503                 : bool
    5504               0 : nsGenericElement::AttrValueIs(PRInt32 aNameSpaceID,
    5505                 :                               nsIAtom* aName,
    5506                 :                               nsIAtom* aValue,
    5507                 :                               nsCaseTreatment aCaseSensitive) const
    5508                 : {
    5509               0 :   NS_ASSERTION(aName, "Must have attr name");
    5510               0 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
    5511               0 :   NS_ASSERTION(aValue, "Null value atom");
    5512                 : 
    5513               0 :   const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
    5514               0 :   return val && val->Equals(aValue, aCaseSensitive);
    5515                 : }
    5516                 : 
    5517                 : PRInt32
    5518               3 : nsGenericElement::FindAttrValueIn(PRInt32 aNameSpaceID,
    5519                 :                                   nsIAtom* aName,
    5520                 :                                   AttrValuesArray* aValues,
    5521                 :                                   nsCaseTreatment aCaseSensitive) const
    5522                 : {
    5523               3 :   NS_ASSERTION(aName, "Must have attr name");
    5524               3 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
    5525               3 :   NS_ASSERTION(aValues, "Null value array");
    5526                 :   
    5527               3 :   const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
    5528               3 :   if (val) {
    5529               0 :     for (PRInt32 i = 0; aValues[i]; ++i) {
    5530               0 :       if (val->Equals(*aValues[i], aCaseSensitive)) {
    5531               0 :         return i;
    5532                 :       }
    5533                 :     }
    5534               0 :     return ATTR_VALUE_NO_MATCH;
    5535                 :   }
    5536               3 :   return ATTR_MISSING;
    5537                 : }
    5538                 : 
    5539                 : nsresult
    5540               0 : nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
    5541                 :                             bool aNotify)
    5542                 : {
    5543               0 :   NS_ASSERTION(nsnull != aName, "must have attribute name");
    5544                 : 
    5545               0 :   PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID);
    5546               0 :   if (index < 0) {
    5547               0 :     return NS_OK;
    5548                 :   }
    5549                 : 
    5550               0 :   nsresult rv = BeforeSetAttr(aNameSpaceID, aName, nsnull, aNotify);
    5551               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5552                 : 
    5553               0 :   nsIDocument *document = GetCurrentDoc();
    5554               0 :   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
    5555                 : 
    5556               0 :   if (aNotify) {
    5557                 :     nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName,
    5558               0 :                                      nsIDOMMutationEvent::REMOVAL);
    5559                 :   }
    5560                 : 
    5561                 :   bool hasMutationListeners = aNotify &&
    5562                 :     nsContentUtils::HasMutationListeners(this,
    5563                 :                                          NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
    5564               0 :                                          this);
    5565                 : 
    5566                 :   // Grab the attr node if needed before we remove it from the attr map
    5567               0 :   nsCOMPtr<nsIDOMAttr> attrNode;
    5568               0 :   if (hasMutationListeners) {
    5569               0 :     nsAutoString ns;
    5570               0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
    5571               0 :     GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
    5572               0 :                                getter_AddRefs(attrNode));
    5573                 :   }
    5574                 : 
    5575                 :   // Clear binding to nsIDOMNamedNodeMap
    5576               0 :   nsDOMSlots *slots = GetExistingDOMSlots();
    5577               0 :   if (slots && slots->mAttributeMap) {
    5578               0 :     slots->mAttributeMap->DropAttribute(aNameSpaceID, aName);
    5579                 :   }
    5580                 : 
    5581                 :   // The id-handling code, and in the future possibly other code, need to
    5582                 :   // react to unexpected attribute changes.
    5583               0 :   nsMutationGuard::DidMutate();
    5584                 : 
    5585               0 :   nsAttrValue oldValue;
    5586               0 :   rv = mAttrsAndChildren.RemoveAttrAt(index, oldValue);
    5587               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5588                 : 
    5589               0 :   if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
    5590                 :     nsRefPtr<nsXBLBinding> binding =
    5591               0 :       OwnerDoc()->BindingManager()->GetBinding(this);
    5592               0 :     if (binding) {
    5593               0 :       binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
    5594                 :     }
    5595                 :   }
    5596                 : 
    5597               0 :   UpdateState(aNotify);
    5598                 : 
    5599               0 :   if (aNotify) {
    5600                 :     nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
    5601               0 :                                   nsIDOMMutationEvent::REMOVAL);
    5602                 :   }
    5603                 : 
    5604               0 :   rv = AfterSetAttr(aNameSpaceID, aName, nsnull, aNotify);
    5605               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5606                 : 
    5607               0 :   if (hasMutationListeners) {
    5608               0 :     nsCOMPtr<nsIDOMEventTarget> node = do_QueryObject(this);
    5609               0 :     nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
    5610                 : 
    5611               0 :     mutation.mRelatedNode = attrNode;
    5612               0 :     mutation.mAttrName = aName;
    5613                 : 
    5614               0 :     nsAutoString value;
    5615               0 :     oldValue.ToString(value);
    5616               0 :     if (!value.IsEmpty())
    5617               0 :       mutation.mPrevAttrValue = do_GetAtom(value);
    5618               0 :     mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
    5619                 : 
    5620               0 :     mozAutoSubtreeModified subtree(OwnerDoc(), this);
    5621               0 :     (new nsAsyncDOMEvent(this, mutation))->RunDOMEventWhenSafe();
    5622                 :   }
    5623                 : 
    5624               0 :   return NS_OK;
    5625                 : }
    5626                 : 
    5627                 : const nsAttrName*
    5628            6147 : nsGenericElement::GetAttrNameAt(PRUint32 aIndex) const
    5629                 : {
    5630            6147 :   return mAttrsAndChildren.GetSafeAttrNameAt(aIndex);
    5631                 : }
    5632                 : 
    5633                 : PRUint32
    5634            4270 : nsGenericElement::GetAttrCount() const
    5635                 : {
    5636            4270 :   return mAttrsAndChildren.AttrCount();
    5637                 : }
    5638                 : 
    5639                 : const nsTextFragment*
    5640               0 : nsGenericElement::GetText()
    5641                 : {
    5642               0 :   return nsnull;
    5643                 : }
    5644                 : 
    5645                 : PRUint32
    5646               0 : nsGenericElement::TextLength()
    5647                 : {
    5648                 :   // We can remove this assertion if it turns out to be useful to be able
    5649                 :   // to depend on this returning 0
    5650               0 :   NS_NOTREACHED("called nsGenericElement::TextLength");
    5651                 : 
    5652               0 :   return 0;
    5653                 : }
    5654                 : 
    5655                 : nsresult
    5656               0 : nsGenericElement::SetText(const PRUnichar* aBuffer, PRUint32 aLength,
    5657                 :                           bool aNotify)
    5658                 : {
    5659               0 :   NS_ERROR("called nsGenericElement::SetText");
    5660                 : 
    5661               0 :   return NS_ERROR_FAILURE;
    5662                 : }
    5663                 : 
    5664                 : nsresult
    5665               0 : nsGenericElement::AppendText(const PRUnichar* aBuffer, PRUint32 aLength,
    5666                 :                              bool aNotify)
    5667                 : {
    5668               0 :   NS_ERROR("called nsGenericElement::AppendText");
    5669                 : 
    5670               0 :   return NS_ERROR_FAILURE;
    5671                 : }
    5672                 : 
    5673                 : bool
    5674               0 : nsGenericElement::TextIsOnlyWhitespace()
    5675                 : {
    5676               0 :   return false;
    5677                 : }
    5678                 : 
    5679                 : void
    5680               0 : nsGenericElement::AppendTextTo(nsAString& aResult)
    5681                 : {
    5682                 :   // We can remove this assertion if it turns out to be useful to be able
    5683                 :   // to depend on this appending nothing.
    5684               0 :   NS_NOTREACHED("called nsGenericElement::TextLength");
    5685               0 : }
    5686                 : 
    5687                 : #ifdef DEBUG
    5688                 : void
    5689               0 : nsGenericElement::ListAttributes(FILE* out) const
    5690                 : {
    5691               0 :   PRUint32 index, count = mAttrsAndChildren.AttrCount();
    5692               0 :   for (index = 0; index < count; index++) {
    5693               0 :     nsAutoString buffer;
    5694                 : 
    5695                 :     // name
    5696               0 :     mAttrsAndChildren.AttrNameAt(index)->GetQualifiedName(buffer);
    5697                 : 
    5698                 :     // value
    5699               0 :     buffer.AppendLiteral("=\"");
    5700               0 :     nsAutoString value;
    5701               0 :     mAttrsAndChildren.AttrAt(index)->ToString(value);
    5702               0 :     for (int i = value.Length(); i >= 0; --i) {
    5703               0 :       if (value[i] == PRUnichar('"'))
    5704               0 :         value.Insert(PRUnichar('\\'), PRUint32(i));
    5705                 :     }
    5706               0 :     buffer.Append(value);
    5707               0 :     buffer.AppendLiteral("\"");
    5708                 : 
    5709               0 :     fputs(" ", out);
    5710               0 :     fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
    5711                 :   }
    5712               0 : }
    5713                 : 
    5714                 : void
    5715               0 : nsGenericElement::List(FILE* out, PRInt32 aIndent,
    5716                 :                        const nsCString& aPrefix) const
    5717                 : {
    5718                 :   PRInt32 indent;
    5719               0 :   for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    5720                 : 
    5721               0 :   fputs(aPrefix.get(), out);
    5722                 : 
    5723               0 :   fputs(NS_LossyConvertUTF16toASCII(mNodeInfo->QualifiedName()).get(), out);
    5724                 : 
    5725               0 :   fprintf(out, "@%p", (void *)this);
    5726                 : 
    5727               0 :   ListAttributes(out);
    5728                 : 
    5729               0 :   fprintf(out, " state=[%llx]", State().GetInternalValue());
    5730               0 :   fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
    5731               0 :   if (IsCommonAncestorForRangeInSelection()) {
    5732                 :     nsRange::RangeHashTable* ranges =
    5733               0 :       static_cast<nsRange::RangeHashTable*>(GetProperty(nsGkAtoms::range));
    5734               0 :     fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
    5735                 :   }
    5736               0 :   fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
    5737               0 :   fprintf(out, " refcount=%d<", mRefCnt.get());
    5738                 : 
    5739               0 :   nsIContent* child = GetFirstChild();
    5740               0 :   if (child) {
    5741               0 :     fputs("\n", out);
    5742                 :     
    5743               0 :     for (; child; child = child->GetNextSibling()) {
    5744               0 :       child->List(out, aIndent + 1);
    5745                 :     }
    5746                 : 
    5747               0 :     for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    5748                 :   }
    5749                 : 
    5750               0 :   fputs(">\n", out);
    5751                 :   
    5752               0 :   nsGenericElement* nonConstThis = const_cast<nsGenericElement*>(this);
    5753                 : 
    5754                 :   // XXX sXBL/XBL2 issue! Owner or current document?
    5755               0 :   nsIDocument *document = OwnerDoc();
    5756                 : 
    5757                 :   // Note: not listing nsIAnonymousContentCreator-created content...
    5758                 : 
    5759               0 :   nsBindingManager* bindingManager = document->BindingManager();
    5760               0 :   nsCOMPtr<nsIDOMNodeList> anonymousChildren;
    5761                 :   bindingManager->GetAnonymousNodesFor(nonConstThis,
    5762               0 :                                        getter_AddRefs(anonymousChildren));
    5763                 : 
    5764               0 :   if (anonymousChildren) {
    5765                 :     PRUint32 length;
    5766               0 :     anonymousChildren->GetLength(&length);
    5767               0 :     if (length > 0) {
    5768               0 :       for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    5769               0 :       fputs("anonymous-children<\n", out);
    5770                 : 
    5771               0 :       for (PRUint32 i = 0; i < length; ++i) {
    5772               0 :         nsCOMPtr<nsIDOMNode> node;
    5773               0 :         anonymousChildren->Item(i, getter_AddRefs(node));
    5774               0 :         nsCOMPtr<nsIContent> child = do_QueryInterface(node);
    5775               0 :         child->List(out, aIndent + 1);
    5776                 :       }
    5777                 : 
    5778               0 :       for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    5779               0 :       fputs(">\n", out);
    5780                 :     }
    5781                 :   }
    5782                 : 
    5783               0 :   if (bindingManager->HasContentListFor(nonConstThis)) {
    5784               0 :     nsCOMPtr<nsIDOMNodeList> contentList;
    5785                 :     bindingManager->GetContentListFor(nonConstThis,
    5786               0 :                                       getter_AddRefs(contentList));
    5787                 : 
    5788               0 :     NS_ASSERTION(contentList != nsnull, "oops, binding manager lied");
    5789                 :     
    5790                 :     PRUint32 length;
    5791               0 :     contentList->GetLength(&length);
    5792               0 :     if (length > 0) {
    5793               0 :       for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    5794               0 :       fputs("content-list<\n", out);
    5795                 : 
    5796               0 :       for (PRUint32 i = 0; i < length; ++i) {
    5797               0 :         nsCOMPtr<nsIDOMNode> node;
    5798               0 :         contentList->Item(i, getter_AddRefs(node));
    5799               0 :         nsCOMPtr<nsIContent> child = do_QueryInterface(node);
    5800               0 :         child->List(out, aIndent + 1);
    5801                 :       }
    5802                 : 
    5803               0 :       for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    5804               0 :       fputs(">\n", out);
    5805                 :     }
    5806                 :   }
    5807               0 : }
    5808                 : 
    5809                 : void
    5810               0 : nsGenericElement::DumpContent(FILE* out, PRInt32 aIndent,
    5811                 :                               bool aDumpAll) const
    5812                 : {
    5813                 :   PRInt32 indent;
    5814               0 :   for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    5815                 : 
    5816               0 :   const nsString& buf = mNodeInfo->QualifiedName();
    5817               0 :   fputs("<", out);
    5818               0 :   fputs(NS_LossyConvertUTF16toASCII(buf).get(), out);
    5819                 : 
    5820               0 :   if(aDumpAll) ListAttributes(out);
    5821                 : 
    5822               0 :   fputs(">", out);
    5823                 : 
    5824               0 :   if(aIndent) fputs("\n", out);
    5825                 : 
    5826               0 :   for (nsIContent* child = GetFirstChild();
    5827                 :        child;
    5828               0 :        child = child->GetNextSibling()) {
    5829               0 :     PRInt32 indent = aIndent ? aIndent + 1 : 0;
    5830               0 :     child->DumpContent(out, indent, aDumpAll);
    5831                 :   }
    5832               0 :   for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    5833               0 :   fputs("</", out);
    5834               0 :   fputs(NS_LossyConvertUTF16toASCII(buf).get(), out);
    5835               0 :   fputs(">", out);
    5836                 : 
    5837               0 :   if(aIndent) fputs("\n", out);
    5838               0 : }
    5839                 : #endif
    5840                 : 
    5841                 : PRUint32
    5842          140781 : nsGenericElement::GetChildCount() const
    5843                 : {
    5844          140781 :   return mAttrsAndChildren.ChildCount();
    5845                 : }
    5846                 : 
    5847                 : nsIContent *
    5848            6629 : nsGenericElement::GetChildAt(PRUint32 aIndex) const
    5849                 : {
    5850            6629 :   return mAttrsAndChildren.GetSafeChildAt(aIndex);
    5851                 : }
    5852                 : 
    5853                 : nsIContent * const *
    5854             287 : nsGenericElement::GetChildArray(PRUint32* aChildCount) const
    5855                 : {
    5856             287 :   return mAttrsAndChildren.GetChildArray(aChildCount);
    5857                 : }
    5858                 : 
    5859                 : PRInt32
    5860             607 : nsGenericElement::IndexOf(nsINode* aPossibleChild) const
    5861                 : {
    5862             607 :   return mAttrsAndChildren.IndexOfChild(aPossibleChild);
    5863                 : }
    5864                 : 
    5865                 : nsINode::nsSlots*
    5866            3306 : nsGenericElement::CreateSlots()
    5867                 : {
    5868            3306 :   return new nsDOMSlots();
    5869                 : }
    5870                 : 
    5871                 : bool
    5872               0 : nsGenericElement::CheckHandleEventForLinksPrecondition(nsEventChainVisitor& aVisitor,
    5873                 :                                                        nsIURI** aURI) const
    5874                 : {
    5875               0 :   if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault ||
    5876               0 :       (!NS_IS_TRUSTED_EVENT(aVisitor.mEvent) &&
    5877                 :        (aVisitor.mEvent->message != NS_MOUSE_CLICK) &&
    5878                 :        (aVisitor.mEvent->message != NS_KEY_PRESS) &&
    5879                 :        (aVisitor.mEvent->message != NS_UI_ACTIVATE)) ||
    5880               0 :       !aVisitor.mPresContext ||
    5881                 :       (aVisitor.mEvent->flags & NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS)) {
    5882               0 :     return false;
    5883                 :   }
    5884                 : 
    5885                 :   // Make sure we actually are a link
    5886               0 :   return IsLink(aURI);
    5887                 : }
    5888                 : 
    5889                 : nsresult
    5890               0 : nsGenericElement::PreHandleEventForLinks(nsEventChainPreVisitor& aVisitor)
    5891                 : {
    5892                 :   // Optimisation: return early if this event doesn't interest us.
    5893                 :   // IMPORTANT: this switch and the switch below it must be kept in sync!
    5894               0 :   switch (aVisitor.mEvent->message) {
    5895                 :   case NS_MOUSE_ENTER_SYNTH:
    5896                 :   case NS_FOCUS_CONTENT:
    5897                 :   case NS_MOUSE_EXIT_SYNTH:
    5898                 :   case NS_BLUR_CONTENT:
    5899                 :     break;
    5900                 :   default:
    5901               0 :     return NS_OK;
    5902                 :   }
    5903                 : 
    5904                 :   // Make sure we meet the preconditions before continuing
    5905               0 :   nsCOMPtr<nsIURI> absURI;
    5906               0 :   if (!CheckHandleEventForLinksPrecondition(aVisitor, getter_AddRefs(absURI))) {
    5907               0 :     return NS_OK;
    5908                 :   }
    5909                 : 
    5910               0 :   nsresult rv = NS_OK;
    5911                 : 
    5912                 :   // We do the status bar updates in PreHandleEvent so that the status bar gets
    5913                 :   // updated even if the event is consumed before we have a chance to set it.
    5914               0 :   switch (aVisitor.mEvent->message) {
    5915                 :   // Set the status bar similarly for mouseover and focus
    5916                 :   case NS_MOUSE_ENTER_SYNTH:
    5917               0 :     aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    5918                 :     // FALL THROUGH
    5919                 :   case NS_FOCUS_CONTENT:
    5920               0 :     if (aVisitor.mEvent->eventStructType != NS_FOCUS_EVENT ||
    5921               0 :         !static_cast<nsFocusEvent*>(aVisitor.mEvent)->isRefocus) {
    5922               0 :       nsAutoString target;
    5923               0 :       GetLinkTarget(target);
    5924                 :       nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
    5925               0 :                                   false, true, true);
    5926                 :       // Make sure any ancestor links don't also TriggerLink
    5927               0 :       aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS;
    5928                 :     }
    5929               0 :     break;
    5930                 : 
    5931                 :   case NS_MOUSE_EXIT_SYNTH:
    5932               0 :     aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    5933                 :     // FALL THROUGH
    5934                 :   case NS_BLUR_CONTENT:
    5935               0 :     rv = LeaveLink(aVisitor.mPresContext);
    5936               0 :     if (NS_SUCCEEDED(rv)) {
    5937               0 :       aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS;
    5938                 :     }
    5939               0 :     break;
    5940                 : 
    5941                 :   default:
    5942                 :     // switch not in sync with the optimization switch earlier in this function
    5943               0 :     NS_NOTREACHED("switch statements not in sync");
    5944               0 :     return NS_ERROR_UNEXPECTED;
    5945                 :   }
    5946                 : 
    5947               0 :   return rv;
    5948                 : }
    5949                 : 
    5950                 : nsresult
    5951               0 : nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor)
    5952                 : {
    5953                 :   // Optimisation: return early if this event doesn't interest us.
    5954                 :   // IMPORTANT: this switch and the switch below it must be kept in sync!
    5955               0 :   switch (aVisitor.mEvent->message) {
    5956                 :   case NS_MOUSE_BUTTON_DOWN:
    5957                 :   case NS_MOUSE_CLICK:
    5958                 :   case NS_UI_ACTIVATE:
    5959                 :   case NS_KEY_PRESS:
    5960                 :     break;
    5961                 :   default:
    5962               0 :     return NS_OK;
    5963                 :   }
    5964                 : 
    5965                 :   // Make sure we meet the preconditions before continuing
    5966               0 :   nsCOMPtr<nsIURI> absURI;
    5967               0 :   if (!CheckHandleEventForLinksPrecondition(aVisitor, getter_AddRefs(absURI))) {
    5968               0 :     return NS_OK;
    5969                 :   }
    5970                 : 
    5971               0 :   nsresult rv = NS_OK;
    5972                 : 
    5973               0 :   switch (aVisitor.mEvent->message) {
    5974                 :   case NS_MOUSE_BUTTON_DOWN:
    5975                 :     {
    5976               0 :       if (aVisitor.mEvent->eventStructType == NS_MOUSE_EVENT &&
    5977                 :           static_cast<nsMouseEvent*>(aVisitor.mEvent)->button ==
    5978                 :           nsMouseEvent::eLeftButton) {
    5979                 :         // don't make the link grab the focus if there is no link handler
    5980               0 :         nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler();
    5981               0 :         nsIDocument *document = GetCurrentDoc();
    5982               0 :         if (handler && document) {
    5983               0 :           nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    5984               0 :           if (fm) {
    5985               0 :             aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS;
    5986               0 :             nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
    5987                 :             fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOUSE |
    5988               0 :                                nsIFocusManager::FLAG_NOSCROLL);
    5989                 :           }
    5990                 : 
    5991                 :           nsEventStateManager::SetActiveManager(
    5992               0 :             aVisitor.mPresContext->EventStateManager(), this);
    5993                 :         }
    5994                 :       }
    5995                 :     }
    5996               0 :     break;
    5997                 : 
    5998                 :   case NS_MOUSE_CLICK:
    5999               0 :     if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent)) {
    6000               0 :       nsInputEvent* inputEvent = static_cast<nsInputEvent*>(aVisitor.mEvent);
    6001               0 :       if (inputEvent->isControl || inputEvent->isMeta ||
    6002                 :           inputEvent->isAlt ||inputEvent->isShift) {
    6003               0 :         break;
    6004                 :       }
    6005                 : 
    6006                 :       // The default action is simply to dispatch DOMActivate
    6007               0 :       nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
    6008               0 :       if (shell) {
    6009                 :         // single-click
    6010               0 :         nsEventStatus status = nsEventStatus_eIgnore;
    6011                 :         nsUIEvent actEvent(NS_IS_TRUSTED_EVENT(aVisitor.mEvent),
    6012               0 :                            NS_UI_ACTIVATE, 1);
    6013                 : 
    6014               0 :         rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
    6015               0 :         if (NS_SUCCEEDED(rv)) {
    6016               0 :           aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    6017                 :         }
    6018                 :       }
    6019                 :     }
    6020               0 :     break;
    6021                 : 
    6022                 :   case NS_UI_ACTIVATE:
    6023                 :     {
    6024               0 :       if (aVisitor.mEvent->originalTarget == this) {
    6025               0 :         nsAutoString target;
    6026               0 :         GetLinkTarget(target);
    6027                 :         nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
    6028               0 :                                     true, true, NS_IS_TRUSTED_EVENT(aVisitor.mEvent));
    6029               0 :         aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    6030                 :       }
    6031                 :     }
    6032               0 :     break;
    6033                 : 
    6034                 :   case NS_KEY_PRESS:
    6035                 :     {
    6036               0 :       if (aVisitor.mEvent->eventStructType == NS_KEY_EVENT) {
    6037               0 :         nsKeyEvent* keyEvent = static_cast<nsKeyEvent*>(aVisitor.mEvent);
    6038               0 :         if (keyEvent->keyCode == NS_VK_RETURN) {
    6039               0 :           nsEventStatus status = nsEventStatus_eIgnore;
    6040                 :           rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this,
    6041               0 :                                   false, 0, &status);
    6042               0 :           if (NS_SUCCEEDED(rv)) {
    6043               0 :             aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    6044                 :           }
    6045                 :         }
    6046                 :       }
    6047                 :     }
    6048               0 :     break;
    6049                 : 
    6050                 :   default:
    6051                 :     // switch not in sync with the optimization switch earlier in this function
    6052               0 :     NS_NOTREACHED("switch statements not in sync");
    6053               0 :     return NS_ERROR_UNEXPECTED;
    6054                 :   }
    6055                 : 
    6056               0 :   return rv;
    6057                 : }
    6058                 : 
    6059                 : void
    6060               0 : nsGenericElement::FireNodeRemovedForChildren()
    6061                 : {
    6062               0 :   nsIDocument* doc = OwnerDoc();
    6063                 :   // Optimize the common case
    6064               0 :   if (!nsContentUtils::
    6065               0 :         HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
    6066               0 :     return;
    6067                 :   }
    6068                 : 
    6069               0 :   nsCOMPtr<nsIDocument> owningDoc = doc;
    6070                 : 
    6071               0 :   nsCOMPtr<nsINode> child;
    6072               0 :   for (child = GetFirstChild();
    6073               0 :        child && child->GetNodeParent() == this;
    6074               0 :        child = child->GetNextSibling()) {
    6075               0 :     nsContentUtils::MaybeFireNodeRemoved(child, this, doc);
    6076                 :   }
    6077                 : }
    6078                 : 
    6079                 : void
    6080               0 : nsGenericElement::GetLinkTarget(nsAString& aTarget)
    6081                 : {
    6082               0 :   aTarget.Truncate();
    6083               0 : }
    6084                 : 
    6085                 : // NOTE: The aPresContext pointer is NOT addrefed.
    6086                 : // *aSelectorList might be null even if NS_OK is returned; this
    6087                 : // happens when all the selectors were pseudo-element selectors.
    6088                 : static nsresult
    6089             110 : ParseSelectorList(nsINode* aNode,
    6090                 :                   const nsAString& aSelectorString,
    6091                 :                   nsCSSSelectorList** aSelectorList)
    6092                 : {
    6093             110 :   NS_ENSURE_ARG(aNode);
    6094                 : 
    6095             110 :   nsIDocument* doc = aNode->OwnerDoc();
    6096             220 :   nsCSSParser parser(doc->CSSLoader());
    6097                 : 
    6098                 :   nsCSSSelectorList* selectorList;
    6099                 :   nsresult rv = parser.ParseSelectorString(aSelectorString,
    6100                 :                                            doc->GetDocumentURI(),
    6101                 :                                            0, // XXXbz get the line number!
    6102             110 :                                            &selectorList);
    6103             110 :   NS_ENSURE_SUCCESS(rv, rv);
    6104                 : 
    6105                 :   // Filter out pseudo-element selectors from selectorList
    6106             110 :   nsCSSSelectorList** slot = &selectorList;
    6107             110 :   do {
    6108             110 :     nsCSSSelectorList* cur = *slot;
    6109             110 :     if (cur->mSelectors->IsPseudoElement()) {
    6110               0 :       *slot = cur->mNext;
    6111               0 :       cur->mNext = nsnull;
    6112               0 :       delete cur;
    6113                 :     } else {
    6114             110 :       slot = &cur->mNext;
    6115                 :     }
    6116                 :   } while (*slot);
    6117             110 :   *aSelectorList = selectorList;
    6118                 : 
    6119             110 :   return NS_OK;
    6120                 : }
    6121                 : 
    6122                 : // Actually find elements matching aSelectorList (which must not be
    6123                 : // null) and which are descendants of aRoot and put them in Alist.  If
    6124                 : // onlyFirstMatch, then stop once the first one is found.
    6125                 : template<bool onlyFirstMatch, class T>
    6126             110 : inline static nsresult FindMatchingElements(nsINode* aRoot,
    6127                 :                                             const nsAString& aSelector,
    6128                 :                                             T &aList)
    6129                 : {
    6130             220 :   nsAutoPtr<nsCSSSelectorList> selectorList;
    6131                 :   nsresult rv = ParseSelectorList(aRoot, aSelector,
    6132             110 :                                   getter_Transfers(selectorList));
    6133             110 :   NS_ENSURE_SUCCESS(rv, rv);
    6134             110 :   NS_ENSURE_TRUE(selectorList, NS_OK);
    6135                 : 
    6136             110 :   NS_ASSERTION(selectorList->mSelectors,
    6137                 :                "How can we not have any selectors?");
    6138                 : 
    6139             110 :   nsIDocument* doc = aRoot->OwnerDoc();  
    6140                 :   TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited,
    6141             220 :                                    doc);
    6142             110 :   doc->FlushPendingLinkUpdates();
    6143                 : 
    6144                 :   // Fast-path selectors involving IDs.  We can only do this if aRoot
    6145                 :   // is in the document and the document is not in quirks mode, since
    6146                 :   // ID selectors are case-insensitive in quirks mode.  Also, only do
    6147                 :   // this if selectorList only has one selector, because otherwise
    6148                 :   // ordering the elements correctly is a pain.
    6149             110 :   NS_ASSERTION(aRoot->IsElement() || aRoot->IsNodeOfType(nsINode::eDOCUMENT) ||
    6150                 :                !aRoot->IsInDoc(),
    6151                 :                "The optimization below to check ContentIsDescendantOf only for "
    6152                 :                "elements depends on aRoot being either an element or a "
    6153                 :                "document if it's in the document.");
    6154             110 :   if (aRoot->IsInDoc() &&
    6155                 :       doc->GetCompatibilityMode() != eCompatibility_NavQuirks &&
    6156                 :       !selectorList->mNext &&
    6157                 :       selectorList->mSelectors->mIDList) {
    6158               0 :     nsIAtom* id = selectorList->mSelectors->mIDList->mAtom;
    6159                 :     const nsSmallVoidArray* elements =
    6160               0 :       doc->GetAllElementsForId(nsDependentAtomString(id));
    6161                 : 
    6162                 :     // XXXbz: Should we fall back to the tree walk if aRoot is not the
    6163                 :     // document and |elements| is long, for some value of "long"?
    6164               0 :     if (elements) {
    6165               0 :       for (PRInt32 i = 0; i < elements->Count(); ++i) {
    6166               0 :         Element *element = static_cast<Element*>(elements->ElementAt(i));
    6167               0 :         if (!aRoot->IsElement() ||
    6168                 :             nsContentUtils::ContentIsDescendantOf(element, aRoot)) {
    6169                 :           // We have an element with the right id and it's a descendant
    6170                 :           // of aRoot.  Make sure it really matches the selector.
    6171               0 :           if (nsCSSRuleProcessor::SelectorListMatches(element, matchingContext,
    6172                 :                                                       selectorList)) {
    6173               0 :             aList.AppendElement(element);
    6174                 :             if (onlyFirstMatch) {
    6175               0 :               return NS_OK;
    6176                 :             }
    6177                 :           }
    6178                 :         }
    6179                 :       }
    6180                 :     }
    6181                 : 
    6182                 :     // No elements with this id, or none of them are our descendants,
    6183                 :     // or none of them match.  We're done here.
    6184               0 :     return NS_OK;
    6185                 :   }
    6186                 : 
    6187            5244 :   for (nsIContent* cur = aRoot->GetFirstChild();
    6188                 :        cur;
    6189                 :        cur = cur->GetNextNode(aRoot)) {
    6190            5134 :     if (cur->IsElement() &&
    6191                 :         nsCSSRuleProcessor::SelectorListMatches(cur->AsElement(),
    6192                 :                                                 matchingContext,
    6193                 :                                                 selectorList)) {
    6194             164 :       aList.AppendElement(cur->AsElement());
    6195                 :       if (onlyFirstMatch) {
    6196               0 :         return NS_OK;
    6197                 :       }
    6198                 :     }
    6199                 :   }
    6200                 : 
    6201             110 :   return NS_OK;
    6202                 : }
    6203                 : 
    6204                 : struct ElementHolder {
    6205               0 :   ElementHolder() : mElement(nsnull) {}
    6206               0 :   void AppendElement(Element* aElement) {
    6207               0 :     NS_ABORT_IF_FALSE(!mElement, "Should only get one element");
    6208               0 :     mElement = aElement;
    6209               0 :   }
    6210                 :   Element* mElement;
    6211                 : };
    6212                 : 
    6213                 : /* static */
    6214                 : nsIContent*
    6215               0 : nsGenericElement::doQuerySelector(nsINode* aRoot, const nsAString& aSelector,
    6216                 :                                   nsresult *aResult)
    6217                 : {
    6218               0 :   NS_PRECONDITION(aResult, "Null out param?");
    6219                 : 
    6220               0 :   ElementHolder holder;
    6221               0 :   *aResult = FindMatchingElements<true>(aRoot, aSelector, holder);
    6222                 : 
    6223               0 :   return holder.mElement;
    6224                 : }
    6225                 : 
    6226                 : /* static */
    6227                 : nsresult
    6228             110 : nsGenericElement::doQuerySelectorAll(nsINode* aRoot,
    6229                 :                                      const nsAString& aSelector,
    6230                 :                                      nsIDOMNodeList **aReturn)
    6231                 : {
    6232             110 :   NS_PRECONDITION(aReturn, "Null out param?");
    6233                 : 
    6234             110 :   nsSimpleContentList* contentList = new nsSimpleContentList(aRoot);
    6235             110 :   NS_ENSURE_TRUE(contentList, NS_ERROR_OUT_OF_MEMORY);
    6236             110 :   NS_ADDREF(*aReturn = contentList);
    6237                 :   
    6238             110 :   return FindMatchingElements<false>(aRoot, aSelector, *contentList);
    6239                 : }
    6240                 : 
    6241                 : 
    6242                 : bool
    6243               0 : nsGenericElement::MozMatchesSelector(const nsAString& aSelector, nsresult* aResult)
    6244                 : {
    6245               0 :   nsAutoPtr<nsCSSSelectorList> selectorList;
    6246               0 :   bool matches = false;
    6247                 : 
    6248               0 :   *aResult = ParseSelectorList(this, aSelector, getter_Transfers(selectorList));
    6249                 : 
    6250               0 :   if (NS_SUCCEEDED(*aResult)) {
    6251               0 :     OwnerDoc()->FlushPendingLinkUpdates();
    6252                 :     TreeMatchContext matchingContext(false,
    6253                 :                                      nsRuleWalker::eRelevantLinkUnvisited,
    6254               0 :                                      OwnerDoc());
    6255                 :     matches = nsCSSRuleProcessor::SelectorListMatches(this, matchingContext,
    6256               0 :                                                       selectorList);
    6257                 :   }
    6258                 : 
    6259               0 :   return matches;
    6260                 : }
    6261                 : 
    6262                 : NS_IMETHODIMP
    6263               0 : nsNSElementTearoff::MozMatchesSelector(const nsAString& aSelector, bool* aReturn)
    6264                 : {
    6265               0 :   NS_PRECONDITION(aReturn, "Null out param?");
    6266                 : 
    6267                 :   nsresult rv;
    6268               0 :   *aReturn = mContent->MozMatchesSelector(aSelector, &rv);
    6269                 : 
    6270               0 :   return rv;
    6271                 : }
    6272                 : 
    6273                 : size_t
    6274               0 : nsINode::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
    6275                 : {
    6276               0 :   size_t n = 0;
    6277                 :   nsEventListenerManager* elm =
    6278               0 :     const_cast<nsINode*>(this)->GetListenerManager(false);
    6279               0 :   if (elm) {
    6280               0 :     n += elm->SizeOfIncludingThis(aMallocSizeOf);
    6281                 :   }
    6282                 : 
    6283                 :   // Measurement of the following members may be added later if DMD finds it is
    6284                 :   // worthwhile:
    6285                 :   // - mNodeInfo (Nb: allocated in nsNodeInfo.cpp with a nsFixedSizeAllocator)
    6286                 :   // - mSlots
    6287                 :   //
    6288                 :   // The following members are not measured:
    6289                 :   // - mParent, mNextSibling, mPreviousSibling, mFirstChild: because they're
    6290                 :   //   non-owning
    6291               0 :   return n;
    6292                 : }
    6293                 : 
    6294                 : size_t
    6295               0 : nsGenericElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
    6296                 : {
    6297               0 :   return Element::SizeOfExcludingThis(aMallocSizeOf) +
    6298               0 :          mAttrsAndChildren.SizeOfExcludingThis(aMallocSizeOf);
    6299                 : }
    6300                 : 
    6301                 : static const nsAttrValue::EnumTable kCORSAttributeTable[] = {
    6302                 :   // Order matters here
    6303                 :   // See ParseCORSValue
    6304                 :   { "anonymous",       CORS_ANONYMOUS       },
    6305                 :   { "use-credentials", CORS_USE_CREDENTIALS },
    6306                 :   { 0 }
    6307                 : };
    6308                 : 
    6309                 : /* static */ void
    6310               0 : nsGenericElement::ParseCORSValue(const nsAString& aValue,
    6311                 :                                  nsAttrValue& aResult)
    6312                 : {
    6313                 :   DebugOnly<bool> success =
    6314                 :     aResult.ParseEnumValue(aValue, kCORSAttributeTable, false,
    6315                 :                            // default value is anonymous if aValue is
    6316                 :                            // not a value we understand
    6317               0 :                            &kCORSAttributeTable[0]);
    6318               0 :   MOZ_ASSERT(success);
    6319               0 : }
    6320                 : 
    6321                 : /* static */ CORSMode
    6322               0 : nsGenericElement::StringToCORSMode(const nsAString& aValue)
    6323                 : {
    6324               0 :   if (aValue.IsVoid()) {
    6325               0 :     return CORS_NONE;
    6326                 :   }
    6327                 : 
    6328               0 :   nsAttrValue val;
    6329               0 :   nsGenericElement::ParseCORSValue(aValue, val);
    6330               0 :   return CORSMode(val.GetEnumValue());
    6331                 : }
    6332                 : 
    6333                 : /* static */ CORSMode
    6334               0 : nsGenericElement::AttrValueToCORSMode(const nsAttrValue* aValue)
    6335                 : {
    6336               0 :   if (!aValue) {
    6337               0 :     return CORS_NONE;
    6338                 :   }
    6339                 : 
    6340               0 :   return CORSMode(aValue->GetEnumValue());
    6341                 : }
    6342                 : 
    6343                 : #define EVENT(name_, id_, type_, struct_)                                    \
    6344                 :   NS_IMETHODIMP nsINode::GetOn##name_(JSContext *cx, jsval *vp) {            \
    6345                 :     nsEventListenerManager *elm = GetListenerManager(false);              \
    6346                 :     if (elm) {                                                               \
    6347                 :       elm->GetJSEventListener(nsGkAtoms::on##name_, vp);                     \
    6348                 :     } else {                                                                 \
    6349                 :       *vp = JSVAL_NULL;                                                      \
    6350                 :     }                                                                        \
    6351                 :     return NS_OK;                                                            \
    6352                 :   }                                                                          \
    6353                 :   NS_IMETHODIMP nsINode::SetOn##name_(JSContext *cx, const jsval &v) {       \
    6354                 :     nsEventListenerManager *elm = GetListenerManager(true);               \
    6355                 :     if (!elm) {                                                              \
    6356                 :       return NS_ERROR_OUT_OF_MEMORY;                                         \
    6357                 :     }                                                                        \
    6358                 :                                                                              \
    6359                 :     JSObject *obj = GetWrapper();                                            \
    6360                 :     if (!obj) {                                                              \
    6361                 :       /* Just silently do nothing */                                         \
    6362                 :       return NS_OK;                                                          \
    6363                 :     }                                                                        \
    6364                 :     return elm->SetJSEventListenerToJsval(nsGkAtoms::on##name_, cx, obj, v); \
    6365                 : }
    6366                 : #define TOUCH_EVENT EVENT
    6367                 : #define DOCUMENT_ONLY_EVENT EVENT
    6368                 : #include "nsEventNameList.h"
    6369                 : #undef DOCUMENT_ONLY_EVENT
    6370                 : #undef TOUCH_EVENT
    6371                 : #undef EVENT
    6372                 : 
    6373                 : bool
    6374               0 : nsINode::Contains(const nsINode* aOther) const
    6375                 : {
    6376               0 :   if (aOther == this) {
    6377               0 :     return true;
    6378                 :   }
    6379               0 :   if (!aOther ||
    6380               0 :       OwnerDoc() != aOther->OwnerDoc() ||
    6381               0 :       IsInDoc() != aOther->IsInDoc() ||
    6382               0 :       !(aOther->IsElement() ||
    6383               0 :         aOther->IsNodeOfType(nsINode::eCONTENT)) ||
    6384               0 :       !GetFirstChild()) {
    6385               0 :     return false;
    6386                 :   }
    6387                 : 
    6388               0 :   const nsIContent* other = static_cast<const nsIContent*>(aOther);
    6389               0 :   if (this == OwnerDoc()) {
    6390                 :     // document.contains(aOther) returns true if aOther is in the document,
    6391                 :     // but is not in any anonymous subtree.
    6392                 :     // IsInDoc() check is done already before this.
    6393               0 :     return !other->IsInAnonymousSubtree();
    6394                 :   }
    6395                 : 
    6396               0 :   if (!IsElement() && !IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT)) {
    6397               0 :     return false;
    6398                 :   }
    6399                 : 
    6400               0 :   const nsIContent* thisContent = static_cast<const nsIContent*>(this);
    6401               0 :   if (thisContent->GetBindingParent() != other->GetBindingParent()) {
    6402               0 :     return false;
    6403                 :   }
    6404                 : 
    6405               0 :   return nsContentUtils::ContentIsDescendantOf(other, this);
    6406                 : }
    6407                 : 
    6408                 : nsresult
    6409               0 : nsINode::Contains(nsIDOMNode* aOther, bool* aReturn)
    6410                 : {
    6411               0 :   nsCOMPtr<nsINode> node = do_QueryInterface(aOther);
    6412               0 :   *aReturn = Contains(node);
    6413               0 :   return NS_OK;
    6414            4392 : }

Generated by: LCOV version 1.7