LCOV - app.info - content/base/src/nsGenericElement.cpp

LCOV - code coverage report
| Current view: | directory - content/base/src - nsGenericElement.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 2809 | 1117 | 39.8 %
| Date: | 2012-04-21 | 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          125736 : nsWrapperCache::RemoveExpandoObject()
         178                 : {
         179          125736 :   JSObject *expando = GetExpandoObjectPreserveColor();
         180          125736 :   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          125736 : }
         187                 :
         188                 : //----------------------------------------------------------------------
         189                 :
         190           10423 : nsINode::nsSlots::~nsSlots()
         191                 : {
         192            4587 :   if (mChildNodes) {
         193               0 :     mChildNodes->DropReference();
         194               0 :     NS_RELEASE(mChildNodes);
         195                 :   }
         196                 :
         197            4587 :   if (mWeakReference) {
         198               0 :     mWeakReference->NoticeNodeDestruction();
         199                 :   }
         200           11672 : }
         201                 :
         202                 : void
         203            5477 : nsINode::nsSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
         204                 : {
         205            5477 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildNodes");
         206            5477 :   cb.NoteXPCOMChild(mChildNodes);
         207            5477 : }
         208                 :
         209                 : void
         210            4587 : nsINode::nsSlots::Unlink()
         211                 : {
         212            4587 :   if (mChildNodes) {
         213            1527 :     mChildNodes->DropReference();
         214            1527 :     NS_RELEASE(mChildNodes);
         215                 :   }
         216            4587 : }
         217                 :
         218                 : //----------------------------------------------------------------------
         219                 :
         220          230320 : nsINode::~nsINode()
         221                 : {
         222          115160 :   NS_ASSERTION(!HasSlots(), "nsNodeUtils::LastRelease was not called?");
         223          230320 : }
         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            1251 : nsINode::CreateSlots()
         268                 : {
         269            1251 :   return new nsSlots();
         270                 : }
         271                 :
         272                 : bool
         273           49305 : nsINode::IsEditableInternal() const
         274                 : {
         275           49305 :   if (HasFlag(NODE_IS_EDITABLE)) {
         276                 :     // The node is in an editable contentEditable subtree.
         277               5 :     return true;
         278                 :   }
         279                 :
         280           49300 :   nsIDocument *doc = GetCurrentDoc();
         281                 :
         282                 :   // Check if the node is in a document and the document is in designMode.
         283           49300 :   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           57667 : nsINode::CheckNotNativeAnonymous() const
         428                 : {
         429           57667 :   if (!IsNodeOfType(eCONTENT))
         430            2914 :     return;
         431           54753 :   nsIContent* content = static_cast<const nsIContent *>(this)->GetBindingParent();
         432          109506 :   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             362 : nsINode::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
         521                 : {
         522             362 :   *aOwnerDocument = nsnull;
         523                 :
         524             362 :   nsIDocument *ownerDoc = GetOwnerDocument();
         525                 :
         526             362 :   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           11758 : 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            5369 : 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           10738 :   nsCOMPtr<nsIDocument> document = OwnerDoc();
        1159                 :
        1160                 :   // Do nothing if the element does not belong to a document
        1161            5369 :   if (!document) {
        1162               0 :     *aRetVal = true;
        1163               0 :     return NS_OK;
        1164                 :   }
        1165                 :
        1166                 :   // Obtain a presentation shell
        1167            5369 :   nsIPresShell *shell = document->GetShell();
        1168           10738 :   nsRefPtr<nsPresContext> context;
        1169            5369 :   if (shell) {
        1170               0 :     context = shell->GetPresContext();
        1171                 :   }
        1172                 :
        1173            5369 :   nsEventStatus status = nsEventStatus_eIgnore;
        1174                 :   nsresult rv =
        1175                 :     nsEventDispatcher::DispatchDOMEvent(this, nsnull, aEvent, context,
        1176            5369 :                                         &status);
        1177            5369 :   *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
        1178            5369 :   return rv;
        1179                 : }
        1180                 :
        1181                 : nsresult
        1182            6423 : nsINode::PostHandleEvent(nsEventChainPostVisitor& /*aVisitor*/)
        1183                 : {
        1184            6423 :   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           32346 : nsINode::GetListenerManager(bool aCreateIfNotFound)
        1199                 : {
        1200           32346 :   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          164309 : nsINode::Trace(nsINode *tmp, TraceCallback cb, void *closure)
        1212                 : {
        1213          164309 :   nsContentUtils::TraceWrapper(tmp, cb, closure);
        1214          164309 : }
        1215                 :
        1216                 :
        1217                 : static
        1218          689715 : 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          689715 :                                     NODE_IS_INSERTION_PARENT);
        1225          689715 :   return aNode->HasFlag(problematicFlags) ||
        1226          689715 :          aNode->NodeType() == nsIDOMNode::ATTRIBUTE_NODE ||
        1227                 :          // For strange cases like xbl:content/xbl:children
        1228          689473 :          (aNode->IsElement() &&
        1229         2068903 :           aNode->AsElement()->IsInNamespace(kNameSpaceID_XBL));
        1230                 : }
        1231                 :
        1232                 : /* static */
        1233                 : bool
        1234          164295 : nsINode::Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb)
        1235                 : {
        1236          164295 :   nsIDocument *currentDoc = tmp->GetCurrentDoc();
        1237          325186 :   if (currentDoc &&
        1238          160891 :       nsCCUncollectableMarker::InGeneration(cb, currentDoc->GetMarkedCCGeneration())) {
        1239               0 :     return false;
        1240                 :   }
        1241                 :
        1242          164295 :   if (nsCCUncollectableMarker::sGeneration) {
        1243                 :     // If we're black no need to traverse.
        1244          102539 :     if (tmp->IsBlack() || tmp->InCCBlackTree()) {
        1245               0 :       return false;
        1246                 :     }
        1247                 :
        1248          102539 :     if (!UnoptimizableCCNode(tmp)) {
        1249                 :       // If we're in a black document, return early.
        1250          102418 :       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          102418 :       nsIContent* parent = tmp->GetParent();
        1256          102418 :       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          164295 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNodeInfo)
        1264          164295 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(GetParent())
        1265                 :
        1266          164295 :   nsSlots *slots = tmp->GetExistingSlots();
        1267          164295 :   if (slots) {
        1268            5477 :     slots->Traverse(cb);
        1269                 :   }
        1270                 :
        1271          164295 :   if (tmp->HasProperties()) {
        1272               0 :     nsNodeUtils::TraverseUserData(tmp, cb);
        1273                 :   }
        1274                 :
        1275          326890 :   if (tmp->NodeType() != nsIDOMNode::DOCUMENT_NODE &&
        1276          162595 :       tmp->HasFlag(NODE_HAS_LISTENERMANAGER)) {
        1277               3 :     nsContentUtils::TraverseListenerManager(tmp, cb);
        1278                 :   }
        1279                 :
        1280          164295 :   return true;
        1281                 : }
        1282                 :
        1283                 : /* static */
        1284                 : void
        1285          114867 : nsINode::Unlink(nsINode *tmp)
        1286                 : {
        1287          114867 :   nsContentUtils::ReleaseWrapper(tmp, tmp);
        1288                 :
        1289          114867 :   nsSlots *slots = tmp->GetExistingSlots();
        1290          114867 :   if (slots) {
        1291            4587 :     slots->Unlink();
        1292                 :   }
        1293                 :
        1294          228485 :   if (tmp->NodeType() != nsIDOMNode::DOCUMENT_NODE &&
        1295          113618 :       tmp->HasFlag(NODE_HAS_LISTENERMANAGER)) {
        1296               0 :     nsContentUtils::RemoveListenerManager(tmp);
        1297               0 :     tmp->UnsetFlags(NODE_HAS_LISTENERMANAGER);
        1298                 :   }
        1299                 :
        1300          114867 :   if (tmp->HasProperties()) {
        1301               0 :     nsNodeUtils::UnlinkUserData(tmp);
        1302                 :   }
        1303          114867 : }
        1304                 :
        1305                 : //----------------------------------------------------------------------
        1306                 :
        1307                 : nsEventStates
        1308           11494 : Element::IntrinsicState() const
        1309                 : {
        1310           11494 :   return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE :
        1311           22988 :                         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           11494 : Element::UpdateState(bool aNotify)
        1337                 : {
        1338           11494 :   nsEventStates oldState = mState;
        1339           11494 :   mState = IntrinsicState() | (oldState & ESM_MANAGED_STATES);
        1340           11494 :   if (aNotify) {
        1341            1769 :     nsEventStates changedStates = oldState ^ mState;
        1342            1769 :     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           11494 : }
        1351                 :
        1352                 : void
        1353           73982 : nsIContent::UpdateEditableState(bool aNotify)
        1354                 : {
        1355                 :   // Guaranteed to be non-element content
        1356           73982 :   NS_ASSERTION(!IsElement(), "What happened here?");
        1357           73982 :   nsIContent *parent = GetParent();
        1358                 :
        1359           73982 :   SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
        1360           73982 : }
        1361                 :
        1362                 : void
        1363           37811 : nsGenericElement::UpdateEditableState(bool aNotify)
        1364                 : {
        1365           37811 :   nsIContent *parent = GetParent();
        1366                 :
        1367           37811 :   SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
        1368           37811 :   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           37811 :     if (IsEditable()) {
        1376               0 :       RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
        1377               0 :       AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
        1378                 :     } else {
        1379           37811 :       RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
        1380           37811 :       AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
        1381                 :     }
        1382                 :   }
        1383           37811 : }
        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          131202 : GetJSObjectChild(nsWrapperCache* aCache)
        1704                 : {
        1705          131202 :   if (aCache->PreservingWrapper()) {
        1706               0 :     return aCache->GetWrapperPreserveColor();
        1707                 :   }
        1708          131202 :   return aCache->GetExpandoObjectPreserveColor();
        1709                 : }
        1710                 :
        1711                 : static bool
        1712           59701 : NeedsScriptTraverse(nsWrapperCache* aCache)
        1713                 : {
        1714           59701 :   JSObject* o = GetJSObjectChild(aCache);
        1715           59701 :   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            1396 : 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            1361 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsChildContentList)
        1739            1361 :   return !NeedsScriptTraverse(tmp);
        1740                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
        1741                 :
        1742             562 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsChildContentList)
        1743             562 :   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           42552 : NS_INTERFACE_TABLE_HEAD(nsChildContentList)
        1751           42552 :   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           41025 :   NS_OFFSET_AND_INTERFACE_TABLE_END
        1756           41025 :   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
        1757           27258 :   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            1396 : 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            1396 : 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            1396 : 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            1396 : 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            1396 : 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            1396 : 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            3754 : nsGenericElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL)
        2515                 : {
        2516            3754 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mStyle");
        2517            3754 :   cb.NoteXPCOMChild(mStyle.get());
        2518                 :
        2519            3754 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mSMILOverrideStyle");
        2520            3754 :   cb.NoteXPCOMChild(mSMILOverrideStyle.get());
        2521                 :
        2522            3754 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mAttributeMap");
        2523            3754 :   cb.NoteXPCOMChild(mAttributeMap.get());
        2524                 :
        2525            3754 :   if (aIsXUL) {
        2526               9 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mControllers");
        2527               9 :     cb.NoteXPCOMChild(mControllers);
        2528                 :   }
        2529                 :
        2530            3754 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
        2531            3754 :   cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
        2532                 :
        2533            3754 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
        2534            3754 :   cb.NoteXPCOMChild(mClassList.get());
        2535            3754 : }
        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           37958 : nsGenericElement::nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo)
        2556           37958 :   : Element(aNodeInfo)
        2557                 : {
        2558           37958 :   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           37958 :   SetFlags((nsIProgrammingLanguage::JAVASCRIPT << NODE_SCRIPT_TYPE_OFFSET));
        2568           37958 :   SetIsElement();
        2569           37958 : }
        2570                 :
        2571           75912 : nsGenericElement::~nsGenericElement()
        2572                 : {
        2573           37956 :   NS_PRECONDITION(!IsInDoc(),
        2574                 :                   "Please remove this from the document properly");
        2575           37956 :   if (GetParent()) {
        2576               0 :     NS_RELEASE(mParent);
        2577                 :   }
        2578           75912 : }
        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            1742 : nsGenericElement::SetAttribute(const nsAString& aName,
        2776                 :                                const nsAString& aValue)
        2777                 : {
        2778            1742 :   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
        2779                 :
        2780            1742 :   if (!name) {
        2781            1740 :     nsresult rv = nsContentUtils::CheckQName(aName, false);
        2782            1740 :     NS_ENSURE_SUCCESS(rv, rv);
        2783                 :
        2784            3480 :     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
        2785            1740 :     NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
        2786                 :
        2787            1740 :     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           37956 : nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
        3139                 :                              nsIContent* aBindingParent,
        3140                 :                              bool aCompileEventHandlers)
        3141                 : {
        3142           37956 :   NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
        3143           37956 :   NS_PRECONDITION(HasSameOwnerDoc(NODE_FROM(aParent, aDocument)),
        3144                 :                   "Must have the same owner document");
        3145           37956 :   NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
        3146                 :                   "aDocument must be current doc of aParent");
        3147           37956 :   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           37956 :   NS_PRECONDITION(!GetParent() || aParent == GetParent(),
        3151                 :                   "Already have a parent.  Unbind first!");
        3152           37956 :   NS_PRECONDITION(!GetBindingParent() ||
        3153                 :                   aBindingParent == GetBindingParent() ||
        3154                 :                   (!aBindingParent && aParent &&
        3155                 :                    aParent->GetBindingParent() == GetBindingParent()),
        3156                 :                   "Already have a binding parent.  Unbind first!");
        3157           37956 :   NS_PRECONDITION(!aParent || !aDocument ||
        3158                 :                   !aParent->HasFlag(NODE_FORCE_XBL_BINDINGS),
        3159                 :                   "Parent in document but flagged as forcing XBL");
        3160           37956 :   NS_PRECONDITION(aBindingParent != this,
        3161                 :                   "Content must not be its own binding parent");
        3162           37956 :   NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() ||
        3163                 :                   aBindingParent == aParent,
        3164                 :                   "Native anonymous content must have its parent as its "
        3165                 :                   "own binding parent");
        3166                 :
        3167           37956 :   if (!aBindingParent && aParent) {
        3168           36695 :     aBindingParent = aParent->GetBindingParent();
        3169                 :   }
        3170                 :
        3171                 : #ifdef MOZ_XUL
        3172                 :   // First set the binding parent
        3173           37956 :   nsXULElement* xulElem = nsXULElement::FromContent(this);
        3174           37956 :   if (xulElem) {
        3175             144 :     xulElem->SetXULBindingParent(aBindingParent);
        3176                 :   }
        3177                 :   else
        3178                 : #endif
        3179                 :   {
        3180           37812 :     if (aBindingParent) {
        3181               0 :       nsDOMSlots *slots = DOMSlots();
        3182                 :
        3183               0 :       slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
        3184                 :     }
        3185                 :   }
        3186           37956 :   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           37956 :   if (aParent && aParent->IsInNativeAnonymousSubtree()) {
        3192               0 :     SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
        3193                 :   }
        3194                 :
        3195           37956 :   bool hadForceXBL = HasFlag(NODE_FORCE_XBL_BINDINGS);
        3196                 :
        3197                 :   // Now set the parent and set the "Force attach xbl" flag if needed.
        3198           37956 :   if (aParent) {
        3199           36695 :     if (!GetParent()) {
        3200           36621 :       NS_ADDREF(aParent);
        3201                 :     }
        3202           36695 :     mParent = aParent;
        3203                 :
        3204           36695 :     if (aParent->HasFlag(NODE_FORCE_XBL_BINDINGS)) {
        3205               0 :       SetFlags(NODE_FORCE_XBL_BINDINGS);
        3206                 :     }
        3207                 :   }
        3208                 :   else {
        3209            1261 :     mParent = aDocument;
        3210                 :   }
        3211           37956 :   SetParentIsContent(aParent);
        3212                 :
        3213                 :   // XXXbz sXBL/XBL2 issue!
        3214                 :
        3215                 :   // Finally, set the document
        3216           37956 :   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           37767 :     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           37767 :                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           37956 :   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           37956 :   UpdateEditableState(false);
        3274                 :
        3275                 :   // Now recurse into our kids
        3276           38037 :   for (nsIContent* child = GetFirstChild(); child;
        3277              81 :        child = child->GetNextSibling()) {
        3278                 :     rv = child->BindToTree(aDocument, this, aBindingParent,
        3279              81 :                            aCompileEventHandlers);
        3280              81 :     NS_ENSURE_SUCCESS(rv, rv);
        3281                 :   }
        3282                 :
        3283           37956 :   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           37956 :   NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
        3289           37956 :   NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
        3290           37956 :   NS_POSTCONDITION(aBindingParent == GetBindingParent(),
        3291                 :                    "Bound to wrong binding parent");
        3292                 :
        3293           37956 :   return NS_OK;
        3294                 : }
        3295                 :
        3296                 : void
        3297          100429 : nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent)
        3298                 : {
        3299          100429 :   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          100429 :     HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetCurrentDoc();
        3305                 :
        3306          100429 :   if (aNullParent) {
        3307           37880 :     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           37880 :     if (GetParent()) {
        3318           36621 :       NS_RELEASE(mParent);
        3319                 :     } else {
        3320            1259 :       mParent = nsnull;
        3321                 :     }
        3322           37880 :     SetParentIsContent(false);
        3323                 :   }
        3324          100429 :   ClearInDocument();
        3325                 :
        3326          100429 :   if (document) {
        3327                 :     // Notify XBL- & nsIAnonymousContentCreator-generated
        3328                 :     // anonymous content that the document is changing.
        3329           37765 :     document->BindingManager()->RemovedFromDocument(this, document);
        3330                 :
        3331           37765 :     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          100429 :   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          100429 :   UnsetFlags(NODE_FORCE_XBL_BINDINGS);
        3349                 :
        3350                 : #ifdef MOZ_XUL
        3351          100429 :   nsXULElement* xulElem = nsXULElement::FromContent(this);
        3352          100429 :   if (xulElem) {
        3353             360 :     xulElem->SetXULBindingParent(nsnull);
        3354                 :   }
        3355                 :   else
        3356                 : #endif
        3357                 :   {
        3358          100069 :     nsDOMSlots *slots = GetExistingDOMSlots();
        3359          100069 :     if (slots) {
        3360            7431 :       slots->mBindingParent = nsnull;
        3361                 :     }
        3362                 :   }
        3363                 :
        3364          100429 :   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          100429 :     PRUint32 i, n = mAttrsAndChildren.ChildCount();
        3369                 :
        3370          298665 :     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          198236 :       mAttrsAndChildren.ChildAt(i)->UnbindFromTree(true, false);
        3375                 :     }
        3376                 :   }
        3377                 :
        3378          100429 :   nsNodeUtils::ParentChainChanged(this);
        3379          100429 : }
        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            9600 : nsGenericElement::IsAttributeMapped(const nsIAtom* aAttribute) const
        3651                 : {
        3652            9600 :   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          234473 : nsGenericElement::GetBindingParent() const
        3740                 : {
        3741          234473 :   nsDOMSlots *slots = GetExistingDOMSlots();
        3742                 :
        3743          234473 :   if (slots) {
        3744             249 :     return slots->mBindingParent;
        3745                 :   }
        3746          234224 :   return nsnull;
        3747                 : }
        3748                 :
        3749                 : bool
        3750          272346 : nsGenericElement::IsNodeOfType(PRUint32 aFlags) const
        3751                 : {
        3752          272346 :   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          110494 : nsGenericElement::InsertChildAt(nsIContent* aKid,
        3781                 :                                 PRUint32 aIndex,
        3782                 :                                 bool aNotify)
        3783                 : {
        3784          110494 :   NS_PRECONDITION(aKid, "null ptr");
        3785                 :
        3786          110494 :   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          111857 : nsINode::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
        3819                 :                          bool aNotify, nsAttrAndChildArray& aChildArray)
        3820                 : {
        3821          111857 :   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          111857 :   nsMutationGuard::DidMutate();
        3828                 :
        3829                 :   // Do this before checking the child-count since this could cause mutations
        3830          111857 :   nsIDocument* doc = GetCurrentDoc();
        3831          223714 :   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
        3832                 :
        3833          111857 :   if (!HasSameOwnerDoc(aKid)) {
        3834               0 :     rv = AdoptNodeIntoOwnerDoc(this, aKid);
        3835               0 :     NS_ENSURE_SUCCESS(rv, rv);
        3836                 :   }
        3837                 :
        3838          111857 :   PRUint32 childCount = aChildArray.ChildCount();
        3839          111857 :   NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE);
        3840          111857 :   bool isAppend = (aIndex == childCount);
        3841                 :
        3842          111857 :   rv = aChildArray.InsertChildAt(aKid, aIndex);
        3843          111857 :   NS_ENSURE_SUCCESS(rv, rv);
        3844          111857 :   if (aIndex == 0) {
        3845           37060 :     mFirstChild = aKid;
        3846                 :   }
        3847                 :
        3848                 :   nsIContent* parent =
        3849          111857 :     IsNodeOfType(eDOCUMENT) ? nsnull : static_cast<nsIContent*>(this);
        3850                 :
        3851          111857 :   rv = aKid->BindToTree(doc, parent, nsnull, true);
        3852          111857 :   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          111857 :   NS_ASSERTION(aKid->GetNodeParent() == this,
        3862                 :                "Did we run script inappropriately?");
        3863                 :
        3864          111857 :   if (aNotify) {
        3865                 :     // Note that we always want to call ContentInserted when things are added
        3866                 :     // as kids to documents
        3867            1454 :     if (parent && isAppend) {
        3868             397 :       nsNodeUtils::ContentAppended(parent, aKid, aIndex);
        3869                 :     } else {
        3870            1057 :       nsNodeUtils::ContentInserted(this, aKid, aIndex);
        3871                 :     }
        3872                 :
        3873            1454 :     if (nsContentUtils::HasMutationListeners(aKid,
        3874            1454 :           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          111857 :   return NS_OK;
        3884                 : }
        3885                 :
        3886                 : nsresult
        3887             226 : nsGenericElement::RemoveChildAt(PRUint32 aIndex, bool aNotify)
        3888                 : {
        3889             452 :   nsCOMPtr<nsIContent> oldKid = mAttrsAndChildren.GetSafeChildAt(aIndex);
        3890             226 :   NS_ASSERTION(oldKid == GetChildAt(aIndex), "Unexpected child in RemoveChildAt");
        3891                 :
        3892             226 :   if (oldKid) {
        3893             226 :     return doRemoveChildAt(aIndex, aNotify, oldKid, mAttrsAndChildren);
        3894                 :   }
        3895                 :
        3896               0 :   return NS_OK;
        3897                 : }
        3898                 :
        3899                 : nsresult
        3900             236 : nsINode::doRemoveChildAt(PRUint32 aIndex, bool aNotify,
        3901                 :                          nsIContent* aKid, nsAttrAndChildArray& aChildArray)
        3902                 : {
        3903             236 :   NS_PRECONDITION(aKid && aKid->GetNodeParent() == this &&
        3904                 :                   aKid == GetChildAt(aIndex) &&
        3905                 :                   IndexOf(aKid) == (PRInt32)aIndex, "Bogus aKid");
        3906                 :
        3907             236 :   nsMutationGuard::DidMutate();
        3908                 :
        3909             236 :   nsIDocument* doc = GetCurrentDoc();
        3910                 :
        3911             472 :   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
        3912                 :
        3913             236 :   nsIContent* previousSibling = aKid->GetPreviousSibling();
        3914                 :
        3915             236 :   if (GetFirstChild() == aKid) {
        3916             116 :     mFirstChild = aKid->GetNextSibling();
        3917                 :   }
        3918                 :
        3919             236 :   aChildArray.RemoveChildAt(aIndex);
        3920                 :
        3921             236 :   if (aNotify) {
        3922             236 :     nsNodeUtils::ContentRemoved(this, aKid, aIndex, previousSibling);
        3923                 :   }
        3924                 :
        3925             236 :   aKid->UnbindFromTree();
        3926                 :
        3927             236 :   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             405 : bool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
        4060                 :                         bool aIsReplace, nsINode* aRefChild)
        4061                 : {
        4062             405 :   NS_PRECONDITION(aNewChild, "Must have new child");
        4063             405 :   NS_PRECONDITION(!aIsReplace || aRefChild,
        4064                 :                   "Must have ref content for replace");
        4065             405 :   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             405 :   if (aParent && nsContentUtils::ContentIsDescendantOf(aParent, aNewChild)) {
        4072               0 :     return false;
        4073                 :   }
        4074                 :
        4075                 :   // The allowed child nodes differ for documents and elements
        4076             405 :   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             272 :       if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
        4089                 :         // Always ok to have elements under other elements or document fragments
        4090             271 :         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             405 : nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
        4231                 :                                nsINode* aRefChild)
        4232                 : {
        4233             405 :   if (!aNewChild || (aReplace && !aRefChild)) {
        4234               0 :     return NS_ERROR_NULL_POINTER;
        4235                 :   }
        4236                 :
        4237            1473 :   if ((!IsNodeOfType(eDOCUMENT) &&
        4238             404 :        !IsNodeOfType(eDOCUMENT_FRAGMENT) &&
        4239             259 :        !IsElement()) ||
        4240             405 :       !aNewChild->IsNodeOfType(eCONTENT)){
        4241               0 :     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
        4242                 :   }
        4243                 :
        4244             405 :   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             405 :     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             405 :     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             405 :     nsINode* oldParent = aNewChild->GetNodeParent();
        4270             405 :     if (oldParent) {
        4271                 :       nsContentUtils::MaybeFireNodeRemoved(aNewChild, oldParent,
        4272              77 :                                            aNewChild->OwnerDoc());
        4273                 :     }
        4274                 :
        4275                 :     // If we're inserting a fragment, fire for all the children of the
        4276                 :     // fragment
        4277             405 :     if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
        4278               0 :       static_cast<nsGenericElement*>(aNewChild)->FireNodeRemovedForChildren();
        4279                 :     }
        4280                 :   }
        4281                 :
        4282             405 :   nsIDocument* doc = OwnerDoc();
        4283             405 :   nsIContent* newContent = static_cast<nsIContent*>(aNewChild);
        4284                 :   PRInt32 insPos;
        4285                 :
        4286             810 :   mozAutoDocUpdate batch(GetCurrentDoc(), UPDATE_CONTENT_MODEL, true);
        4287                 :
        4288                 :   // Figure out which index to insert at
        4289             405 :   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             397 :     insPos = GetChildCount();
        4297                 :   }
        4298                 :
        4299                 :   // Make sure that the inserted node is allowed as a child of its new parent.
        4300             405 :   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             405 :   if (aReplace) {
        4308               0 :     res = RemoveChildAt(insPos, true);
        4309               0 :     NS_ENSURE_SUCCESS(res, res);
        4310                 :   }
        4311                 :
        4312             405 :   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             810 :   nsCOMPtr<nsINode> oldParent = newContent->GetNodeParent();
        4321             405 :   if (oldParent) {
        4322              77 :     PRInt32 removeIndex = oldParent->IndexOf(newContent);
        4323              77 :     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              77 :     res = oldParent->RemoveChildAt(removeIndex, true);
        4330              77 :     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              77 :     if (oldParent == this && removeIndex < insPos) {
        4335              70 :       --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             405 :   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             405 :   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             405 :     res = InsertChildAt(newContent, insPos, true);
        4420             405 :     NS_ENSURE_SUCCESS(res, res);
        4421                 :   }
        4422                 :
        4423             405 :   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            1396 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericElement)
        4450                 :
        4451                 : #define SUBTREE_UNBINDINGS_PER_RUNNABLE 500
        4452                 :
        4453                 : class ContentUnbinder : public nsRunnable
        4454                 : {
        4455                 : public:
        4456              44 :   ContentUnbinder()
        4457              44 :   {
        4458              44 :     nsLayoutStatics::AddRef();
        4459              44 :     mLast = this;
        4460              44 :   }
        4461                 :
        4462              88 :   ~ContentUnbinder()
        4463              88 :   {
        4464              44 :     Run();
        4465              44 :     nsLayoutStatics::Release();
        4466             176 :   }
        4467                 :
        4468           52768 :   void UnbindSubtree(nsIContent* aNode)
        4469                 :   {
        4470           88091 :     if (aNode->NodeType() != nsIDOMNode::ELEMENT_NODE &&
        4471           35323 :         aNode->NodeType() != nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
        4472           35323 :       return;
        4473                 :     }
        4474           17445 :     nsGenericElement* container = static_cast<nsGenericElement*>(aNode);
        4475           17445 :     PRUint32 childCount = container->mAttrsAndChildren.ChildCount();
        4476           17445 :     if (childCount) {
        4477           86613 :       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          104886 :           container->mAttrsAndChildren.TakeChildAt(childCount);
        4485           52443 :         if (childCount == 0) {
        4486           17085 :           container->mFirstChild = nsnull;
        4487                 :         }
        4488           52443 :         UnbindSubtree(child);
        4489           52443 :         child->UnbindFromTree();
        4490                 :       }
        4491                 :     }
        4492                 :   }
        4493                 :
        4494              88 :   NS_IMETHOD Run()
        4495                 :   {
        4496             176 :     nsAutoScriptBlocker scriptBlocker;
        4497              88 :     PRUint32 len = mSubtreeRoots.Length();
        4498              88 :     if (len) {
        4499              44 :       PRTime start = PR_Now();
        4500             369 :       for (PRUint32 i = 0; i < len; ++i) {
        4501             325 :         UnbindSubtree(mSubtreeRoots[i]);
        4502                 :       }
        4503              44 :       mSubtreeRoots.Clear();
        4504                 :       Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_CONTENT_UNBIND,
        4505              44 :                             PRUint32(PR_Now() - start) / PR_USEC_PER_MSEC);
        4506                 :     }
        4507              88 :     if (this == sContentUnbinder) {
        4508              44 :       sContentUnbinder = nsnull;
        4509              44 :       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              88 :     return NS_OK;
        4519                 :   }
        4520                 :
        4521             325 :   static void Append(nsIContent* aSubtreeRoot)
        4522                 :   {
        4523             325 :     if (!sContentUnbinder) {
        4524              44 :       sContentUnbinder = new ContentUnbinder();
        4525              88 :       nsCOMPtr<nsIRunnable> e = sContentUnbinder;
        4526              44 :       NS_DispatchToMainThread(e);
        4527                 :     }
        4528                 :
        4529             325 :     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             325 :     sContentUnbinder->mLast->mSubtreeRoots.AppendElement(aSubtreeRoot);
        4535             325 :   }
        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           37911 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericElement)
        4548           37911 :   nsINode::Unlink(tmp);
        4549                 :
        4550           37911 :   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           37911 :   if (UnoptimizableCCNode(tmp) || !nsCCUncollectableMarker::sGeneration) {
        4557           20456 :     PRUint32 childCount = tmp->mAttrsAndChildren.ChildCount();
        4558           20456 :     if (childCount) {
        4559                 :       // Don't allow script to run while we're unbinding everything.
        4560           37262 :       nsAutoScriptBlocker scriptBlocker;
        4561           95085 :       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          115646 :         nsCOMPtr<nsIContent> child = tmp->mAttrsAndChildren.TakeChildAt(childCount);
        4568           57823 :         if (childCount == 0) {
        4569           18631 :           tmp->mFirstChild = nsnull;
        4570                 :         }
        4571           57823 :         child->UnbindFromTree();
        4572                 :       }
        4573                 :     }
        4574           17455 :   } else if (!tmp->GetParent() && tmp->mAttrsAndChildren.ChildCount()) {
        4575             325 :     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           37911 :     nsDOMSlots *slots = tmp->GetExistingDOMSlots();
        4584           37911 :     if (slots) {
        4585            3315 :       slots->Unlink(tmp->IsXUL());
        4586                 :     }
        4587                 :   }
        4588                 :
        4589                 :   {
        4590                 :     nsIDocument *doc;
        4591           37911 :     if (!tmp->GetNodeParent() && (doc = tmp->OwnerDoc())) {
        4592           15470 :       doc->BindingManager()->RemovedFromDocument(tmp, doc);
        4593                 :     }
        4594                 :   }
        4595           37911 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
        4596                 :
        4597           54211 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGenericElement)
        4598           54211 :   nsINode::Trace(tmp, aCallback, aClosure);
        4599           54211 : 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           28127 : nsGenericElement::MarkNodeChildren(nsINode* aNode)
        4620                 : {
        4621           28127 :   JSObject* o = GetJSObjectChild(aNode);
        4622           28127 :   xpc_UnmarkGrayObject(o);
        4623                 :
        4624           28127 :   nsEventListenerManager* elm = aNode->GetListenerManager(false);
        4625           28127 :   if (elm) {
        4626               0 :     elm->UnmarkGrayJSListeners();
        4627                 :   }
        4628                 :
        4629           28127 :   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           28127 : }
        4639                 :
        4640                 : nsINode*
        4641            2693 : FindOptimizableSubtreeRoot(nsINode* aNode)
        4642                 : {
        4643                 :   nsINode* p;
        4644           10139 :   while ((p = aNode->GetNodeParent())) {
        4645            4753 :     if (UnoptimizableCCNode(aNode)) {
        4646               0 :       return nsnull;
        4647                 :     }
        4648            4753 :     aNode = p;
        4649                 :   }
        4650                 :
        4651            2693 :   if (UnoptimizableCCNode(aNode)) {
        4652             121 :     return nsnull;
        4653                 :   }
        4654            2572 :   return aNode;
        4655                 : }
        4656                 :
        4657                 : nsAutoTArray<nsINode*, 1020>* gCCBlackMarkedNodes = nsnull;
        4658                 :
        4659                 : void
        4660            1892 : ClearBlackMarkedNodes()
        4661                 : {
        4662            1892 :   if (!gCCBlackMarkedNodes) {
        4663            1848 :     return;
        4664                 :   }
        4665              44 :   PRUint32 len = gCCBlackMarkedNodes->Length();
        4666             402 :   for (PRUint32 i = 0; i < len; ++i) {
        4667             358 :     nsINode* n = gCCBlackMarkedNodes->ElementAt(i);
        4668             358 :     n->SetCCMarkedRoot(false);
        4669             358 :     n->SetInCCBlackTree(false);
        4670                 :   }
        4671              44 :   delete gCCBlackMarkedNodes;
        4672              44 :   gCCBlackMarkedNodes = nsnull;
        4673                 : }
        4674                 :
        4675                 : // static
        4676                 : bool
        4677           93554 : nsGenericElement::CanSkipInCC(nsINode* aNode)
        4678                 : {
        4679                 :   // Don't try to optimize anything during shutdown.
        4680           93554 :   if (nsCCUncollectableMarker::sGeneration == 0) {
        4681           45229 :     return false;
        4682                 :   }
        4683                 :
        4684                 :   // Bail out early if aNode is somewhere in anonymous content,
        4685                 :   // or otherwise unusual.
        4686           48325 :   if (UnoptimizableCCNode(aNode)) {
        4687               0 :     return false;
        4688                 :   }
        4689                 :
        4690           48325 :   nsIDocument* currentDoc = aNode->GetCurrentDoc();
        4691           96478 :   if (currentDoc &&
        4692           48153 :       nsCCUncollectableMarker::InGeneration(currentDoc->GetMarkedCCGeneration())) {
        4693               0 :     return !NeedsScriptTraverse(aNode);
        4694                 :   }
        4695                 :
        4696                 :   nsINode* root =
        4697                 :     currentDoc ? static_cast<nsINode*>(currentDoc) :
        4698           48325 :                  FindOptimizableSubtreeRoot(aNode);
        4699           48325 :   if (!root) {
        4700               0 :     return false;
        4701                 :   }
        4702                 :
        4703                 :   // Subtree has been traversed already.
        4704           48325 :   if (root->CCMarkedRoot()) {
        4705           47967 :     return root->InCCBlackTree() && !NeedsScriptTraverse(aNode);
        4706                 :   }
        4707                 :
        4708             358 :   if (!gCCBlackMarkedNodes) {
        4709              44 :     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             716 :   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             716 :   nsAutoTArray<nsINode*, 1020> grayNodes;
        4719                 :
        4720             358 :   bool foundBlack = root->IsBlack();
        4721             358 :   if (root != currentDoc) {
        4722               4 :     currentDoc = nsnull;
        4723               4 :     if (NeedsScriptTraverse(root)) {
        4724               0 :       grayNodes.AppendElement(root);
        4725               4 :     } else if (static_cast<nsIContent*>(root)->IsPurple()) {
        4726               4 :       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           58132 :   for (nsIContent* node = root->GetFirstChild(); node;
        4735           57774 :        node = node->GetNextNode(root)) {
        4736           57774 :     foundBlack = foundBlack || node->IsBlack();
        4737           57774 :     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               0 :       break;
        4742                 :     }
        4743           57774 :     if (NeedsScriptTraverse(node)) {
        4744                 :       // Gray nodes need real CC traverse.
        4745               0 :       grayNodes.AppendElement(node);
        4746           57774 :     } else if (node->IsPurple()) {
        4747           47967 :       nodesToUnpurple.AppendElement(node);
        4748                 :     }
        4749                 :   }
        4750                 :
        4751             358 :   root->SetCCMarkedRoot(true);
        4752             358 :   root->SetInCCBlackTree(foundBlack);
        4753             358 :   gCCBlackMarkedNodes->AppendElement(root);
        4754                 :
        4755             358 :   if (!foundBlack) {
        4756             358 :     return false;
        4757                 :   }
        4758                 :
        4759               0 :   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               0 :       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               0 :   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               0 :   return !NeedsScriptTraverse(aNode);
        4782                 : }
        4783                 :
        4784                 : nsAutoTArray<nsINode*, 1020>* gPurpleRoots = nsnull;
        4785                 :
        4786             375 : void ClearPurpleRoots()
        4787                 : {
        4788             375 :   if (!gPurpleRoots) {
        4789              86 :     return;
        4790                 :   }
        4791             289 :   PRUint32 len = gPurpleRoots->Length();
        4792            2832 :   for (PRUint32 i = 0; i < len; ++i) {
        4793            2543 :     nsINode* n = gPurpleRoots->ElementAt(i);
        4794            2543 :     n->SetIsPurpleRoot(false);
        4795                 :   }
        4796             289 :   delete gPurpleRoots;
        4797             289 :   gPurpleRoots = nsnull;
        4798                 : }
        4799                 :
        4800                 : static bool
        4801          320008 : ShouldClearPurple(nsIContent* aContent)
        4802                 : {
        4803          320008 :   if (aContent && aContent->IsPurple()) {
        4804          276634 :     return true;
        4805                 :   }
        4806                 :
        4807           43374 :   JSObject* o = GetJSObjectChild(aContent);
        4808           43374 :   if (o && xpc_IsGrayGCThing(o)) {
        4809               0 :     return true;
        4810                 :   }
        4811                 :
        4812           43374 :   if (aContent->HasListenerManager()) {
        4813               0 :     return true;
        4814                 :   }
        4815                 :
        4816           43374 :   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          393501 : nsGenericElement::CanSkip(nsINode* aNode, bool aRemovingAllowed)
        4838                 : {
        4839                 :   // Don't try to optimize anything during shutdown.
        4840          393501 :   if (nsCCUncollectableMarker::sGeneration == 0) {
        4841             862 :     return false;
        4842                 :   }
        4843                 :
        4844          392639 :   bool unoptimizable = UnoptimizableCCNode(aNode);
        4845          392639 :   nsIDocument* currentDoc = aNode->GetCurrentDoc();
        4846          808435 :   if (currentDoc &&
        4847          390118 :       nsCCUncollectableMarker::InGeneration(currentDoc->GetMarkedCCGeneration()) &&
        4848           25678 :       (!unoptimizable || NodeHasActiveFrame(currentDoc, aNode))) {
        4849           25678 :     MarkNodeChildren(aNode);
        4850           25678 :     return true;
        4851                 :   }
        4852          366961 :   if (unoptimizable) {
        4853               0 :     return false;
        4854                 :   }
        4855                 :
        4856                 :   nsINode* root = currentDoc ? static_cast<nsINode*>(currentDoc) :
        4857          366961 :                                FindOptimizableSubtreeRoot(aNode);
        4858          366961 :   if (!root) {
        4859             121 :     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          366840 :   if (root->IsPurpleRoot()) {
        4865          364148 :     return false;
        4866                 :   }
        4867                 :
        4868                 :   // nodesToClear contains nodes which are either purple or
        4869                 :   // gray.
        4870            5384 :   nsAutoTArray<nsIContent*, 1020> nodesToClear;
        4871                 :
        4872            2692 :   bool foundBlack = root->IsBlack();
        4873            2692 :   if (root != currentDoc) {
        4874              48 :     currentDoc = nsnull;
        4875              48 :     if (ShouldClearPurple(static_cast<nsIContent*>(root))) {
        4876              48 :       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          322652 :   for (nsIContent* node = root->GetFirstChild(); node;
        4885          319960 :        node = node->GetNextNode(root)) {
        4886          320109 :     foundBlack = foundBlack || node->IsBlack();
        4887          320109 :     if (foundBlack) {
        4888             149 :       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             149 :         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          319960 :     } 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          276586 :       nodesToClear.AppendElement(node);
        4904                 :     }
        4905                 :   }
        4906                 :
        4907            2692 :   if (!currentDoc || !foundBlack) {
        4908            2543 :     if (!gPurpleRoots) {
        4909             289 :       gPurpleRoots = new nsAutoTArray<nsINode*, 1020>();
        4910                 :     }
        4911            2543 :     root->SetIsPurpleRoot(true);
        4912            2543 :     gPurpleRoots->AppendElement(root);
        4913                 :   }
        4914                 :
        4915            2692 :   if (!foundBlack) {
        4916            2543 :     return false;
        4917                 :   }
        4918                 :
        4919             149 :   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             149 :       MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration);
        4924             149 :     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             149 :   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             149 :   return true;
        4939                 : }
        4940                 :
        4941                 : bool
        4942          234496 : nsGenericElement::CanSkipThis(nsINode* aNode)
        4943                 : {
        4944          234496 :   if (nsCCUncollectableMarker::sGeneration == 0) {
        4945          118894 :     return false;
        4946                 :   }
        4947          115602 :   if (aNode->IsBlack()) {
        4948              14 :     return true;
        4949                 :   }
        4950          115588 :   nsIDocument* c = aNode->GetCurrentDoc();
        4951                 :   return
        4952          115252 :     ((c && nsCCUncollectableMarker::InGeneration(c->GetMarkedCCGeneration())) ||
        4953          230840 :      aNode->InCCBlackTree()) && !NeedsScriptTraverse(aNode);
        4954                 : }
        4955                 :
        4956                 : void
        4957            1365 : nsGenericElement::InitCCCallbacks()
        4958                 : {
        4959            1365 :   nsCycleCollector_setForgetSkippableCallback(ClearPurpleRoots);
        4960            1365 :   nsCycleCollector_setBeforeUnlinkCallback(ClearBlackMarkedNodes);
        4961            1365 : }
        4962                 :
        4963          160941 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGenericElement)
        4964          160941 :   return nsGenericElement::CanSkip(tmp, aRemovingAllowed);
        4965                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
        4966                 :
        4967           33463 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGenericElement)
        4968           33463 :   return nsGenericElement::CanSkipInCC(tmp);
        4969                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
        4970                 :
        4971          154966 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGenericElement)
        4972          154966 :   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           54197 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGenericElement)
        4991           54197 :   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           54197 :     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           54197 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
        5035                 :
        5036           54197 :   if (!nsINode::Traverse(tmp, cb)) {
        5037               0 :     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
        5038                 :   }
        5039                 :
        5040           54197 :   tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb);
        5041                 :
        5042           54197 :   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           54197 :     PRUint32 attrs = tmp->mAttrsAndChildren.AttrCount();
        5056           68914 :     for (i = 0; i < attrs; i++) {
        5057           14717 :       const nsAttrName* name = tmp->mAttrsAndChildren.AttrNameAt(i);
        5058           14717 :       if (!name->IsAtom()) {
        5059            2128 :         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
        5060                 :                                            "mAttrsAndChildren[i]->NodeInfo()");
        5061            2128 :         cb.NoteXPCOMChild(name->NodeInfo());
        5062                 :       }
        5063                 :     }
        5064                 :
        5065           54197 :     PRUint32 kids = tmp->mAttrsAndChildren.ChildCount();
        5066          213074 :     for (i = 0; i < kids; i++) {
        5067          158877 :       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAttrsAndChildren[i]");
        5068          158877 :       cb.NoteXPCOMChild(tmp->mAttrsAndChildren.GetSafeChildAt(i));
        5069                 :     }
        5070                 :   }
        5071                 :
        5072                 :   // Traverse any DOM slots of interest.
        5073                 :   {
        5074           54197 :     nsDOMSlots *slots = tmp->GetExistingDOMSlots();
        5075           54197 :     if (slots) {
        5076            3754 :       slots->Traverse(cb, tmp->IsXUL());
        5077                 :     }
        5078                 :   }
        5079           54197 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
        5080                 :
        5081                 :
        5082         2015349 : NS_INTERFACE_MAP_BEGIN(nsGenericElement)
        5083         2015349 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
        5084         2004455 :   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericElement)
        5085          328942 :   NS_INTERFACE_MAP_ENTRY(Element)
        5086          328942 :   NS_INTERFACE_MAP_ENTRY(nsIContent)
        5087           56736 :   NS_INTERFACE_MAP_ENTRY(nsINode)
        5088           45820 :   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
        5089           45645 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNSElement, new nsNSElementTearoff(this))
        5090           45641 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
        5091                 :                                  new nsNodeSupportsWeakRefTearoff(this))
        5092           45641 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNodeSelector,
        5093                 :                                  new nsNodeSelectorTearoff(this))
        5094           45641 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
        5095                 :                                  new nsNode3Tearoff(this))
        5096           45641 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsITouchEventReceiver,
        5097                 :                                  new nsTouchEventReceiverTearoff(this))
        5098           45641 :   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           45641 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
        5105           38851 : NS_INTERFACE_MAP_END
        5106                 :
        5107          716929 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGenericElement)
        5108          716919 : NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsGenericElement,
        5109                 :                                               nsNodeUtils::LastRelease(this))
        5110                 :
        5111                 : nsresult
        5112             955 : nsGenericElement::PostQueryInterface(REFNSIID aIID, void** aInstancePtr)
        5113                 : {
        5114                 :   return OwnerDoc()->BindingManager()->GetBindingImplementation(this, aIID,
        5115             955 :                                                                 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            7690 : nsGenericElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
        5162                 : {
        5163            7690 :   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           11346 : 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           11346 :   bool modification = false;
        5194                 :   *aHasListeners = aNotify &&
        5195                 :     nsContentUtils::HasMutationListeners(this,
        5196                 :                                          NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
        5197           11346 :                                          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           11346 :   if (*aHasListeners || aNotify) {
        5205            1770 :     nsAttrInfo info(GetAttrInfo(aNamespaceID, aName));
        5206            1770 :     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           11345 :     static_cast<PRUint8>(nsIDOMMutationEvent::ADDITION);
        5231           11345 :   return false;
        5232                 : }
        5233                 :
        5234                 : nsresult
        5235           11346 : 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           11346 :   NS_ENSURE_ARG_POINTER(aName);
        5242           11346 :   NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
        5243                 :                "Don't call SetAttr with unknown namespace");
        5244                 :
        5245           11346 :   if (!mAttrsAndChildren.CanFitMoreAttrs()) {
        5246               0 :     return NS_ERROR_FAILURE;
        5247                 :   }
        5248                 :
        5249                 :   PRUint8 modType;
        5250                 :   bool hasListeners;
        5251           22692 :   nsAttrValueOrString value(aValue);
        5252           22692 :   nsAttrValue oldValue;
        5253                 :
        5254           11346 :   if (MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, value, aNotify,
        5255           11346 :                             oldValue, &modType, &hasListeners)) {
        5256               1 :     return NS_OK;
        5257                 :   }
        5258                 :
        5259           11345 :   nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
        5260           11345 :   NS_ENSURE_SUCCESS(rv, rv);
        5261                 :
        5262           11345 :   if (aNotify) {
        5263            1769 :     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           22690 :   nsAutoScriptBlocker scriptBlocker;
        5269                 :
        5270           22690 :   nsAttrValue attrValue;
        5271           11345 :   if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
        5272           10969 :     attrValue.SetTo(aValue);
        5273                 :   }
        5274                 :
        5275                 :   return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
        5276                 :                           attrValue, modType, hasListeners, aNotify,
        5277           11345 :                           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           11345 : 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           11345 :   nsIDocument* document = GetCurrentDoc();
        5332           22690 :   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
        5333                 :
        5334           11345 :   nsMutationGuard::DidMutate();
        5335                 :
        5336                 :   // Copy aParsedValue for later use since it will be lost when we call
        5337                 :   // SetAndTakeMappedAttr below
        5338           22690 :   nsAttrValue aValueForAfterSetAttr;
        5339           11345 :   if (aCallAfterSetAttr) {
        5340           11345 :     aValueForAfterSetAttr.SetTo(aParsedValue);
        5341                 :   }
        5342                 :
        5343           11345 :   if (aNamespaceID == kNameSpaceID_None) {
        5344                 :     // XXXbz Perhaps we should push up the attribute mapping function
        5345                 :     // stuff to nsGenericElement?
        5346            9666 :     if (!IsAttributeMapped(aName) ||
        5347               0 :         !SetMappedAttribute(document, aName, aParsedValue, &rv)) {
        5348            9666 :       rv = mAttrsAndChildren.SetAndTakeAttr(aName, aParsedValue);
        5349                 :     }
        5350                 :   }
        5351                 :   else {
        5352            3358 :     nsCOMPtr<nsINodeInfo> ni;
        5353                 :     ni = mNodeInfo->NodeInfoManager()->GetNodeInfo(aName, aPrefix,
        5354                 :                                                    aNamespaceID,
        5355            1679 :                                                    nsIDOMNode::ATTRIBUTE_NODE);
        5356            1679 :     NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
        5357                 :
        5358            3358 :     rv = mAttrsAndChildren.SetAndTakeAttr(ni, aParsedValue);
        5359                 :   }
        5360           11345 :   NS_ENSURE_SUCCESS(rv, rv);
        5361                 :
        5362           11345 :   if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
        5363                 :     nsRefPtr<nsXBLBinding> binding =
        5364             124 :       OwnerDoc()->BindingManager()->GetBinding(this);
        5365              62 :     if (binding) {
        5366               0 :       binding->AttributeChanged(aName, aNamespaceID, false, aNotify);
        5367                 :     }
        5368                 :   }
        5369                 :
        5370           11345 :   UpdateState(aNotify);
        5371                 :
        5372           11345 :   if (aNotify) {
        5373            1769 :     nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType);
        5374                 :   }
        5375                 :
        5376           11345 :   if (aNamespaceID == kNameSpaceID_XMLEvents &&
        5377               0 :       aName == nsGkAtoms::event && mNodeInfo->GetDocument()) {
        5378               0 :     mNodeInfo->GetDocument()->AddXMLEventsContent(this);
        5379                 :   }
        5380           11345 :   if (aCallAfterSetAttr) {
        5381           11345 :     rv = AfterSetAttr(aNamespaceID, aName, &aValueForAfterSetAttr, aNotify);
        5382           11345 :     NS_ENSURE_SUCCESS(rv, rv);
        5383                 :   }
        5384                 :
        5385           11345 :   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           11345 :   return NS_OK;
        5411                 : }
        5412                 :
        5413                 : bool
        5414             183 : nsGenericElement::ParseAttribute(PRInt32 aNamespaceID,
        5415                 :                                  nsIAtom* aAttribute,
        5416                 :                                  const nsAString& aValue,
        5417                 :                                  nsAttrValue& aResult)
        5418                 : {
        5419             183 :   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            3023 : nsGenericElement::GetAttrInfo(PRInt32 aNamespaceID, nsIAtom* aName) const
        5442                 : {
        5443            3023 :   NS_ASSERTION(nsnull != aName, "must have attribute name");
        5444            3023 :   NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
        5445                 :                "must have a real namespace ID!");
        5446                 :
        5447            3023 :   PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNamespaceID);
        5448            3023 :   if (index >= 0) {
        5449                 :     return nsAttrInfo(mAttrsAndChildren.AttrNameAt(index),
        5450             855 :                       mAttrsAndChildren.AttrAt(index));
        5451                 :   }
        5452                 :
        5453            2168 :   return nsAttrInfo(nsnull, nsnull);
        5454                 : }
        5455                 :
        5456                 :
        5457                 : bool
        5458            9234 : nsGenericElement::GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
        5459                 :                           nsAString& aResult) const
        5460                 : {
        5461            9234 :   NS_ASSERTION(nsnull != aName, "must have attribute name");
        5462            9234 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
        5463                 :                "must have a real namespace ID!");
        5464                 :
        5465            9234 :   const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
        5466            9234 :   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             259 :     aResult.Truncate();
        5471                 :
        5472             259 :     return false;
        5473                 :   }
        5474                 :
        5475            8975 :   val->ToString(aResult);
        5476                 :
        5477            8975 :   return true;
        5478                 : }
        5479                 :
        5480                 : bool
        5481            2064 : nsGenericElement::HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const
        5482                 : {
        5483            2064 :   NS_ASSERTION(nsnull != aName, "must have attribute name");
        5484            2064 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
        5485                 :                "must have a real namespace ID!");
        5486                 :
        5487            2064 :   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            5933 : nsGenericElement::GetAttrNameAt(PRUint32 aIndex) const
        5629                 : {
        5630            5933 :   return mAttrsAndChildren.GetSafeAttrNameAt(aIndex);
        5631                 : }
        5632                 :
        5633                 : PRUint32
        5634            4247 : nsGenericElement::GetAttrCount() const
        5635                 : {
        5636            4247 :   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          140810 : nsGenericElement::GetChildCount() const
        5843                 : {
        5844          140810 :   return mAttrsAndChildren.ChildCount();
        5845                 : }
        5846                 :
        5847                 : nsIContent *
        5848            6690 : nsGenericElement::GetChildAt(PRUint32 aIndex) const
        5849                 : {
        5850            6690 :   return mAttrsAndChildren.GetSafeChildAt(aIndex);
        5851                 : }
        5852                 :
        5853                 : nsIContent * const *
        5854             264 : nsGenericElement::GetChildArray(PRUint32* aChildCount) const
        5855                 : {
        5856             264 :   return mAttrsAndChildren.GetChildArray(aChildCount);
        5857                 : }
        5858                 :
        5859                 : PRInt32
        5860             600 : nsGenericElement::IndexOf(nsINode* aPossibleChild) const
        5861                 : {
        5862             600 :   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            4188 : }

Generated by: LCOV version 1.7