Changeset 166144 in webkit


Ignore:
Timestamp:
Mar 23, 2014 2:37:56 PM (10 years ago)
Author:
Darin Adler
Message:

Remove code in HTMLObjectElement attribute parsing that forces style resolution and layout
https://bugs.webkit.org/show_bug.cgi?id=130653

Reviewed by Antti Koivisto.

Source/WebCore:

  • dom/ContainerNode.cpp: Moved the post-attach callback code from here to

StyleResolveTree.h/cpp.

  • dom/ContainerNode.h: Ditto.
  • dom/Document.cpp:

(WebCore::Document::recalcStyle): Use Style::PostResolutionCallbackDisabler instead of
PostAttachCallbackDisabler.

  • dom/Element.h: Moved the post-attach callback code from here to StyleResolveTree.h/cpp.
  • html/HTMLEmbedElement.cpp:

(WebCore::HTMLEmbedElement::parseAttribute): Simplified the code for typeAttr, turning
it into a 1-liner. Added a FIXME in codeAttr about the fact that it does not have the
code to trigger image loads. Changed srcAttr to call updateImageLoaderWithNewURLSoon to
do the image loading logic.

  • html/HTMLFormControlElement.cpp:

(WebCore::HTMLFormControlElement::didAttachRenderers): Updated to use
Style::queuePostResolutionCallback and use a lambda instead of a function.
(WebCore::HTMLFormControlElement::didRecalcStyle): Ditto. Also added RefPtr instead
of just using wishful thinking to keep the object alive.

  • html/HTMLFrameOwnerElement.cpp:

(WebCore::HTMLFrameOwnerElement::scheduleSetNeedsStyleRecalc): Ditto.

  • html/HTMLObjectElement.cpp:

(WebCore::HTMLObjectElement::parseAttribute):: Simplified the code for typeAttr, turning
it into a 1-liner. Changed dataAttr to use updateImageLoaderWithNewURLSoon(). Also made
it call setNeedsWidgetUpdate(true) unconditionally after checking carefully to see that's
harmless if there is no renderer. Changed classidAttr to call setNeedsWidgetUpdate(true)
unconditionally and not set m_classId.
(WebCore::HTMLObjectElement::shouldAllowQuickTimeClassIdQuirk): Use fastGetAttribute
instead of classId and descendantsOfType instead of getElementsByTagName.
(WebCore::HTMLObjectElement::hasValidClassId): Use fastGetAttribute instead of classId.
(WebCore::HTMLObjectElement::renderFallbackContent): Use imageLoader instead of m_imageLoader.

  • html/HTMLObjectElement.h: Removed classId, since there is no reason to cache that

attribute in a data member. Rearranged header, making more private, and fixing some typos,
and doing a "using" instead of a function to disambiguate the inherited form functions.

  • html/HTMLPlugInImageElement.cpp:

(WebCore::HTMLPlugInImageElement::HTMLPlugInImageElement): Initialize m_needsImageReload.
(WebCore::HTMLPlugInImageElement::createElementRenderer): Fixed some code that assumed the
first child of the shadow root is guaranteed to be an element.
(WebCore::HTMLPlugInImageElement::didRecalcStyle): Added. Calls the new
scheduleUpdateForAfterStyleResolution function.
(WebCore::HTMLPlugInImageElement::didAttachRenderers): Moved all the logic from this
function into scheduleUpdateForAfterStyleResolution. Also added a call through to the base
class; cleaner even though it's just an assertion.
(WebCore::HTMLPlugInImageElement::scheduleUpdateForAfterStyleResolution): Added.
Schedules a call to updateAfterStyleResolution when needed.
(WebCore::HTMLPlugInImageElement::updateAfterStyleResolution): Added.
Combines updateWidgetIfNecessary and startLoadingImage, and also deals with the new
m_needsImageReload boolean in cases where no actual loading is done.
(WebCore::HTMLPlugInImageElement::removedFrom): Added. Do not delay the load event of
document once this element is removed, clears m_needsImageReload.
(WebCore::HTMLPlugInImageElement::didMoveToNewDocument): Removed null check on oldDocument,
since m_needsDocumentActivationCallbacks can't be true if the old document was null.
(WebCore::is100Percent): Added helper to make function below more readable.
(WebCore::HTMLPlugInImageElement::subframeLoaderWillCreatePlugIn): Restructured the code a
bit. The part that attracted my attention was the local variable of type RenderBox, which
was named renderEmbeddedObject. Turns out the caller guarantees to only call this if there
is a renderer of type RenderEmbeddedObject, so depend on that.
(WebCore::HTMLPlugInImageElement::setNeedsImageReload): Added. When called with true, sets
the flag and triggers a style recalculation, and lets updateAfterStyleResolution do the rest.
When called with false, reverses the effects and stops delaying the load event.

  • html/HTMLPlugInImageElement.h: Trimmed includes a bit. Made more members private.

Marked more function members final. Made a protected imageLoader function so that
m_imageLoader can be private. Added new protected function updateImageLoaderWithNewURLSoon,
as well as other new private functions. Made m_imageLoader be std::unique_ptr instead of
OwnPtr, and added m_needsImageReload.

  • style/StyleResolveTree.cpp:

(WebCore::Style::needsPseudoElement): Fixed spelling error in the name of this function.
(WebCore::Style::attachBeforeOrAfterPseudoElementIfNeeded): Updated for name change.
(WebCore::Style::attachRenderTree): Update for new name of PostResolutionCallbackDisabler.
(WebCore::Style::updateBeforeOrAfterPseudoElement): Updated for name change.
(WebCore::Style::postResolutionCallbackQueue): Added.
(WebCore::Style::queuePostResolutionCallback): Added.
(WebCore::Style::suspendMemoryCacheClientCalls): Added. This is a side effect of the original
PostAttachCallbackDisabler that is now done in a cleaner way, using the callback queue, instead
of as a special case. It should not work for multiple documents across multiple pages instead of
only the outermost one.
(WebCore::Style::PostResolutionCallbackDisabler::PostResolutionCallbackDisabler): Added.
Calls suspendMemoryCacheClientCalls, but a FIXME tries to point out why that isn't so great.
(WebCore::Style::PostResolutionCallbackDisabler::~PostResolutionCallbackDisabler): Added.
(WebCore::Style::postResolutionCallbacksAreSuspended): Added.

  • style/StyleResolveTree.h: Added queuePostResolutionCallback and

postResolutionCallbacksAreSuspended. Also added PostResolutionCallbackDisabler, which should
eventually become a private implementation detail.

Source/WebKit/mac:

  • WebCoreSupport/WebFrameLoaderClient.mm: Call toHTMLPlugInImageElement instead of

doing a static_cast.

LayoutTests:

  • plugins/plugin-remove-readystatechange-expected.txt: Added a blank line; not what this

test is testing, but the different timing of loads results in this blank line.

  • plugins/plugin-remove-readystatechange.html: Updated test to use waitUntilDone/notifyDone

rather than racing. Added a computation of offsetLeft to trigger layout and adding a long
comment explaining why this is needed and potentially insufficient in the long run.

  • svg/custom/object-no-size-attributes-expected.txt: Removed expectation of an empty text

renderer from the render tree.

  • svg/custom/object-no-size-attributes.xhtml: Restructured the source so there is no text

to render. Without this, we were seeing two text renderers due to the loading timing change.

Location:
trunk
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r166141 r166144  
     12014-03-23  Darin Adler  <darin@apple.com>
     2
     3        Remove code in HTMLObjectElement attribute parsing that forces style resolution and layout
     4        https://bugs.webkit.org/show_bug.cgi?id=130653
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * plugins/plugin-remove-readystatechange-expected.txt: Added a blank line; not what this
     9        test is testing, but the different timing of loads results in this blank line.
     10        * plugins/plugin-remove-readystatechange.html: Updated test to use waitUntilDone/notifyDone
     11        rather than racing. Added a computation of offsetLeft to trigger layout and adding a long
     12        comment explaining why this is needed and potentially insufficient in the long run.
     13
     14        * svg/custom/object-no-size-attributes-expected.txt: Removed expectation of an empty text
     15        renderer from the render tree.
     16        * svg/custom/object-no-size-attributes.xhtml: Restructured the source so there is no text
     17        to render. Without this, we were seeing two text renderers due to the loading timing change.
     18
    1192014-03-23  James Craig  <jcraig@apple.com>
    220
  • trunk/LayoutTests/plugins/plugin-remove-readystatechange-expected.txt

    r160908 r166144  
    11ALERT: PASS: element could not be re-appended
    22This test passes if it does not trip an assert in debug builds. It ensures a readystatechange event can't get dispatched until after a plugin is fully removed.
     3
  • trunk/LayoutTests/plugins/plugin-remove-readystatechange.html

    r128524 r166144  
    88<embed id="viewer" src="resources/simple_blank.swf"></embed>
    99<script>
    10 if (window.testRunner)
     10if (window.testRunner) {
    1111    testRunner.dumpAsText();
     12    testRunner.waitUntilDone();
     13}
    1214
    1315var i = 0;
     
    1921        catch (e) {
    2022            alert('PASS: element could not be re-appended');
    21        }
     23        }
     24        if (window.testRunner)
     25            testRunner.notifyDone();
    2226    }
    2327    i++;
     
    2529
    2630window.addEventListener('DOMContentLoaded', function() {
     31    // This test relies on removing the embed element while it is actively loading.
     32    // There's no observable event that creates the exact right timing for that.
     33    // As of this writing, after DOMContentLoaded, then next layout is the right time.
     34    // Here we evaluate document.body.offsetLeft to trigger that layout. But really,
     35    // this is a race condition, nothing guarantees that the load starts at that moment,
     36    // and we might have to revise this test again in the future.
     37    document.body.offsetLeft;
    2738    document.body.removeChild(document.getElementById('viewer'));
    2839});
  • trunk/LayoutTests/svg/custom/object-no-size-attributes-expected.txt

    r161140 r166144  
    1010          RenderSVGRoot {svg} at (0,0) size 100x100
    1111            RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
    12       RenderText {#text} at (0,0) size 0x0
  • trunk/LayoutTests/svg/custom/object-no-size-attributes.xhtml

    r87526 r166144  
    22<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    33<body>
    4 <object type="image/svg+xml" data="data:image/svg+xml;charset=utf-8,%3Csvg%20width%3D%22100px%22%20height%3D%22100px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20fill%3D%22green%22%20width%3D%22100px%22%20height%3D%22100px%22%20%2F%3E%3C%2Fsvg%3E" style='background: red'></object>
    5 
    6 <!--
     4<object type="image/svg+xml" data="data:image/svg+xml;charset=utf-8,%3Csvg%20width%3D%22100px%22%20height%3D%22100px%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20fill%3D%22green%22%20width%3D%22100px%22%20height%3D%22100px%22%20%2F%3E%3C%2Fsvg%3E" style='background: red'></object><!--
    75100px x 100px SVG
    86
     
    1412
    1513You should see a 100 x 100 green square above.  No red should be visible.  &lt;object&gt; tags should treat the width/height attributes on an embeded SVG as the intrinsic size and not default to the CSS default of 300 x 150.
    16 -->
    17 
    18 </body>
     14--></body>
    1915</html>
  • trunk/Source/WebCore/ChangeLog

    r166143 r166144  
     12014-03-23  Darin Adler  <darin@apple.com>
     2
     3        Remove code in HTMLObjectElement attribute parsing that forces style resolution and layout
     4        https://bugs.webkit.org/show_bug.cgi?id=130653
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * dom/ContainerNode.cpp: Moved the post-attach callback code from here to
     9        StyleResolveTree.h/cpp.
     10        * dom/ContainerNode.h: Ditto.
     11
     12        * dom/Document.cpp:
     13        (WebCore::Document::recalcStyle): Use Style::PostResolutionCallbackDisabler instead of
     14        PostAttachCallbackDisabler.
     15
     16        * dom/Element.h: Moved the post-attach callback code from here to StyleResolveTree.h/cpp.
     17
     18        * html/HTMLEmbedElement.cpp:
     19        (WebCore::HTMLEmbedElement::parseAttribute): Simplified the code for typeAttr, turning
     20        it into a 1-liner. Added a FIXME in codeAttr about the fact that it does not have the
     21        code to trigger image loads. Changed srcAttr to call updateImageLoaderWithNewURLSoon to
     22        do the image loading logic.
     23
     24        * html/HTMLFormControlElement.cpp:
     25        (WebCore::HTMLFormControlElement::didAttachRenderers): Updated to use
     26        Style::queuePostResolutionCallback and use a lambda instead of a function.
     27        (WebCore::HTMLFormControlElement::didRecalcStyle): Ditto. Also added RefPtr instead
     28        of just using wishful thinking to keep the object alive.
     29        * html/HTMLFrameOwnerElement.cpp:
     30        (WebCore::HTMLFrameOwnerElement::scheduleSetNeedsStyleRecalc): Ditto.
     31
     32        * html/HTMLObjectElement.cpp:
     33        (WebCore::HTMLObjectElement::parseAttribute):: Simplified the code for typeAttr, turning
     34        it into a 1-liner. Changed dataAttr to use updateImageLoaderWithNewURLSoon(). Also made
     35        it call setNeedsWidgetUpdate(true) unconditionally after checking carefully to see that's
     36        harmless if there is no renderer. Changed classidAttr to call setNeedsWidgetUpdate(true)
     37        unconditionally and not set m_classId.
     38        (WebCore::HTMLObjectElement::shouldAllowQuickTimeClassIdQuirk): Use fastGetAttribute
     39        instead of classId and descendantsOfType instead of getElementsByTagName.
     40        (WebCore::HTMLObjectElement::hasValidClassId): Use fastGetAttribute instead of classId.
     41        (WebCore::HTMLObjectElement::renderFallbackContent): Use imageLoader instead of m_imageLoader.
     42
     43        * html/HTMLObjectElement.h: Removed classId, since there is no reason to cache that
     44        attribute in a data member. Rearranged header, making more private, and fixing some typos,
     45        and doing a "using" instead of a function to disambiguate the inherited form functions.
     46
     47        * html/HTMLPlugInImageElement.cpp:
     48        (WebCore::HTMLPlugInImageElement::HTMLPlugInImageElement): Initialize m_needsImageReload.
     49        (WebCore::HTMLPlugInImageElement::createElementRenderer): Fixed some code that assumed the
     50        first child of the shadow root is guaranteed to be an element.
     51        (WebCore::HTMLPlugInImageElement::didRecalcStyle): Added. Calls the new
     52        scheduleUpdateForAfterStyleResolution function.
     53        (WebCore::HTMLPlugInImageElement::didAttachRenderers): Moved all the logic from this
     54        function into scheduleUpdateForAfterStyleResolution. Also added a call through to the base
     55        class; cleaner even though it's just an assertion.
     56        (WebCore::HTMLPlugInImageElement::scheduleUpdateForAfterStyleResolution): Added.
     57        Schedules a call to updateAfterStyleResolution when needed.
     58        (WebCore::HTMLPlugInImageElement::updateAfterStyleResolution): Added.
     59        Combines updateWidgetIfNecessary and startLoadingImage, and also deals with the new
     60        m_needsImageReload boolean in cases where no actual loading is done.
     61        (WebCore::HTMLPlugInImageElement::removedFrom): Added. Do not delay the load event of
     62        document once this element is removed, clears m_needsImageReload.
     63        (WebCore::HTMLPlugInImageElement::didMoveToNewDocument): Removed null check on oldDocument,
     64        since m_needsDocumentActivationCallbacks can't be true if the old document was null.
     65        (WebCore::is100Percent): Added helper to make function below more readable.
     66        (WebCore::HTMLPlugInImageElement::subframeLoaderWillCreatePlugIn): Restructured the code a
     67        bit. The part that attracted my attention was the local variable of type RenderBox, which
     68        was named renderEmbeddedObject. Turns out the caller guarantees to only call this if there
     69        is a renderer of type RenderEmbeddedObject, so depend on that.
     70        (WebCore::HTMLPlugInImageElement::setNeedsImageReload): Added. When called with true, sets
     71        the flag and triggers a style recalculation, and lets updateAfterStyleResolution do the rest.
     72        When called with false, reverses the effects and stops delaying the load event.
     73
     74        * html/HTMLPlugInImageElement.h: Trimmed includes a bit. Made more members private.
     75        Marked more function members final. Made a protected imageLoader function so that
     76        m_imageLoader can be private. Added new protected function updateImageLoaderWithNewURLSoon,
     77        as well as other new private functions. Made m_imageLoader be std::unique_ptr instead of
     78        OwnPtr, and added m_needsImageReload.
     79
     80        * style/StyleResolveTree.cpp:
     81        (WebCore::Style::needsPseudoElement): Fixed spelling error in the name of this function.
     82        (WebCore::Style::attachBeforeOrAfterPseudoElementIfNeeded): Updated for name change.
     83        (WebCore::Style::attachRenderTree): Update for new name of PostResolutionCallbackDisabler.
     84        (WebCore::Style::updateBeforeOrAfterPseudoElement): Updated for name change.
     85        (WebCore::Style::postResolutionCallbackQueue): Added.
     86        (WebCore::Style::queuePostResolutionCallback): Added.
     87        (WebCore::Style::suspendMemoryCacheClientCalls): Added. This is a side effect of the original
     88        PostAttachCallbackDisabler that is now done in a cleaner way, using the callback queue, instead
     89        of as a special case. It should not work for multiple documents across multiple pages instead of
     90        only the outermost one.
     91        (WebCore::Style::PostResolutionCallbackDisabler::PostResolutionCallbackDisabler): Added.
     92        Calls suspendMemoryCacheClientCalls, but a FIXME tries to point out why that isn't so great.
     93        (WebCore::Style::PostResolutionCallbackDisabler::~PostResolutionCallbackDisabler): Added.
     94        (WebCore::Style::postResolutionCallbacksAreSuspended): Added.
     95
     96        * style/StyleResolveTree.h: Added queuePostResolutionCallback and
     97        postResolutionCallbacksAreSuspended. Also added PostResolutionCallbackDisabler, which should
     98        eventually become a private implementation detail.
     99
    11002014-03-23  Sam Weinig  <sam@webkit.org>
    2101
  • trunk/Source/WebCore/dom/ContainerNode.cpp

    r164854 r166144  
    3838#include "JSNode.h"
    3939#include "LabelsNodeList.h"
    40 #include "LoaderStrategy.h"
    41 #include "MemoryCache.h"
    4240#include "MutationEvent.h"
    4341#include "NameNodeList.h"
    4442#include "NodeRareData.h"
    4543#include "NodeRenderStyle.h"
    46 #include "PlatformStrategies.h"
    4744#include "RadioNodeList.h"
    4845#include "RenderBox.h"
     
    6360static void dispatchChildInsertionEvents(Node&);
    6461static void dispatchChildRemovalEvents(Node&);
    65 
    66 typedef std::pair<RefPtr<Node>, unsigned> CallbackParameters;
    67 typedef std::pair<NodeCallback, CallbackParameters> CallbackInfo;
    68 typedef Vector<CallbackInfo> NodeCallbackQueue;
    69 
    70 static NodeCallbackQueue* s_postAttachCallbackQueue;
    71 
    72 static size_t s_attachDepth;
    73 static bool s_shouldReEnableMemoryCacheCallsAfterAttach;
    7462
    7563ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0;
     
    757745
    758746    newChild->setNeedsStyleRecalc(ReconstructRenderTree);
    759 }
    760 
    761 void ContainerNode::suspendPostAttachCallbacks(Document& document)
    762 {
    763     if (!s_attachDepth) {
    764         ASSERT(!s_shouldReEnableMemoryCacheCallsAfterAttach);
    765         if (Page* page = document.page()) {
    766             // FIXME: How can this call be specific to one Page, while the
    767             // s_attachDepth is a global? Doesn't make sense.
    768             if (page->areMemoryCacheClientCallsEnabled()) {
    769                 page->setMemoryCacheClientCallsEnabled(false);
    770                 s_shouldReEnableMemoryCacheCallsAfterAttach = true;
    771             }
    772         }
    773         platformStrategies()->loaderStrategy()->resourceLoadScheduler()->suspendPendingRequests();
    774     }
    775     ++s_attachDepth;
    776 }
    777 
    778 void ContainerNode::resumePostAttachCallbacks(Document& document)
    779 {
    780     if (s_attachDepth == 1) {
    781         Ref<Document> protect(document);
    782 
    783         if (s_postAttachCallbackQueue)
    784             dispatchPostAttachCallbacks();
    785         if (s_shouldReEnableMemoryCacheCallsAfterAttach) {
    786             s_shouldReEnableMemoryCacheCallsAfterAttach = false;
    787             if (Page* page = document.page())
    788                 page->setMemoryCacheClientCallsEnabled(true);
    789         }
    790         platformStrategies()->loaderStrategy()->resourceLoadScheduler()->resumePendingRequests();
    791     }
    792     --s_attachDepth;
    793 }
    794 
    795 void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node& node, unsigned callbackData)
    796 {
    797     if (!s_postAttachCallbackQueue)
    798         s_postAttachCallbackQueue = new NodeCallbackQueue;
    799    
    800     s_postAttachCallbackQueue->append(CallbackInfo(callback, CallbackParameters(&node, callbackData)));
    801 }
    802 
    803 bool ContainerNode::postAttachCallbacksAreSuspended()
    804 {
    805     return s_attachDepth;
    806 }
    807 
    808 void ContainerNode::dispatchPostAttachCallbacks()
    809 {
    810     // We recalculate size() each time through the loop because a callback
    811     // can add more callbacks to the end of the queue.
    812     for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) {
    813         const CallbackInfo& info = (*s_postAttachCallbackQueue)[i];
    814         NodeCallback callback = info.first;
    815         CallbackParameters params = info.second;
    816 
    817         callback(*params.first, params.second);
    818     }
    819     s_postAttachCallbackQueue->clear();
    820747}
    821748
  • trunk/Source/WebCore/dom/ContainerNode.h

    r164854 r166144  
    8080
    8181class ContainerNode : public Node {
    82     friend class PostAttachCallbackDisabler;
    8382public:
    8483    virtual ~ContainerNode();
     
    141140    explicit ContainerNode(Document&, ConstructionType = CreateContainer);
    142141
    143     static void queuePostAttachCallback(NodeCallback, Node&, unsigned = 0);
    144     static bool postAttachCallbacksAreSuspended();
    145 
    146142    template<class GenericNode, class GenericNodeContainer>
    147143    friend void appendChildToContainer(GenericNode* child, GenericNodeContainer&);
     
    157153    void removeBetween(Node* previousChild, Node* nextChild, Node& oldChild);
    158154    void insertBeforeCommon(Node& nextChild, Node& oldChild);
    159 
    160     static void dispatchPostAttachCallbacks();
    161     static void suspendPostAttachCallbacks(Document&);
    162     static void resumePostAttachCallbacks(Document&);
    163155
    164156    bool getUpperLeftCorner(FloatPoint&) const;
  • trunk/Source/WebCore/dom/Document.cpp

    r165848 r166144  
    17571757    m_inStyleRecalc = true;
    17581758    {
    1759         PostAttachCallbackDisabler disabler(*this);
     1759        Style::PostResolutionCallbackDisabler disabler(*this);
    17601760        WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
    17611761
  • trunk/Source/WebCore/dom/Element.h

    r166124 r166144  
    799799}
    800800
    801 class PostAttachCallbackDisabler {
    802 public:
    803     explicit PostAttachCallbackDisabler(Document& document)
    804         : m_document(document)
    805     {
    806         Element::suspendPostAttachCallbacks(m_document);
    807     }
    808 
    809     ~PostAttachCallbackDisabler()
    810     {
    811         Element::resumePostAttachCallbacks(m_document);
    812     }
    813 
    814 private:
    815     Document& m_document;
    816 };
    817 
    818801} // namespace WebCore
    819802
  • trunk/Source/WebCore/html/HTMLEmbedElement.cpp

    r163457 r166144  
    9898{
    9999    if (name == typeAttr) {
    100         m_serviceType = value.string().lower();
    101         size_t pos = m_serviceType.find(";");
    102         if (pos != notFound)
    103             m_serviceType = m_serviceType.left(pos);
    104     } else if (name == codeAttr)
     100        m_serviceType = value.string().left(value.find(";")).lower();
     101        // FIXME: The only difference between this and HTMLObjectElement's corresponding
     102        // code is that HTMLObjectElement does setNeedsWidgetUpdate(true). Consider moving
     103        // this up to the HTMLPlugInImageElement to be shared.
     104    } else if (name == codeAttr) {
    105105        m_url = stripLeadingAndTrailingHTMLSpaces(value);
    106     else if (name == srcAttr) {
     106        // FIXME: Why no call to updateImageLoaderWithNewURLSoon?
     107        // FIXME: If both code and src attributes are specified, last one parsed/changed wins. That can't be right!
     108    } else if (name == srcAttr) {
    107109        m_url = stripLeadingAndTrailingHTMLSpaces(value);
    108         document().updateStyleIfNeeded();
    109         if (renderer() && isImageType()) {
    110             if (!m_imageLoader)
    111                 m_imageLoader = adoptPtr(new HTMLImageLoader(*this));
    112             m_imageLoader->updateFromElementIgnoringPreviousError();
    113         }
     110        updateImageLoaderWithNewURLSoon();
     111        // FIXME: If both code and src attributes are specified, last one parsed/changed wins. That can't be right!
    114112    } else
    115113        HTMLPlugInImageElement::parseAttribute(name, value);
  • trunk/Source/WebCore/html/HTMLFormControlElement.cpp

    r164822 r166144  
    208208}
    209209
    210 static void focusPostAttach(Node& element, unsigned)
    211 {
    212     toElement(element).focus();
    213     element.deref();
    214 }
    215 
    216210void HTMLFormControlElement::didAttachRenderers()
    217211{
     
    224218    if (shouldAutofocus(this)) {
    225219        setAutofocused();
    226         ref();
    227         queuePostAttachCallback(focusPostAttach, *this);
     220
     221        RefPtr<HTMLFormControlElement> element = this;
     222        Style::queuePostResolutionCallback([element] {
     223            element->focus();
     224        });
    228225    }
    229226}
     
    288285}
    289286
    290 static void updateFromElementCallback(Node& node, unsigned)
    291 {
    292     if (auto renderer = toHTMLFormControlElement(node).renderer())
    293         renderer->updateFromElement();
    294 }
    295 
    296287void HTMLFormControlElement::didRecalcStyle(Style::Change)
    297288{
    298289    // updateFromElement() can cause the selection to change, and in turn
    299290    // trigger synchronous layout, so it must not be called during style recalc.
    300     if (renderer())
    301         queuePostAttachCallback(updateFromElementCallback, *this);
     291    if (renderer()) {
     292        RefPtr<HTMLFormControlElement> element = this;
     293        Style::queuePostResolutionCallback([element]{
     294            if (auto* renderer = element->renderer())
     295                renderer->updateFromElement();
     296        });
     297    }
    302298}
    303299
  • trunk/Source/WebCore/html/HTMLFrameOwnerElement.cpp

    r163440 r166144  
    122122}
    123123
    124 static void needsStyleRecalcCallback(Node& node, unsigned data)
    125 {
    126     node.setNeedsStyleRecalc(static_cast<StyleChangeType>(data));
    127 }
    128 
    129124void HTMLFrameOwnerElement::scheduleSetNeedsStyleRecalc(StyleChangeType changeType)
    130125{
    131     if (postAttachCallbacksAreSuspended())
    132         queuePostAttachCallback(needsStyleRecalcCallback, *this, static_cast<unsigned>(changeType));
    133     else
     126    if (Style::postResolutionCallbacksAreSuspended()) {
     127        RefPtr<HTMLFrameOwnerElement> element = this;
     128        Style::queuePostResolutionCallback([element, changeType]{
     129            element->setNeedsStyleRecalc(changeType);
     130        });
     131    } else
    134132        setNeedsStyleRecalc(changeType);
    135133}
  • trunk/Source/WebCore/html/HTMLObjectElement.cpp

    r165699 r166144  
    108108        formAttributeChanged();
    109109    else if (name == typeAttr) {
    110         m_serviceType = value.lower();
    111         size_t pos = m_serviceType.find(";");
    112         if (pos != notFound)
    113             m_serviceType = m_serviceType.left(pos);
    114         if (renderer())
    115             setNeedsWidgetUpdate(true);
     110        m_serviceType = value.string().left(value.find(';')).lower();
     111        setNeedsWidgetUpdate(true);
    116112    } else if (name == dataAttr) {
    117113        m_url = stripLeadingAndTrailingHTMLSpaces(value);
    118         document().updateStyleIfNeeded();
    119         if (renderer()) {
    120             setNeedsWidgetUpdate(true);
    121             if (isImageType()) {
    122                 if (!m_imageLoader)
    123                     m_imageLoader = adoptPtr(new HTMLImageLoader(*this));
    124                 m_imageLoader->updateFromElementIgnoringPreviousError();
    125             }
    126         }
    127     } else if (name == classidAttr) {
    128         m_classId = value;
    129         if (renderer())
    130             setNeedsWidgetUpdate(true);
    131     } else if (name == onbeforeloadAttr)
     114        setNeedsWidgetUpdate(true);
     115        updateImageLoaderWithNewURLSoon();
     116    } else if (name == classidAttr)
     117        setNeedsWidgetUpdate(true);
     118    else if (name == onbeforeloadAttr)
    132119        setAttributeEventListener(eventNames().beforeloadEvent, name, value);
    133120    else
     
    252239    // fallback content, which ensures the quirk will disable itself if Wiki
    253240    // Server is updated to generate an alternate embed tag as fallback content.
     241
    254242    if (!document().page()
    255243        || !document().page()->settings().needsSiteSpecificQuirks()
    256244        || hasFallbackContent()
    257         || !equalIgnoringCase(classId(), "clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"))
     245        || !equalIgnoringCase(fastGetAttribute(classidAttr), "clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"))
    258246        return false;
    259247
    260     RefPtr<NodeList> metaElements = document().getElementsByTagName(HTMLNames::metaTag.localName());
    261     unsigned length = metaElements->length();
    262     for (unsigned i = 0; i < length; ++i) {
    263         HTMLMetaElement& metaElement = toHTMLMetaElement(*metaElements->item(i));
     248    for (auto& metaElement : descendantsOfType<HTMLMetaElement>(document())) {
    264249        if (equalIgnoringCase(metaElement.name(), "generator") && metaElement.content().startsWith("Mac OS X Server Web Services Server", false))
    265250            return true;
    266251    }
    267    
     252
    268253    return false;
    269254}
     
    271256bool HTMLObjectElement::hasValidClassId()
    272257{
    273     if (MIMETypeRegistry::isJavaAppletMIMEType(serviceType()) && classId().startsWith("java:", false))
     258    if (MIMETypeRegistry::isJavaAppletMIMEType(serviceType()) && fastGetAttribute(classidAttr).startsWith("java:", false))
    274259        return true;
    275260   
     
    279264    // HTML5 says that fallback content should be rendered if a non-empty
    280265    // classid is specified for which the UA can't find a suitable plug-in.
    281     return classId().isEmpty();
     266    return fastGetAttribute(classidAttr).isEmpty();
    282267}
    283268
     
    376361
    377362    // Before we give up and use fallback content, check to see if this is a MIME type issue.
    378     if (m_imageLoader && m_imageLoader->image() && m_imageLoader->image()->status() != CachedResource::LoadError) {
    379         m_serviceType = m_imageLoader->image()->response().mimeType();
     363    auto* loader = imageLoader();
     364    if (loader && loader->image() && loader->image()->status() != CachedResource::LoadError) {
     365        m_serviceType = loader->image()->response().mimeType();
    380366        if (!isImageType()) {
    381367            // If we don't think we have an image type anymore, then clear the image from the loader.
    382             m_imageLoader->setImage(0);
     368            loader->setImage(nullptr);
    383369            return;
    384370        }
     
    387373    m_useFallbackContent = true;
    388374
    389     // This is here mainly to keep acid2 non-flaky. A style recalc is required to make fallback resources to load. Without forcing
    390     // this may happen after all the other resources have been loaded and the document is already considered complete.
    391     // FIXME: Disentangle fallback content handling from style recalcs.
     375    // This was added to keep Acid 2 non-flaky. A style recalc is required to make fallback resources load.
     376    // Without forcing, this may happen after all the other resources have been loaded and the document is already
     377    // considered complete. FIXME: Could address this with incrementLoadEventDelayCount instead, as we do with
     378    // image loading in HTMLPlugInImageElement, or disentangle loading from style entirely.
    392379    document().updateStyleIfNeeded();
    393380}
  • trunk/Source/WebCore/html/HTMLObjectElement.h

    r162180 r166144  
    3737
    3838    bool isDocNamedItem() const { return m_docNamedItem; }
    39 
    40     const String& classId() const { return m_classId; }
    41 
    4239    bool containsJavaApplet() const;
    4340
     41    bool hasFallbackContent() const;
    4442    virtual bool useFallbackContent() const override { return m_useFallbackContent; }
    4543    void renderFallbackContent();
    4644
    47     // Implementations of FormAssociatedElement
    48     HTMLFormElement* form() const { return FormAssociatedElement::form(); }
     45    // Implementation of constraint validation API.
     46    // Note that the object elements are always barred from constraint validation.
     47    static bool checkValidity() { return true; }
     48    virtual void setCustomValidity(const String&) override { }
     49    virtual String validationMessage() const override { return String(); }
    4950
    50     virtual bool isFormControlElement() const override { return false; }
     51    using HTMLPlugInImageElement::ref;
     52    using HTMLPlugInImageElement::deref;
    5153
    52     virtual bool isEnumeratable() const override { return true; }
    53     virtual bool appendFormData(FormDataList&, bool) override;
    54 
    55     // Implementations of constraint validation API.
    56     // Note that the object elements are always barred from constraint validation.
    57     virtual String validationMessage() const override { return String(); }
    58     bool checkValidity() { return true; }
    59     virtual void setCustomValidity(const String&) override { }
    60 
    61     using Node::ref;
    62     using Node::deref;
    63 
    64     virtual bool canContainRangeEndPoint() const override { return useFallbackContent(); }
    65 
    66     bool hasFallbackContent() const;
     54    using FormAssociatedElement::form;
    6755
    6856private:
     
    10593    virtual const HTMLObjectElement& asHTMLElement() const override final { return *this; }
    10694
    107     String m_classId;
     95    virtual bool isFormControlElement() const override { return false; }
     96
     97    virtual bool isEnumeratable() const override { return true; }
     98    virtual bool appendFormData(FormDataList&, bool) override;
     99
     100    virtual bool canContainRangeEndPoint() const override { return useFallbackContent(); }
     101
    108102    bool m_docNamedItem : 1;
    109103    bool m_useFallbackContent : 1;
  • trunk/Source/WebCore/html/HTMLPlugInImageElement.cpp

    r165607 r166144  
    11/*
    2  * Copyright (C) 2008, 2011, 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2011, 2012, 2014 Apple Inc. All rights reserved.
    33 *
    44 * This library is free software; you can redistribute it and/or
     
    112112    // the same codepath in this class.
    113113    , m_needsWidgetUpdate(!createdByParser)
     114    , m_needsImageReload(false)
    114115    , m_shouldPreferPlugInsForImages(preferPlugInsForImagesOption == ShouldPreferPlugInsForImages)
    115116    , m_needsDocumentActivationCallbacks(false)
     
    228229#if PLATFORM(IOS)
    229230    if (ShadowRoot* shadowRoot = this->shadowRoot()) {
    230         Element* shadowElement = toElement(shadowRoot->firstChild());
    231         if (shadowElement && shadowElement->shadowPseudoId() == "-apple-youtube-shadow-iframe")
     231        Node* shadowNode = shadowRoot->firstChild();
     232        if (shadowNode && shadowNode->isElementNode() && toElement(*shadowNode).shadowPseudoId() == "-apple-youtube-shadow-iframe")
    232233            return createRenderer<RenderBlockFlow>(*this, std::move(style));
    233234    }
    234235#endif
     236
    235237    return HTMLPlugInElement::createElementRenderer(std::move(style));
    236238}
     
    245247}
    246248
     249void HTMLPlugInImageElement::didRecalcStyle(Style::Change styleChange)
     250{
     251    scheduleUpdateForAfterStyleResolution();
     252
     253    HTMLPlugInElement::didRecalcStyle(styleChange);
     254}
     255
    247256void HTMLPlugInImageElement::didAttachRenderers()
    248257{
    249     if (!isImageType()) {
    250         queuePostAttachCallback(&HTMLPlugInImageElement::updateWidgetCallback, *this);
    251         return;
    252     }
    253     if (!renderer() || useFallbackContent())
    254         return;
    255 
    256     // Image load might complete synchronously and cause us to re-enter attach.
    257     queuePostAttachCallback(&HTMLPlugInImageElement::startLoadingImageCallback, *this);
     258    scheduleUpdateForAfterStyleResolution();
     259
     260    HTMLPlugInElement::didAttachRenderers();
    258261}
    259262
     
    262265    // FIXME: Because of the insanity that is HTMLPlugInImageElement::willRecalcStyle,
    263266    // we can end up detaching during an attach() call, before we even have a
    264     // renderer.  In that case, don't mark the widget for update.
     267    // renderer. In that case, don't mark the widget for update.
    265268    if (renderer() && !useFallbackContent()) {
    266269        // Update the widget the next time we attach (detaching destroys the plugin).
    267270        setNeedsWidgetUpdate(true);
    268271    }
     272
    269273    HTMLPlugInElement::willDetachRenderers();
    270274}
    271275
    272 void HTMLPlugInImageElement::updateWidgetIfNecessary()
    273 {
    274     document().updateStyleIfNeeded();
    275 
    276     if (!needsWidgetUpdate() || useFallbackContent() || isImageType())
    277         return;
    278 
    279     if (!renderEmbeddedObject() || renderEmbeddedObject()->isPluginUnavailable())
    280         return;
    281 
    282     updateWidget(CreateOnlyNonNetscapePlugins);
     276void HTMLPlugInImageElement::scheduleUpdateForAfterStyleResolution()
     277{
     278    if (m_needsImageReload || (renderer() && !useFallbackContent())) {
     279        RefPtr<HTMLPlugInImageElement> element = this;
     280        Style::queuePostResolutionCallback([element]{
     281            element->updateAfterStyleResolution();
     282        });
     283    }
     284}
     285
     286void HTMLPlugInImageElement::updateAfterStyleResolution()
     287{
     288    // Do this after style resolution, since the image or widget load might complete synchronously
     289    // and cause us to re-enter otherwise. Also, we can't really answer the question "do I have a renderer"
     290    // accurately until after style resolution.
     291
     292    if (renderer() && !useFallbackContent()) {
     293        if (isImageType()) {
     294            if (!m_imageLoader)
     295                m_imageLoader = std::make_unique<HTMLImageLoader>(*this);
     296            if (m_needsImageReload)
     297                m_imageLoader->updateFromElementIgnoringPreviousError();
     298            else
     299                m_imageLoader->updateFromElement();
     300        } else {
     301            if (m_needsWidgetUpdate && renderEmbeddedObject() && !renderEmbeddedObject()->isPluginUnavailable())
     302                updateWidget(CreateOnlyNonNetscapePlugins);
     303        }
     304    }
     305
     306    // Either we reloaded the image just now, or we had some reason not to.
     307    // Either way, clear the flag now, since we don't need to remember to try again.
     308    setNeedsImageReload(false);
    283309}
    284310
     
    294320}
    295321
     322void HTMLPlugInImageElement::removedFrom(ContainerNode& root)
     323{
     324    // Important to do this when removed from a document to remove the possibility
     325    // we might delay the document's load event indefinitely.
     326    setNeedsImageReload(false);
     327
     328    HTMLPlugInElement::removedFrom(root);
     329}
     330
    296331void HTMLPlugInImageElement::didMoveToNewDocument(Document* oldDocument)
    297332{
    298333    if (m_needsDocumentActivationCallbacks) {
    299         if (oldDocument)
    300             oldDocument->unregisterForPageCacheSuspensionCallbacks(this);
     334        oldDocument->unregisterForPageCacheSuspensionCallbacks(this);
    301335        document().registerForPageCacheSuspensionCallbacks(this);
    302336    }
     
    304338    if (m_imageLoader)
    305339        m_imageLoader->elementDidMoveToNewDocument();
     340
    306341    HTMLPlugInElement::didMoveToNewDocument(oldDocument);
    307342}
     
    320355
    321356    HTMLPlugInElement::documentDidResumeFromPageCache();
    322 }
    323 
    324 void HTMLPlugInImageElement::updateWidgetCallback(Node& node, unsigned)
    325 {
    326     toHTMLPlugInImageElement(node).updateWidgetIfNecessary();
    327 }
    328 
    329 void HTMLPlugInImageElement::startLoadingImage()
    330 {
    331     if (!m_imageLoader)
    332         m_imageLoader = adoptPtr(new HTMLImageLoader(*this));
    333     m_imageLoader->updateFromElement();
    334 }
    335 
    336 void HTMLPlugInImageElement::startLoadingImageCallback(Node& node, unsigned)
    337 {
    338     toHTMLPlugInImageElement(node).startLoadingImage();
    339357}
    340358
     
    438456    root.appendChild(shadowElement, ASSERT_NO_EXCEPTION);
    439457
    440     RefPtr<HTMLIFrameElement> iframeElement = HTMLIFrameElement::create(HTMLNames::iframeTag, document());
    441     if (hasAttribute(HTMLNames::widthAttr))
    442         iframeElement->setAttribute(HTMLNames::widthAttr, AtomicString("100%", AtomicString::ConstructFromLiteral));
    443     if (hasAttribute(HTMLNames::heightAttr)) {
    444         iframeElement->setAttribute(HTMLNames::styleAttr, AtomicString("max-height: 100%", AtomicString::ConstructFromLiteral));
    445         iframeElement->setAttribute(HTMLNames::heightAttr, getAttribute(HTMLNames::heightAttr));
    446     }
    447     iframeElement->setAttribute(HTMLNames::srcAttr, src);
    448     iframeElement->setAttribute(HTMLNames::frameborderAttr, AtomicString("0", AtomicString::ConstructFromLiteral));
     458    RefPtr<HTMLIFrameElement> iframeElement = HTMLIFrameElement::create(iframeTag, document());
     459    if (hasAttribute(widthAttr))
     460        iframeElement->setAttribute(widthAttr, AtomicString("100%", AtomicString::ConstructFromLiteral));
     461    if (hasAttribute(heightAttr)) {
     462        iframeElement->setAttribute(styleAttr, AtomicString("max-height: 100%", AtomicString::ConstructFromLiteral));
     463        iframeElement->setAttribute(heightAttr, getAttribute(heightAttr));
     464    }
     465    iframeElement->setAttribute(srcAttr, src);
     466    iframeElement->setAttribute(frameborderAttr, AtomicString("0", AtomicString::ConstructFromLiteral));
    449467
    450468    // Disable frame flattening for this iframe.
    451     iframeElement->setAttribute(HTMLNames::scrollingAttr, AtomicString("no", AtomicString::ConstructFromLiteral));
     469    iframeElement->setAttribute(scrollingAttr, AtomicString("no", AtomicString::ConstructFromLiteral));
    452470    shadowElement->appendChild(iframeElement, ASSERT_NO_EXCEPTION);
    453471}
     
    611629}
    612630
     631static inline bool is100Percent(Length length)
     632{
     633    return length.isPercent() && length.percent() == 100;
     634}
     635
    613636void HTMLPlugInImageElement::subframeLoaderWillCreatePlugIn(const URL& url)
    614637{
     
    695718    }
    696719
    697     RenderBox* renderEmbeddedObject = toRenderBox(renderer());
    698     Length styleWidth = renderEmbeddedObject->style().width();
    699     Length styleHeight = renderEmbeddedObject->style().height();
    700     LayoutRect contentBoxRect = renderEmbeddedObject->contentBoxRect();
    701     int contentWidth = contentBoxRect.width();
    702     int contentHeight = contentBoxRect.height();
    703     int contentArea = contentWidth * contentHeight;
    704     IntSize visibleViewSize = document().frame()->view()->visibleSize();
    705     int visibleArea = visibleViewSize.width() * visibleViewSize.height();
    706 
    707     if (inMainFrame && styleWidth.isPercent() && (styleWidth.percent() == 100)
    708         && styleHeight.isPercent() && (styleHeight.percent() == 100)
    709         && (static_cast<float>(contentArea) / visibleArea > sizingFullPageAreaRatioThreshold)) {
    710         LOG(Plugins, "%p Plug-in is top level full page, set to play", this);
    711         m_snapshotDecision = NeverSnapshot;
    712         return;
     720    auto& renderer = toRenderEmbeddedObject(*this->renderer());
     721    LayoutRect contentRect = renderer.contentBoxRect();
     722    int contentWidth = contentRect.width();
     723    int contentHeight = contentRect.height();
     724
     725    if (inMainFrame) {
     726        auto& style = renderer.style();
     727        bool isFullPage = is100Percent(style.width()) && is100Percent(style.height());
     728        IntSize visibleViewSize = document().frame()->view()->visibleSize();
     729        float contentArea = contentWidth * contentHeight;
     730        float visibleArea = visibleViewSize.width() * visibleViewSize.height();
     731        if (isFullPage && contentArea > visibleArea * sizingFullPageAreaRatioThreshold) {
     732            LOG(Plugins, "%p Plug-in is top level full page, set to play", this);
     733            m_snapshotDecision = NeverSnapshot;
     734            return;
     735        }
    713736    }
    714737
    715738    if (contentWidth <= sizingTinyDimensionThreshold || contentHeight <= sizingTinyDimensionThreshold) {
    716739        LOG(Plugins, "%p Plug-in is very small %dx%d, set to play", this, contentWidth, contentHeight);
    717         m_sizeWhenSnapshotted = IntSize(contentBoxRect.width().toInt(), contentBoxRect.height().toInt());
     740        m_sizeWhenSnapshotted = IntSize(contentWidth, contentHeight);
    718741        m_snapshotDecision = MaySnapshotWhenResized;
    719742        return;
     
    727750    }
    728751
    729     LOG(Plugins, "%p Plug-in from (%s, %s) is not auto-start, sized at %dx%d, set to wait for snapshot", this, document().page()->mainFrame().document()->baseURL().host().utf8().data(), url.host().utf8().data(), contentWidth, contentHeight);
     752    LOG(Plugins, "%p Plug-in from (%s, %s) is not auto-start, sized at %dx%d, set to wait for snapshot", this, document().topDocument().baseURL().host().utf8().data(), url.host().utf8().data(), contentWidth, contentHeight);
    730753    m_snapshotDecision = Snapshotted;
    731754    setDisplayState(WaitingForSnapshot);
     
    775798}
    776799
     800void HTMLPlugInImageElement::setNeedsImageReload(bool needsImageReload)
     801{
     802    if (m_needsImageReload == needsImageReload)
     803        return;
     804
     805    m_needsImageReload = needsImageReload;
     806
     807    if (!needsImageReload)
     808        document().decrementLoadEventDelayCount();
     809    else {
     810        // Called when a URL is set, triggering a new load.
     811        // The actual load won't start until we recalculate style, which will tell us whether to load.
     812        document().incrementLoadEventDelayCount();
     813        setNeedsStyleRecalc(SyntheticStyleChange);
     814    }
     815}
     816
    777817} // namespace WebCore
  • trunk/Source/WebCore/html/HTMLPlugInImageElement.h

    r163082 r166144  
    11/*
    2  * Copyright (C) 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2009, 2011, 2012, 2014 Apple Inc. All rights reserved.
    33 *
    44 * This library is free software; you can redistribute it and/or
     
    2424#include "HTMLPlugInElement.h"
    2525
    26 #include "RenderStyle.h"
    27 #include <wtf/OwnPtr.h>
    28 
    2926namespace WebCore {
    3027
    3128class HTMLImageLoader;
    32 class HTMLVideoElement;
    3329class FrameLoader;
    3430class Image;
    3531class MouseEvent;
     32class RenderStyle;
    3633class Widget;
    3734
     
    4138};
    4239
    43 enum PreferPlugInsForImagesOption {
    44     ShouldPreferPlugInsForImages,
    45     ShouldNotPreferPlugInsForImages
    46 };
    47 
    48 // Base class for HTMLObjectElement and HTMLEmbedElement
     40// Base class for HTMLAppletElement, HTMLEmbedElement, and HTMLObjectElement.
     41// FIXME: Should HTMLAppletElement inherit from HTMLPlugInElement directly instead?
    4942class HTMLPlugInImageElement : public HTMLPlugInElement {
    5043public:
     
    10598
    10699protected:
     100    enum PreferPlugInsForImagesOption { ShouldPreferPlugInsForImages, ShouldNotPreferPlugInsForImages };
    107101    HTMLPlugInImageElement(const QualifiedName& tagName, Document&, bool createdByParser, PreferPlugInsForImagesOption);
    108102
     103    virtual void removedFrom(ContainerNode&) override;
     104    virtual void didMoveToNewDocument(Document* oldDocument) override;
     105    virtual bool requestObject(const String& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues) override final;
     106
    109107    bool isImageType();
    110 
    111     OwnPtr<HTMLImageLoader> m_imageLoader;
    112     String m_serviceType;
    113     String m_url;
    114     URL m_loadedUrl;
    115 
    116     static void updateWidgetCallback(Node&, unsigned);
    117     static void startLoadingImageCallback(Node&, unsigned);
    118 
    119     virtual void didAttachRenderers() override;
    120     virtual void willDetachRenderers() override;
     108    HTMLImageLoader* imageLoader() { return m_imageLoader.get(); }
     109    void updateImageLoaderWithNewURLSoon() { setNeedsImageReload(true); }
    121110
    122111    bool allowedToLoadFrameURL(const String& url);
    123112    bool wouldLoadAsNetscapePlugin(const String& url, const String& serviceType);
    124113
    125     virtual void didMoveToNewDocument(Document* oldDocument) override;
    126 
    127     virtual void documentWillSuspendForPageCache() override;
    128     virtual void documentDidResumeFromPageCache() override;
    129 
    130     virtual bool isRestartedPlugin() const override { return m_isRestartedPlugin; }
    131     virtual bool requestObject(const String& url, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues) override;
     114    String m_serviceType;
     115    String m_url;
    132116
    133117private:
     118    virtual bool isPlugInImageElement() const override final { return true; }
     119    virtual bool isRestartedPlugin() const override final { return m_isRestartedPlugin; }
     120
     121    virtual void finishParsingChildren() override final;
     122    virtual void didAddUserAgentShadowRoot(ShadowRoot*) override final;
     123
    134124    virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override;
    135     virtual bool willRecalcStyle(Style::Change) override;
     125    virtual bool willRecalcStyle(Style::Change) override final;
     126    virtual void didRecalcStyle(Style::Change styleChange) override final;
     127    virtual void didAttachRenderers() override final;
     128    virtual void willDetachRenderers() override final;
    136129
    137     virtual void didAddUserAgentShadowRoot(ShadowRoot*) override;
     130    virtual void documentWillSuspendForPageCache() override final;
     131    virtual void documentDidResumeFromPageCache() override final;
    138132
    139     virtual void finishParsingChildren() override;
     133    virtual void defaultEventHandler(Event*) override final;
     134    virtual void dispatchPendingMouseClick() override final;
    140135
    141     void updateWidgetIfNecessary();
    142     void startLoadingImage();
     136    virtual void updateSnapshot(PassRefPtr<Image>) override final;
    143137
    144     virtual void updateSnapshot(PassRefPtr<Image>) override;
    145     virtual void dispatchPendingMouseClick() override;
     138    void setNeedsImageReload(bool);
     139    void scheduleUpdateForAfterStyleResolution();
     140    void updateAfterStyleResolution();
     141
    146142    void simulatedMouseClickTimerFired(DeferrableOneShotTimer<HTMLPlugInImageElement>&);
    147143
    148144    void restartSimilarPlugIns();
    149 
    150     virtual bool isPlugInImageElement() const override { return true; }
    151 
    152145    void removeSnapshotTimerFired(Timer<HTMLPlugInImageElement>&);
    153146
    154     virtual void defaultEventHandler(Event*) override;
    155 
     147    std::unique_ptr<HTMLImageLoader> m_imageLoader;
     148    URL m_loadedUrl;
    156149    bool m_needsWidgetUpdate;
     150    bool m_needsImageReload;
    157151    bool m_shouldPreferPlugInsForImages;
    158152    bool m_needsDocumentActivationCallbacks;
  • trunk/Source/WebCore/style/StyleResolveTree.cpp

    r165542 r166144  
    3030#include "AnimationController.h"
    3131#include "CSSFontSelector.h"
    32 #include "Element.h"
    3332#include "ElementIterator.h"
    3433#include "ElementRareData.h"
    3534#include "FlowThreadController.h"
    3635#include "InsertionPoint.h"
     36#include "LoaderStrategy.h"
    3737#include "NodeRenderStyle.h"
    3838#include "NodeRenderingTraversal.h"
    3939#include "NodeTraversal.h"
    40 #include "RenderElement.h"
     40#include "PlatformStrategies.h"
    4141#include "RenderFullScreen.h"
    4242#include "RenderNamedFlowThread.h"
     
    4444#include "RenderView.h"
    4545#include "RenderWidget.h"
     46#include "ResourceLoadScheduler.h"
    4647#include "Settings.h"
    4748#include "ShadowRoot.h"
     
    505506}
    506507
    507 static bool needsPseudeElement(Element& current, PseudoId pseudoId)
     508static bool needsPseudoElement(Element& current, PseudoId pseudoId)
    508509{
    509510    if (!current.document().styleSheetCollection().usesBeforeAfterRules())
     
    520521static void attachBeforeOrAfterPseudoElementIfNeeded(Element& current, PseudoId pseudoId)
    521522{
    522     if (!needsPseudeElement(current, pseudoId))
     523    if (!needsPseudoElement(current, pseudoId))
    523524        return;
    524525    RefPtr<PseudoElement> pseudoElement = PseudoElement::create(current, pseudoId);
     
    529530static void attachRenderTree(Element& current, ContainerNode& renderingParentNode, PassRefPtr<RenderStyle> resolvedStyle)
    530531{
    531     PostAttachCallbackDisabler callbackDisabler(current.document());
     532    PostResolutionCallbackDisabler callbackDisabler(current.document());
    532533    WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
    533534
     
    742743{
    743744    if (PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId)) {
    744         if (needsPseudeElement(current, pseudoId))
     745        if (needsPseudoElement(current, pseudoId))
    745746            resolveTree(*existingPseudoElement, current, current.needsStyleRecalc() ? Force : change);
    746747        else
     
    905906}
    906907
    907 }
    908 }
     908static Vector<std::function<void ()>>& postResolutionCallbackQueue()
     909{
     910    static NeverDestroyed<Vector<std::function<void ()>>> vector;
     911    return vector;
     912}
     913
     914void queuePostResolutionCallback(std::function<void ()> callback)
     915{
     916    postResolutionCallbackQueue().append(callback);
     917}
     918
     919static void suspendMemoryCacheClientCalls(Document& document)
     920{
     921    Page* page = document.page();
     922    if (!page || !page->areMemoryCacheClientCallsEnabled())
     923        return;
     924
     925    page->setMemoryCacheClientCallsEnabled(false);
     926
     927    RefPtr<Document> protectedDocument = &document;
     928    postResolutionCallbackQueue().append([protectedDocument]{
     929        // FIXME: If the document becomes unassociated with the page during style resolution
     930        // then this won't work and the memory cache client calls will be permanently disabled.
     931        if (Page* page = protectedDocument->page())
     932            page->setMemoryCacheClientCallsEnabled(true);
     933    });
     934}
     935
     936static unsigned resolutionNestingDepth;
     937
     938PostResolutionCallbackDisabler::PostResolutionCallbackDisabler(Document& document)
     939{
     940    ++resolutionNestingDepth;
     941
     942    if (resolutionNestingDepth == 1)
     943        platformStrategies()->loaderStrategy()->resourceLoadScheduler()->suspendPendingRequests();
     944
     945    // FIXME: It's strange to build this into the disabler.
     946    suspendMemoryCacheClientCalls(document);
     947}
     948
     949PostResolutionCallbackDisabler::~PostResolutionCallbackDisabler()
     950{
     951    if (resolutionNestingDepth == 1) {
     952        // Get size each time through the loop because a callback can add more callbacks to the end of the queue.
     953        auto& queue = postResolutionCallbackQueue();
     954        for (size_t i = 0; i < queue.size(); ++i)
     955            queue[i]();
     956        queue.clear();
     957
     958        platformStrategies()->loaderStrategy()->resourceLoadScheduler()->resumePendingRequests();
     959    }
     960
     961    --resolutionNestingDepth;
     962}
     963
     964bool postResolutionCallbacksAreSuspended()
     965{
     966    return resolutionNestingDepth;
     967}
     968
     969}
     970}
  • trunk/Source/WebCore/style/StyleResolveTree.h

    r162726 r166144  
    2727#define StyleResolveTree_h
    2828
     29#include <functional>
     30
    2931namespace WebCore {
    3032
     
    4850Change determineChange(const RenderStyle*, const RenderStyle*);
    4951
     52void queuePostResolutionCallback(std::function<void ()>);
     53bool postResolutionCallbacksAreSuspended();
     54
     55class PostResolutionCallbackDisabler {
     56public:
     57    explicit PostResolutionCallbackDisabler(Document&);
     58    ~PostResolutionCallbackDisabler();
     59};
     60
    5061}
    5162
  • trunk/Source/WebKit/mac/ChangeLog

    r166117 r166144  
     12014-03-23  Darin Adler  <darin@apple.com>
     2
     3        Remove code in HTMLObjectElement attribute parsing that forces style resolution and layout
     4        https://bugs.webkit.org/show_bug.cgi?id=130653
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * WebCoreSupport/WebFrameLoaderClient.mm: Call toHTMLPlugInImageElement instead of
     9        doing a static_cast.
     10
    1112014-03-21  Simon Fraser  <simon.fraser@apple.com>
    212
  • trunk/Source/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm

    r165979 r166144  
    21072107                    if (element->hasTagName(HTMLNames::embedTag) || element->hasTagName(HTMLNames::objectTag)) {
    21082108                        // Create a shadow subtree for the plugin element, the iframe player is injected in the shadow tree.
    2109                         HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(element);
    2110                         pluginElement->createShadowIFrameSubtree(embedSrc);
     2109                        toHTMLPlugInImageElement(*element).createShadowIFrameSubtree(embedSrc);
    21112110                        return nullptr;
    21122111                    }
Note: See TracChangeset for help on using the changeset viewer.