Changeset 194926 in webkit


Ignore:
Timestamp:
Jan 12, 2016 2:18:19 PM (8 years ago)
Author:
hyatt@apple.com
Message:

Avoid downloading the wrong image for <picture> elements.
https://bugs.webkit.org/show_bug.cgi?id=153027

Reviewed by Dean Jackson.

I was unable to write a reliable test for this feature (I welcome suggestions regarding
how this could be tested).

  • html/HTMLImageElement.cpp:

(WebCore::HTMLImageElement::HTMLImageElement):
(WebCore::HTMLImageElement::~HTMLImageElement):
(WebCore::HTMLImageElement::bestFitSourceFromPictureElement):
(WebCore::HTMLImageElement::insertedInto):
(WebCore::HTMLImageElement::removedFrom):
(WebCore::HTMLImageElement::pictureNode):
(WebCore::HTMLImageElement::setPictureNode):

  • html/HTMLImageElement.h:
  • html/parser/HTMLConstructionSite.cpp:

(WebCore::HTMLConstructionSite::createHTMLElement):

Images that are built underneath a <picture> element are now connected
to that picture element via a setPictureNode call from the parser. This
ensures that the correct <source> elements are examined before checking the image.

This connection between images and their picture owners is handled using a static
HashMap in HTMLImageElement. This connection is made both from the parser and from
DOM insertions, and the map is queried now instead of looking directly at the
image's parentNode().

Also note the change to pass the document element's computed style in for media
query evaluation. Just as with the preload scanner, the image's style can't be
used as it has not been determined yet.

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r194923 r194926  
     12016-01-12  Dave Hyatt  <hyatt@apple.com>
     2
     3        Avoid downloading the wrong image for <picture> elements.
     4        https://bugs.webkit.org/show_bug.cgi?id=153027
     5
     6        Reviewed by Dean Jackson.
     7
     8        I was unable to write a reliable test for this feature (I welcome suggestions regarding
     9        how this could be tested).
     10
     11        * html/HTMLImageElement.cpp:
     12        (WebCore::HTMLImageElement::HTMLImageElement):
     13        (WebCore::HTMLImageElement::~HTMLImageElement):
     14        (WebCore::HTMLImageElement::bestFitSourceFromPictureElement):
     15        (WebCore::HTMLImageElement::insertedInto):
     16        (WebCore::HTMLImageElement::removedFrom):
     17        (WebCore::HTMLImageElement::pictureNode):
     18        (WebCore::HTMLImageElement::setPictureNode):
     19        * html/HTMLImageElement.h:
     20        * html/parser/HTMLConstructionSite.cpp:
     21        (WebCore::HTMLConstructionSite::createHTMLElement):
     22
     23        Images that are built underneath a <picture> element are now connected
     24        to that picture element via a setPictureNode call from the parser. This
     25        ensures that the correct <source> elements are examined before checking the image.
     26
     27        This connection between images and their picture owners is handled using a static
     28        HashMap in HTMLImageElement. This connection is made both from the parser and from
     29        DOM insertions, and the map is queried now instead of looking directly at the
     30        image's parentNode().
     31
     32        Also note the change to pass the document element's computed style in for media
     33        query evaluation. Just as with the preload scanner, the image's style can't be
     34        used as it has not been determined yet.
     35
    1362016-01-12  Myles C. Maxfield  <mmaxfield@apple.com>
    237
  • trunk/Source/WebCore/html/HTMLImageElement.cpp

    r194617 r194926  
    5454using namespace HTMLNames;
    5555
     56typedef HashMap<const Node*, Node*> PictureOwnerMap;
     57static PictureOwnerMap* gPictureOwnerMap = nullptr;
     58
    5659HTMLImageElement::HTMLImageElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form)
    5760    : HTMLElement(tagName, document)
     
    8386    if (m_form)
    8487        m_form->removeImgElement(this);
     88    setPictureNode(nullptr);
    8589}
    8690
     
    141145ImageCandidate HTMLImageElement::bestFitSourceFromPictureElement()
    142146{
    143     auto* parent = parentNode();
    144     if (!is<HTMLPictureElement>(parent))
     147    auto* pictureOwner = pictureNode();
     148    if (!pictureOwner)
    145149        return { };
    146     auto* picture = downcast<HTMLPictureElement>(parent);
     150    auto* picture = downcast<HTMLPictureElement>(pictureOwner);
    147151    picture->clearViewportDependentResults();
    148152    document().removeViewportDependentPicture(*picture);
    149     for (Node* child = parent->firstChild(); child && child != this; child = child->nextSibling()) {
     153    for (Node* child = picture->firstChild(); child && child != this; child = child->nextSibling()) {
    150154        if (!is<HTMLSourceElement>(*child))
    151155            continue;
     
    164168                continue;
    165169        }
    166         MediaQueryEvaluator evaluator(document().printing() ? "print" : "screen", document().frame(), computedStyle());
     170        MediaQueryEvaluator evaluator(document().printing() ? "print" : "screen", document().frame(), document().documentElement()->computedStyle());
    167171        bool evaluation = evaluator.evalCheckingViewportDependentResults(source.mediaQuerySet(), picture->viewportDependentResults());
    168172        if (picture->hasViewportDependentResults())
     
    314318        document().addImageElementByLowercasedUsemap(*m_lowercasedUsemap.impl(), *this);
    315319
    316     if (is<HTMLPictureElement>(parentNode()))
     320    if (is<HTMLPictureElement>(parentNode())) {
     321        setPictureNode(parentNode());
    317322        selectImageSource();
     323    }
    318324
    319325    // If we have been inserted from a renderer-less document,
     
    332338    if (insertionPoint.inDocument() && !m_lowercasedUsemap.isNull())
    333339        document().removeImageElementByLowercasedUsemap(*m_lowercasedUsemap.impl(), *this);
    334 
     340   
     341    if (is<HTMLPictureElement>(parentNode()))
     342        setPictureNode(nullptr);
     343   
    335344    m_form = nullptr;
    336345    HTMLElement::removedFrom(insertionPoint);
    337346}
    338347
     348Node* HTMLImageElement::pictureNode() const
     349{
     350    if (!gPictureOwnerMap)
     351        return nullptr;
     352    return gPictureOwnerMap->get(this);
     353}
     354   
     355void HTMLImageElement::setPictureNode(Node* node)
     356{
     357    if (!node) {
     358        if (gPictureOwnerMap)
     359            gPictureOwnerMap->remove(this);
     360        return;
     361    }
     362   
     363    if (!gPictureOwnerMap)
     364        gPictureOwnerMap = new PictureOwnerMap();
     365    gPictureOwnerMap->add(this, node);
     366}
     367   
    339368int HTMLImageElement::width(bool ignorePendingStylesheets)
    340369{
  • trunk/Source/WebCore/html/HTMLImageElement.h

    r193840 r194926  
    8888
    8989    bool hasShadowControls() const { return m_experimentalImageMenuEnabled; }
     90   
     91    Node* pictureNode() const;
     92    void setPictureNode(Node*);
    9093
    9194protected:
     
    128131    HTMLFormElement* m_form;
    129132    HTMLFormElement* m_formSetByParser;
     133
    130134    CompositeOperator m_compositeOperator;
    131135    AtomicString m_bestFitImageURL;
  • trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp

    r194496 r194926  
    3737#include "HTMLFormElement.h"
    3838#include "HTMLHtmlElement.h"
     39#include "HTMLImageElement.h"
    3940#include "HTMLOptGroupElement.h"
    4041#include "HTMLOptionElement.h"
    4142#include "HTMLParserIdioms.h"
     43#include "HTMLPictureElement.h"
    4244#include "HTMLScriptElement.h"
    4345#include "HTMLTemplateElement.h"
     
    641643    bool insideTemplateElement = !ownerDocument.frame();
    642644    RefPtr<Element> element = HTMLElementFactory::createElement(tagName, ownerDocument, insideTemplateElement ? nullptr : form(), true);
     645   
     646    // FIXME: This is a hack to connect images to pictures before the image has
     647    // been inserted into the document. It can be removed once asynchronous image
     648    // loading is working.
     649    if (is<HTMLPictureElement>(currentNode()) && is<HTMLImageElement>(*element.get()))
     650        downcast<HTMLImageElement>(*element.get()).setPictureNode(&currentNode());
     651
    643652    setAttributes(element.get(), token, m_parserContentPolicy);
    644653    ASSERT(element->isHTMLElement());
Note: See TracChangeset for help on using the changeset viewer.