OSDN Git Service

Cherry pick 94857
[android-x86/external-webkit.git] / Source / WebCore / rendering / RenderObjectChildList.cpp
index fa4f902..b6c7992 100644 (file)
@@ -36,6 +36,7 @@
 #include "RenderInline.h"
 #include "RenderLayer.h"
 #include "RenderListItem.h"
+#include "RenderQuote.h"
 #include "RenderStyle.h"
 #include "RenderTextFragment.h"
 #include "RenderView.h"
@@ -128,6 +129,9 @@ RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render
     oldChild->setNextSibling(0);
     oldChild->setParent(0);
 
+    RenderCounter::rendererRemovedFromTree(oldChild);
+    RenderQuote::rendererRemovedFromTree(oldChild);
+
     if (AXObjectCache::accessibilityEnabled())
         owner->document()->axObjectCache()->childrenChanged(owner);
 
@@ -174,7 +178,8 @@ void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* n
         if (!newChild->isFloatingOrPositioned() && owner->childrenInline())
             owner->dirtyLinesFromChangedChild(newChild);
     }
-
+    RenderCounter::rendererSubtreeAttached(newChild);
+    RenderQuote::rendererSubtreeAttached(newChild);
     newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
     if (!owner->normalChildNeedsLayout())
         owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
@@ -234,6 +239,8 @@ void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* c
             owner->dirtyLinesFromChangedChild(child);
     }
 
+    RenderCounter::rendererSubtreeAttached(child);
+    RenderQuote::rendererSubtreeAttached(child);
     child->setNeedsLayoutAndPrefWidthsRecalc();
     if (!owner->normalChildNeedsLayout())
         owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
@@ -242,59 +249,6 @@ void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* c
         owner->document()->axObjectCache()->childrenChanged(owner);
 }
 
-static RenderObject* beforeAfterContainer(RenderObject* container, PseudoId type)
-{
-    if (type == BEFORE) {
-        // An anonymous (generated) inline run-in that has PseudoId BEFORE must come from a grandparent.
-        // Therefore we should skip these generated run-ins when checking our immediate children.
-        // If we don't find our :before child immediately, then we should check if we own a
-        // generated inline run-in in the next level of children.
-        RenderObject* first = container;
-        do {
-            // Skip list markers and generated run-ins
-            first = first->firstChild();
-            while (first && (first->isListMarker() || (first->isRenderInline() && first->isRunIn() && first->isAnonymous())))
-                first = first->nextSibling();
-        } while (first && first->isAnonymous() && first->style()->styleType() == NOPSEUDO);
-
-        if (!first)
-            return 0;
-
-        if (first->style()->styleType() == type)
-            return first;
-
-        // Check for a possible generated run-in, using run-in positioning rules.
-        // Skip inlines and floating / positioned blocks, and place as the first child.
-        first = container->firstChild();
-        if (!first->isRenderBlock())
-            return 0;
-        while (first && first->isFloatingOrPositioned())
-            first = first->nextSibling();
-        if (first) {
-            first = first->firstChild();
-            // We still need to skip any list markers that could exist before the run-in.
-            while (first && first->isListMarker())
-                first = first->nextSibling();
-            if (first && first->style()->styleType() == type && first->isRenderInline() && first->isRunIn() && first->isAnonymous())
-                return first;
-        }
-        return 0;
-    }
-
-    if (type == AFTER) {
-        RenderObject* last = container;
-        do {
-            last = last->lastChild();
-        } while (last && last->isAnonymous() && last->style()->styleType() == NOPSEUDO && !last->isListMarker());
-        if (last && last->style()->styleType() != type)
-            return 0;
-        return last;
-    }
-
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-
 static RenderObject* findBeforeAfterParent(RenderObject* object)
 {
     // Only table parts need to search for the :before or :after parent
@@ -304,35 +258,64 @@ static RenderObject* findBeforeAfterParent(RenderObject* object)
     RenderObject* beforeAfterParent = object;
     while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage()))
         beforeAfterParent = beforeAfterParent->firstChild();
-    return beforeAfterParent;
+    return beforeAfterParent ? beforeAfterParent->parent() : 0;
 }
 
-static void invalidateCountersInContainer(RenderObject* container, const AtomicString& identifier)
+RenderObject* RenderObjectChildList::beforePseudoElementRenderer(const RenderObject* owner) const
 {
-    if (!container)
-        return;
-    container = findBeforeAfterParent(container);
-    if (!container)
-        return;
-    // Sometimes the counter is attached directly on the container.
-    if (container->isCounter()) {
-        toRenderCounter(container)->invalidate(identifier);
-        return;
-    }
-    for (RenderObject* content = container->firstChild(); content; content = content->nextSibling()) {
-        if (content->isCounter())
-            toRenderCounter(content)->invalidate(identifier);
+    // An anonymous (generated) inline run-in that has PseudoId BEFORE must come from a grandparent.
+    // Therefore we should skip these generated run-ins when checking our immediate children.
+    // If we don't find our :before child immediately, then we should check if we own a
+    // generated inline run-in in the next level of children.
+    RenderObject* first = const_cast<RenderObject*>(owner);
+    do {
+        // Skip list markers and generated run-ins
+        first = first->firstChild();
+        while (first && first->isListMarker()) {
+            if (first->parent() != owner && first->parent()->isAnonymousBlock())
+                first = first->parent();
+            first = first->nextSibling();
+        }
+        while (first && first->isRenderInline() && first->isRunIn())
+            first = first->nextSibling();
+    } while (first && first->isAnonymous() && first->style()->styleType() == NOPSEUDO);
+
+    if (!first)
+        return 0;
+
+    if (first->style()->styleType() == BEFORE)
+        return first;
+
+    // Check for a possible generated run-in, using run-in positioning rules.
+    // Skip inlines and floating / positioned blocks, and place as the first child.
+    first = owner->firstChild();
+    if (!first->isRenderBlock())
+        return 0;
+    while (first && first->isFloatingOrPositioned())
+        first = first->nextSibling();
+    if (first) {
+        first = first->firstChild();
+        // We still need to skip any list markers that could exist before the run-in.
+        while (first && first->isListMarker())
+            first = first->nextSibling();
+        if (first && first->style()->styleType() == BEFORE && first->isRenderInline() && first->isRunIn())
+            return first;
     }
+    return 0;
 }
 
-void RenderObjectChildList::invalidateCounters(RenderObject* owner, const AtomicString& identifier)
+RenderObject* RenderObjectChildList::afterPseudoElementRenderer(const RenderObject* owner) const
 {
-    ASSERT(!owner->documentBeingDestroyed());
-    invalidateCountersInContainer(beforeAfterContainer(owner, BEFORE), identifier);
-    invalidateCountersInContainer(beforeAfterContainer(owner, AFTER), identifier);
+    RenderObject* last = const_cast<RenderObject*>(owner);
+    do {
+        last = last->lastChild();
+    } while (last && last->isAnonymous() && last->style()->styleType() == NOPSEUDO && !last->isListMarker());
+    if (last && last->style()->styleType() != AFTER)
+        return 0;
+    return last;
 }
 
-void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, RenderObject* styledObject)
+void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject)
 {
     // Double check that the document did in fact use generated content rules.  Otherwise we should not have been called.
     ASSERT(owner->document()->usesBeforeAfterRules());
@@ -345,7 +328,18 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo
         styledObject = owner;
 
     RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
-    RenderObject* child = beforeAfterContainer(owner, type);
+    RenderObject* child;
+    switch (type) {
+    case BEFORE:
+        child = beforePseudoElementRenderer(owner);
+        break;
+    case AFTER:
+        child = afterPseudoElementRenderer(owner);
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+        return;
+    }
 
     // Whether or not we currently have generated content attached.
     bool oldContentPresent = child;
@@ -448,10 +442,14 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo
                 renderer = image;
                 break;
             }
-            case CONTENT_COUNTER:
-                renderer = new (owner->renderArena()) RenderCounter(owner->document(), *content->counter());
-                renderer->setStyle(pseudoElementStyle);
-                break;
+        case CONTENT_COUNTER:
+            renderer = new (owner->renderArena()) RenderCounter(owner->document(), *content->counter());
+            renderer->setStyle(pseudoElementStyle);
+            break;
+        case CONTENT_QUOTE:
+            renderer = new (owner->renderArena()) RenderQuote(owner->document(), content->quote());
+            renderer->setStyle(pseudoElementStyle);
+            break;
         }
 
         if (renderer) {
@@ -459,7 +457,15 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo
                 // Make a generated box that might be any display type now that we are able to drill down into children
                 // to find the original content properly.
                 generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle);
+                ASSERT(styledObject->node()); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements.
+                generatedContentContainer->setNode(styledObject->node()); // This allows access to the generatingNode.
                 generatedContentContainer->setStyle(pseudoElementStyle);
+                if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) {
+                    // The generated content container is not allowed here -> abort.
+                    generatedContentContainer->destroy();
+                    renderer->destroy();
+                    return;
+                }
                 owner->addChild(generatedContentContainer, insertBefore);
             }
             if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle))