content/base/src/nsTextNode.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7  * Implementation of DOM Core's nsIDOMText node.
     8  */
    10 #include "nsTextNode.h"
    11 #include "mozilla/dom/TextBinding.h"
    12 #include "nsContentUtils.h"
    13 #include "mozilla/dom/DirectionalityUtils.h"
    14 #include "nsIDOMEventListener.h"
    15 #include "nsIDOMMutationEvent.h"
    16 #include "nsIDocument.h"
    17 #include "nsThreadUtils.h"
    18 #include "nsStubMutationObserver.h"
    19 #include "mozilla/IntegerPrintfMacros.h"
    20 #ifdef DEBUG
    21 #include "nsRange.h"
    22 #endif
    24 using namespace mozilla;
    25 using namespace mozilla::dom;
    27 /**
    28  * class used to implement attr() generated content
    29  */
    30 class nsAttributeTextNode MOZ_FINAL : public nsTextNode,
    31                                       public nsStubMutationObserver
    32 {
    33 public:
    34   NS_DECL_ISUPPORTS_INHERITED
    36   nsAttributeTextNode(already_AddRefed<nsINodeInfo>& aNodeInfo,
    37                       int32_t aNameSpaceID,
    38                       nsIAtom* aAttrName) :
    39     nsTextNode(aNodeInfo),
    40     mGrandparent(nullptr),
    41     mNameSpaceID(aNameSpaceID),
    42     mAttrName(aAttrName)
    43   {
    44     NS_ASSERTION(mNameSpaceID != kNameSpaceID_Unknown, "Must know namespace");
    45     NS_ASSERTION(mAttrName, "Must have attr name");
    46   }
    48   virtual ~nsAttributeTextNode() {
    49     NS_ASSERTION(!mGrandparent, "We were not unbound!");
    50   }
    52   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
    53                               nsIContent* aBindingParent,
    54                               bool aCompileEventHandlers);
    55   virtual void UnbindFromTree(bool aDeep = true,
    56                               bool aNullParent = true);
    58   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
    59   NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
    61   virtual nsGenericDOMDataNode *CloneDataNode(nsINodeInfo *aNodeInfo,
    62                                               bool aCloneText) const
    63   {
    64     already_AddRefed<nsINodeInfo> ni =
    65       nsCOMPtr<nsINodeInfo>(aNodeInfo).forget();
    66     nsAttributeTextNode *it = new nsAttributeTextNode(ni,
    67                                                       mNameSpaceID,
    68                                                       mAttrName);
    69     if (it && aCloneText) {
    70       it->mText = mText;
    71     }
    73     return it;
    74   }
    76   // Public method for the event to run
    77   void UpdateText() {
    78     UpdateText(true);
    79   }
    81 private:
    82   // Update our text to our parent's current attr value
    83   void UpdateText(bool aNotify);
    85   // This doesn't need to be a strong pointer because it's only non-null
    86   // while we're bound to the document tree, and it points to an ancestor
    87   // so the ancestor must be bound to the document tree the whole time
    88   // and can't be deleted.
    89   nsIContent* mGrandparent;
    90   // What attribute we're showing
    91   int32_t mNameSpaceID;
    92   nsCOMPtr<nsIAtom> mAttrName;
    93 };
    95 nsTextNode::~nsTextNode()
    96 {
    97 }
    99 NS_IMPL_ISUPPORTS_INHERITED(nsTextNode, nsGenericDOMDataNode, nsIDOMNode,
   100                             nsIDOMText, nsIDOMCharacterData)
   102 JSObject*
   103 nsTextNode::WrapNode(JSContext *aCx)
   104 {
   105   return TextBinding::Wrap(aCx, this);
   106 }
   108 bool
   109 nsTextNode::IsNodeOfType(uint32_t aFlags) const
   110 {
   111   return !(aFlags & ~(eCONTENT | eTEXT | eDATA_NODE));
   112 }
   114 nsGenericDOMDataNode*
   115 nsTextNode::CloneDataNode(nsINodeInfo *aNodeInfo, bool aCloneText) const
   116 {
   117   already_AddRefed<nsINodeInfo> ni = nsCOMPtr<nsINodeInfo>(aNodeInfo).forget();
   118   nsTextNode *it = new nsTextNode(ni);
   119   if (aCloneText) {
   120     it->mText = mText;
   121   }
   123   return it;
   124 }
   126 nsresult
   127 nsTextNode::AppendTextForNormalize(const char16_t* aBuffer, uint32_t aLength,
   128                                    bool aNotify, nsIContent* aNextSibling)
   129 {
   130   CharacterDataChangeInfo::Details details = {
   131     CharacterDataChangeInfo::Details::eMerge, aNextSibling
   132   };
   133   return SetTextInternal(mText.GetLength(), 0, aBuffer, aLength, aNotify, &details);
   134 }
   136 nsresult
   137 nsTextNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
   138                        nsIContent* aBindingParent, bool aCompileEventHandlers)
   139 {
   140   nsresult rv = nsGenericDOMDataNode::BindToTree(aDocument, aParent,
   141                                                  aBindingParent,
   142                                                  aCompileEventHandlers);
   143   NS_ENSURE_SUCCESS(rv, rv);
   145   SetDirectionFromNewTextNode(this);
   147   return NS_OK;
   148 }
   150 void nsTextNode::UnbindFromTree(bool aDeep, bool aNullParent)
   151 {
   152   ResetDirectionSetByTextNode(this, aNullParent);
   154   nsGenericDOMDataNode::UnbindFromTree(aDeep, aNullParent);
   155 }
   157 #ifdef DEBUG
   158 void
   159 nsTextNode::List(FILE* out, int32_t aIndent) const
   160 {
   161   int32_t index;
   162   for (index = aIndent; --index >= 0; ) fputs("  ", out);
   164   fprintf(out, "Text@%p", static_cast<const void*>(this));
   165   fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
   166   if (IsCommonAncestorForRangeInSelection()) {
   167     typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
   168     RangeHashTable* ranges =
   169       static_cast<RangeHashTable*>(GetProperty(nsGkAtoms::range));
   170     fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
   171   }
   172   fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
   173   fprintf(out, " refcount=%" PRIuPTR "<", mRefCnt.get());
   175   nsAutoString tmp;
   176   ToCString(tmp, 0, mText.GetLength());
   177   fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
   179   fputs(">\n", out);
   180 }
   182 void
   183 nsTextNode::DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const
   184 {
   185   if(aDumpAll) {
   186     int32_t index;
   187     for (index = aIndent; --index >= 0; ) fputs("  ", out);
   189     nsAutoString tmp;
   190     ToCString(tmp, 0, mText.GetLength());
   192     if(!tmp.EqualsLiteral("\\n")) {
   193       fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
   194       if(aIndent) fputs("\n", out);
   195     }
   196   }
   197 }
   198 #endif
   200 nsresult
   201 NS_NewAttributeContent(nsNodeInfoManager *aNodeInfoManager,
   202                        int32_t aNameSpaceID, nsIAtom* aAttrName,
   203                        nsIContent** aResult)
   204 {
   205   NS_PRECONDITION(aNodeInfoManager, "Missing nodeInfoManager");
   206   NS_PRECONDITION(aAttrName, "Must have an attr name");
   207   NS_PRECONDITION(aNameSpaceID != kNameSpaceID_Unknown, "Must know namespace");
   209   *aResult = nullptr;
   211   already_AddRefed<nsINodeInfo> ni = aNodeInfoManager->GetTextNodeInfo();
   213   nsAttributeTextNode* textNode = new nsAttributeTextNode(ni,
   214                                                           aNameSpaceID,
   215                                                           aAttrName);
   216   if (!textNode) {
   217     return NS_ERROR_OUT_OF_MEMORY;
   218   }
   220   NS_ADDREF(*aResult = textNode);
   222   return NS_OK;
   223 }
   225 NS_IMPL_ISUPPORTS_INHERITED(nsAttributeTextNode, nsTextNode,
   226                             nsIMutationObserver)
   228 nsresult
   229 nsAttributeTextNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
   230                                 nsIContent* aBindingParent,
   231                                 bool aCompileEventHandlers)
   232 {
   233   NS_PRECONDITION(aParent && aParent->GetParent(),
   234                   "This node can't be a child of the document or of the document root");
   236   nsresult rv = nsTextNode::BindToTree(aDocument, aParent,
   237                                        aBindingParent, aCompileEventHandlers);
   238   NS_ENSURE_SUCCESS(rv, rv);
   240   NS_ASSERTION(!mGrandparent, "We were already bound!");
   241   mGrandparent = aParent->GetParent();
   242   mGrandparent->AddMutationObserver(this);
   244   // Note that there is no need to notify here, since we have no
   245   // frame yet at this point.
   246   UpdateText(false);
   248   return NS_OK;
   249 }
   251 void
   252 nsAttributeTextNode::UnbindFromTree(bool aDeep, bool aNullParent)
   253 {
   254   // UnbindFromTree can be called anytime so we have to be safe.
   255   if (mGrandparent) {
   256     // aNullParent might not be true here, but we want to remove the
   257     // mutation observer anyway since we only need it while we're
   258     // in the document.
   259     mGrandparent->RemoveMutationObserver(this);
   260     mGrandparent = nullptr;
   261   }
   262   nsTextNode::UnbindFromTree(aDeep, aNullParent);
   263 }
   265 void
   266 nsAttributeTextNode::AttributeChanged(nsIDocument* aDocument,
   267                                       Element* aElement,
   268                                       int32_t aNameSpaceID,
   269                                       nsIAtom* aAttribute,
   270                                       int32_t aModType)
   271 {
   272   if (aNameSpaceID == mNameSpaceID && aAttribute == mAttrName &&
   273       aElement == mGrandparent) {
   274     // Since UpdateText notifies, do it when it's safe to run script.  Note
   275     // that if we get unbound while the event is up that's ok -- we'll just
   276     // have no grandparent when it fires, and will do nothing.
   277     void (nsAttributeTextNode::*update)() = &nsAttributeTextNode::UpdateText;
   278     nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this, update);
   279     nsContentUtils::AddScriptRunner(ev);
   280   }
   281 }
   283 void
   284 nsAttributeTextNode::NodeWillBeDestroyed(const nsINode* aNode)
   285 {
   286   NS_ASSERTION(aNode == static_cast<nsINode*>(mGrandparent), "Wrong node!");
   287   mGrandparent = nullptr;
   288 }
   290 void
   291 nsAttributeTextNode::UpdateText(bool aNotify)
   292 {
   293   if (mGrandparent) {
   294     nsAutoString attrValue;
   295     mGrandparent->GetAttr(mNameSpaceID, mAttrName, attrValue);
   296     SetText(attrValue, aNotify);
   297   }  
   298 }

mercurial