Back to index

lightning-sunbird  0.9+nobinonly
Classes | Functions | Variables
nsGenericElement.cpp File Reference
#include "nsGenericElement.h"
#include "nsDOMAttribute.h"
#include "nsDOMAttributeMap.h"
#include "nsIAtom.h"
#include "nsINodeInfo.h"
#include "nsIDocument.h"
#include "nsIDocumentEncoder.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMDocument.h"
#include "nsIDOMRange.h"
#include "nsIDOMText.h"
#include "nsIDOMEventReceiver.h"
#include "nsITextContent.h"
#include "nsIContentIterator.h"
#include "nsRange.h"
#include "nsIEventListenerManager.h"
#include "nsILinkHandler.h"
#include "nsIScriptGlobalObject.h"
#include "nsISupportsArray.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
#include "nsIFrame.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsStyleConsts.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsString.h"
#include "nsUnicharUtils.h"
#include "nsIEventStateManager.h"
#include "nsIDOMEvent.h"
#include "nsIPrivateDOMEvent.h"
#include "nsDOMCID.h"
#include "nsIServiceManager.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsDOMCSSDeclaration.h"
#include "nsINameSpaceManager.h"
#include "nsContentList.h"
#include "nsDOMError.h"
#include "nsDOMString.h"
#include "nsIScriptSecurityManager.h"
#include "nsIDOMMutationEvent.h"
#include "nsMutationEvent.h"
#include "nsIBindingManager.h"
#include "nsXBLBinding.h"
#include "nsIDOMViewCSS.h"
#include "nsIXBLService.h"
#include "nsPIDOMWindow.h"
#include "nsIBoxObject.h"
#include "nsPIBoxObject.h"
#include "nsIDOMNSDocument.h"
#include "nsLayoutAtoms.h"
#include "nsHTMLAtoms.h"
#include "nsContentUtils.h"
#include "nsIJSContextStack.h"
#include "nsIDOMEventListener.h"
#include "nsIWebNavigation.h"
#include "nsIBaseWindow.h"
#include "jsapi.h"
#include "nsIDOMXPathEvaluator.h"
#include "nsNodeInfoManager.h"
#include "nsICategoryManager.h"
#include "nsIDOMNSFeatureFactory.h"
#include "nsIDOMDocumentType.h"

Go to the source code of this file.

Classes

struct  nsContentOrDocument
class  nsFragmentObserver

Functions

static nsresult doInsertChildAt (nsIContent *aKid, PRUint32 aIndex, PRBool aNotify, nsIContent *aParent, nsIDocument *aDocument, nsAttrAndChildArray &aChildArray)
 Most of the implementation of the nsIContent InsertChildAt method.
nsresult doRemoveChildAt (PRUint32 aIndex, PRBool aNotify, nsIContent *aKid, nsIContent *aParent, nsIDocument *aDocument, nsAttrAndChildArray &aChildArray)
 Most of the implementation of the nsIContent RemoveChildAt method.
nsresult NS_NewContentIterator (nsIContentIterator **aInstancePtrResult)
 NopClearEntry (PLDHashTable *table, PLDHashEntryHdr *entry)
 RangeListHashInitEntry (PLDHashTable *table, PLDHashEntryHdr *entry, const void *key)
 RangeListHashClearEntry (PLDHashTable *table, PLDHashEntryHdr *entry)
 EventListenerManagerHashInitEntry (PLDHashTable *table, PLDHashEntryHdr *entry, const void *key)
 EventListenerManagerHashClearEntry (PLDHashTable *table, PLDHashEntryHdr *entry)
static PRBool IsAllowedAsChild (nsIContent *aNewChild, PRUint16 aNewNodeType, nsIContent *aParent, nsIDocument *aDocument, PRBool aIsReplace, nsIContent *aRefContent)
 NS_INTERFACE_MAP_ENTRY_TEAROFF (nsIDOMEventReceiver, nsDOMEventRTTearoff::Create(this)) NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMEventTarget
static PRBool NodeHasMutationListeners (nsISupports *aNode)

Variables

PRBool gCheckedForXPathDOM
PRBool gHaveXPathDOM

Function Documentation

static nsresult doInsertChildAt ( nsIContent aKid,
PRUint32  aIndex,
PRBool  aNotify,
nsIContent aParent,
nsIDocument aDocument,
nsAttrAndChildArray aChildArray 
) [static]

Most of the implementation of the nsIContent InsertChildAt method.

Shared by nsDocument for insertions via DOM methods. When called from nsDocument, aParent will be null.

Parameters:
aKidThe child to insert.
aIndexThe index to insert at.
aNotifyWhether to notify.
aParentThe parent to use for the new child.
aDocumentThe document to use for the new child. Must be non-null if aParent is null and must match aParent->GetCurrentDoc() if aParent is not null.
aChildArrayThe child array to work with

Definition at line 2792 of file nsGenericElement.cpp.

{
  NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
  NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
                  "Incorrect aDocument");

  PRUint32 childCount = aChildArray.ChildCount();
  NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE);

  nsMutationGuard::DidMutate();

  PRBool isAppend = (aIndex == childCount);

  mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
  
  // Note that SetRootContent already deals with binding, so if we plan to call
  // it we shouldn't bind ourselves.
  // XXXbz this doesn't put aKid in the right spot, really... We really need a
  // better api for handling kids on documents.
  if (!aParent && aKid->IsContentOfType(nsIContent::eELEMENT)) {
    nsresult rv = aDocument->SetRootContent(aKid);
    NS_ENSURE_SUCCESS(rv, rv);
  } else {
    nsresult rv = aChildArray.InsertChildAt(aKid, aIndex);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = aKid->BindToTree(aDocument, aParent, nsnull, PR_TRUE);
    if (NS_FAILED(rv)) {
      aChildArray.RemoveChildAt(aIndex);
      aKid->UnbindFromTree();
      return rv;
    }
  }
  
  if (aParent && !aParent->IsContentOfType(nsIContent::eXUL)) {
    nsRange::OwnerChildInserted(aParent, aIndex);
  }
  
  // The kid may have removed its parent from the document, so recheck that
  // that's still in the document before proceeding.  Also, the kid may have
  // just removed itself, in which case we don't really want to fire
  // ContentAppended or a mutation event.
  // XXXbz What if the kid just moved us in the document?  Scripts suck.  We
  // really need to stop running them while we're in the middle of modifying
  // the DOM....
  if (aNotify && aDocument && aKid->GetCurrentDoc() == aDocument &&
      (!aParent || aKid->GetParent() == aParent)) {
    // Note that we always want to call ContentInserted when things are added
    // as kids to documents
    if (aParent && isAppend) {
      aDocument->ContentAppended(aParent, aIndex);
    } else {
      aDocument->ContentInserted(aParent, aKid, aIndex);
    }
    
    // XXXbz how come we're not firing mutation listeners for adding to
    // documents?
    if (aParent &&
        nsGenericElement::HasMutationListeners(aParent,
                                               NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
      nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED, aKid);
      mutation.mRelatedNode = do_QueryInterface(aParent);
        
      nsEventStatus status = nsEventStatus_eIgnore;
      aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status);
    }
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult doRemoveChildAt ( PRUint32  aIndex,
PRBool  aNotify,
nsIContent aKid,
nsIContent aParent,
nsIDocument aDocument,
nsAttrAndChildArray aChildArray 
)

Most of the implementation of the nsIContent RemoveChildAt method.

Shared by nsDocument for removals via DOM methods, sometimes. When called from nsDocument, aParent will be null.

Parameters:
aIndexThe index to remove at.
aNotifyWhether to notify.
aKidThe kid at aIndex. Must not be null.
aParentThe parent we're removing from.
aDocumentThe document we're removing from. Must be non-null if aParent is null and must match aParent->GetCurrentDoc() if aParent is not null.
aChildArrayThe child array to work with

Definition at line 2989 of file nsGenericElement.cpp.

{
  NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
  NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
                  "Incorrect aDocument");

  nsMutationGuard::DidMutate();

  nsContentOrDocument container(aParent, aDocument);
  
  NS_PRECONDITION(aKid && aKid->GetParent() == aParent &&
                  aKid == container.GetChildAt(aIndex) &&
                  container.IndexOf(aKid) == (PRInt32)aIndex, "Bogus aKid");

  mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);

  if (aNotify) {
    nsMutationGuard guard;

    if (aParent && 
        nsGenericElement::HasMutationListeners(aParent,
                                               NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
      nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEREMOVED, aKid);
      mutation.mRelatedNode = do_QueryInterface(aParent);
      
      nsEventStatus status = nsEventStatus_eIgnore;
      aKid->HandleDOMEvent(nsnull, &mutation, nsnull,
                           NS_EVENT_FLAG_INIT, &status);
    }
    
    // Someone may have removed the kid or any of its siblings while that event
    // was processing.
    if (guard.Mutated(0)) {
      aIndex = container.IndexOf(aKid);
      if (aIndex == (PRUint32)(-1)) {
        return NS_OK;
      }
    }
  }

  if (aParent && !aParent->IsContentOfType(nsIContent::eXUL)) {
    nsRange::OwnerChildRemoved(aParent, aIndex, aKid);
  }

  // Note that SetRootContent already deals with unbinding, so if we plan to
  // call it we shouldn't unbind ourselves.  It also deals with removing the
  // node from the child array, but not with notifying, unfortunately.  So we
  // have to call ContentRemoved ourselves after setting the root content.
  if (!aParent && aKid->IsContentOfType(nsIContent::eELEMENT)) {
    aDocument->SetRootContent(nsnull);
    if (aNotify) {
      aDocument->ContentRemoved(aParent, aKid, aIndex);
    }
  } else {
    aChildArray.RemoveChildAt(aIndex);

    if (aNotify && aDocument) {
      aDocument->ContentRemoved(aParent, aKid, aIndex);
    }

    aKid->UnbindFromTree();
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 950 of file nsGenericElement.cpp.

{
  EventListenerManagerMapEntry *lm =
    NS_STATIC_CAST(EventListenerManagerMapEntry *, entry);

  // Let the EventListenerManagerMapEntry clean itself up...
  lm->~EventListenerManagerMapEntry();
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 941 of file nsGenericElement.cpp.

{
  // Initialize the entry with placement new
  new (entry) EventListenerManagerMapEntry(key);
  return PR_TRUE;
}

Here is the caller graph for this function:

static PRBool IsAllowedAsChild ( nsIContent aNewChild,
PRUint16  aNewNodeType,
nsIContent aParent,
nsIDocument aDocument,
PRBool  aIsReplace,
nsIContent aRefContent 
) [static]

Definition at line 3088 of file nsGenericElement.cpp.

{
  NS_PRECONDITION(aNewChild, "Must have new child");
  NS_PRECONDITION(!aIsReplace || aRefContent,
                  "Must have ref content for replace");
#ifdef DEBUG
  PRUint16 debugNodeType = 0;
  nsCOMPtr<nsIDOMNode> debugNode(do_QueryInterface(aNewChild));
  nsresult debugRv = debugNode->GetNodeType(&debugNodeType);

  NS_PRECONDITION(NS_SUCCEEDED(debugRv) && debugNodeType == aNewNodeType,
                  "Bogus node type passed");
#endif

  if (aParent && nsContentUtils::ContentIsDescendantOf(aParent, aNewChild)) {
    return PR_FALSE;
  }

  // The allowed child nodes differ for documents and elements
  switch (aNewNodeType) {
  case nsIDOMNode::COMMENT_NODE :
  case nsIDOMNode::PROCESSING_INSTRUCTION_NODE :
    // OK in both cases
    return PR_TRUE;
  case nsIDOMNode::TEXT_NODE :
  case nsIDOMNode::CDATA_SECTION_NODE :
  case nsIDOMNode::ENTITY_REFERENCE_NODE :
    // Only allowed under elements
    return aParent != nsnull;
  case nsIDOMNode::ELEMENT_NODE :
    {
      if (aParent) {
        // Always ok to have elements under other elements
        return PR_TRUE;
      }

      nsIContent* rootContent = aDocument->GetRootContent();
      if (rootContent) {
        // Already have a documentElement, so this is only OK if we're
        // replacing it.
        return aIsReplace && rootContent == aRefContent;
      }

      // We don't have a documentElement yet.  Our one remaining constraint is
      // that the documentElement must come after the doctype.
      if (!aRefContent) {
        // Appending is just fine.
        return PR_TRUE;
      }

      // Now grovel for a doctype
      nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDocument);
      NS_ASSERTION(doc, "Shouldn't happen");
      nsCOMPtr<nsIDOMDocumentType> docType;
      doc->GetDoctype(getter_AddRefs(docType));
      nsCOMPtr<nsIContent> docTypeContent = do_QueryInterface(docType);
      
      if (!docTypeContent) {
        // It's all good.
        return PR_TRUE;
      }

      PRInt32 doctypeIndex = aDocument->IndexOf(docTypeContent);
      PRInt32 insertIndex = aDocument->IndexOf(aRefContent);

      // Now we're OK in the following two cases only:
      // 1) We're replacing something that's not before the doctype
      // 2) We're inserting before something that comes after the doctype 
      return aIsReplace ? (insertIndex >= doctypeIndex) :
        insertIndex > doctypeIndex;
    }
  case nsIDOMNode::DOCUMENT_TYPE_NODE :
    {
      if (aParent) {
        // no doctypes allowed under elements
        return PR_FALSE;
      }

      nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDocument);
      NS_ASSERTION(doc, "Shouldn't happen");
      nsCOMPtr<nsIDOMDocumentType> docType;
      doc->GetDoctype(getter_AddRefs(docType));
      nsCOMPtr<nsIContent> docTypeContent = do_QueryInterface(docType);
      if (docTypeContent) {
        // Already have a doctype, so this is only OK if we're replacing it
        return aIsReplace && docTypeContent == aRefContent;
      }

      // We don't have a doctype yet.  Our one remaining constraint is
      // that the doctype must come before the documentElement.
      nsIContent* rootContent = aDocument->GetRootContent();
      if (!rootContent) {
        // It's all good
        return PR_TRUE;
      }

      if (!aRefContent) {
        // Trying to append a doctype, but have a documentElement
        return PR_FALSE;
      }

      PRInt32 rootIndex = aDocument->IndexOf(rootContent);
      PRInt32 insertIndex = aDocument->IndexOf(aRefContent);

      // Now we're OK if and only if insertIndex <= rootIndex.  Indeed, either
      // we end up replacing aRefContent or we end up before it.  Either one is
      // ok as long as aRefContent is not after rootContent.
      return insertIndex <= rootIndex;
    }
  case nsIDOMNode::DOCUMENT_FRAGMENT_NODE :
    {
      // Note that for now we only allow nodes inside document fragments if
      // they're allowed inside elements.  If we ever change this to allow
      // doctype nodes in document fragments, we'll need to update this code
      if (aParent) {
        // All good here
        return PR_TRUE;
      }

      PRBool sawElement = PR_FALSE;
      PRUint32 count = aNewChild->GetChildCount();
      for (PRUint32 index = 0; index < count; ++index) {
        nsIContent* childContent = aNewChild->GetChildAt(index);
        NS_ASSERTION(childContent, "Something went wrong");
        if (childContent->IsContentOfType(nsIContent::eELEMENT)) {
          if (sawElement) {
            // Can't put two elements into a document
            return PR_FALSE;
          }
          sawElement = PR_TRUE;
        }
        // If we can put this content at the the right place, we might be ok;
        // if not, we bail out.
        nsCOMPtr<nsIDOMNode> childNode(do_QueryInterface(childContent));
        PRUint16 type;
        childNode->GetNodeType(&type);
        if (!IsAllowedAsChild(childContent, type, aParent, aDocument,
                              aIsReplace, aRefContent)) {
          return PR_FALSE;
        }
      }

      // Everything in the fragment checked out ok, so we can stick it in here
      return PR_TRUE;
    }
  default:
    /*
     * aNewChild is of invalid type.
     */
    break;
  }

  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool NodeHasMutationListeners ( nsISupports *  aNode) [static]

Definition at line 3881 of file nsGenericElement.cpp.

{
  nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(aNode));
  if (rec) {
    nsCOMPtr<nsIEventListenerManager> manager;
    rec->GetListenerManager(getter_AddRefs(manager));
    if (manager) {
      PRBool hasMutationListeners = PR_FALSE;
      manager->HasMutationListeners(&hasMutationListeners);
      if (hasMutationListeners)
        return PR_TRUE;
    }
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NopClearEntry ( PLDHashTable table,
PLDHashEntryHdr entry 
)

Definition at line 800 of file nsGenericElement.cpp.

{
  // Do nothing
}

Here is the caller graph for this function:

NS_INTERFACE_MAP_ENTRY_TEAROFF ( nsIDOMEventReceiver  ,
nsDOMEventRTTearoff::  Createthis 
)

Definition at line 299 of file nsContentIterator.cpp.

{
  nsContentIterator * iter = new nsContentIterator();
  if (!iter) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  NS_ADDREF(*aInstancePtrResult = iter);

  return NS_OK;
}

Definition at line 932 of file nsGenericElement.cpp.

{
  RangeListMapEntry *r = NS_STATIC_CAST(RangeListMapEntry *, entry);

  // Let the RangeListMapEntry clean itself up...
  r->~RangeListMapEntry();
}

Here is the call graph for this function:

Here is the caller graph for this function:

RangeListHashInitEntry ( PLDHashTable table,
PLDHashEntryHdr entry,
const void key 
)

Definition at line 923 of file nsGenericElement.cpp.

{
  // Initialize the entry with placement new
  new (entry) RangeListMapEntry(key);
  return PR_TRUE;
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 929 of file nsDocument.cpp.

Definition at line 930 of file nsDocument.cpp.