Source/WebCore/ChangeLog

 12020-09-09 Rob Buis <rbuis@igalia.com>
 2
 3 Implement lazy iframe loading
 4 https://bugs.webkit.org/show_bug.cgi?id=215442
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Implement lazy iframe loading as specified [1, 2]. Lazy iframe loading
 9 is controlled by the loading attribute on <iframe>. When the loading attribute is
 10 not specified, the behavior is like before this patch, i.e. loading is eager.
 11
 12 This changes the way iframe attribute processing is handled as specified here [2].
 13
 14 This implementation relies on Intersection Observer and hence works on WK2 only.
 15
 16 [1] https://html.spec.whatwg.org/#attr-iframe-loading
 17 [2] https://html.spec.whatwg.org/#process-the-iframe-attributes
 18
 19 Tests: imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-base-url-2.tentative.html
 20 imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-base-url.tentative.html
 21 imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-load-event.tentative.html
 22 imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-multiple-times.tentative.html
 23 imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-referrerpolicy-change.sub.tentative.html
 24 imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-to-eager.tentative.html
 25
 26 * Sources.txt:
 27 * WebCore.xcodeproj/project.pbxproj:
 28 * html/HTMLFrameElementBase.cpp:
 29 (WebCore::HTMLFrameElementBase::canLoad const):
 30 (WebCore::HTMLFrameElementBase::openURL):
 31 (WebCore::HTMLFrameElementBase::setLocation):
 32 * html/HTMLFrameElementBase.h:
 33 * html/HTMLFrameOwnerElement.h:
 34 (WebCore::HTMLFrameOwnerElement::lazyLoadFrame):
 35 (WebCore::HTMLFrameOwnerElement::lazyLoadObserverActive const):
 36 * html/HTMLIFrameElement.cpp:
 37 (WebCore::HTMLIFrameElement::parseAttribute):
 38 (WebCore::HTMLIFrameElement::referrerPolicy const):
 39 (WebCore::HTMLIFrameElement::loadingForBindings const):
 40 (WebCore::HTMLIFrameElement::setLoadingForBindings):
 41 (WebCore::isFrameLazyLoadable):
 42 (WebCore::HTMLIFrameElement::lazyLoadFrame):
 43 (WebCore::HTMLIFrameElement::lazyLoadObserverActive const):
 44 (WebCore::HTMLIFrameElement::loadDeferredFrame):
 45 (WebCore::HTMLIFrameElement::lazyLoadFrameObserver):
 46 * html/HTMLIFrameElement.h:
 47 * html/HTMLIFrameElement.idl:
 48 * html/LazyLoadFrameObserver.cpp: Added.
 49 (WebCore::LazyLoadFrameObserver::LazyLoadFrameObserver):
 50 (WebCore::LazyLoadFrameObserver::observe):
 51 (WebCore::LazyLoadFrameObserver::unobserve):
 52 (WebCore::LazyLoadFrameObserver::intersectionObserver):
 53 (WebCore::LazyLoadFrameObserver::isObserved const):
 54 * html/LazyLoadFrameObserver.h: Added.
 55 (WebCore::LazyLoadFrameObserver::url const):
 56 (WebCore::LazyLoadFrameObserver::referrerPolicy const):
 57 (WebCore::LazyLoadFrameObserver::create):
 58 * html/shadow/DateTimeFieldElement.cpp:
 59 * loader/FrameLoader.cpp:
 60 (WebCore::FrameLoader::allChildrenAreComplete const):
 61
1622020-09-08 Ryosuke Niwa <rniwa@webkit.org>
263
364 Having an iframe as a descendent node shouldn't require ElementRareData

Source/WebCore/Sources.txt

@@html/InputType.cpp
11921192html/InputTypeNames.cpp
11931193html/LabelableElement.cpp
11941194html/LabelsNodeList.cpp
 1195html/LazyLoadFrameObserver.cpp
11951196html/LazyLoadImageObserver.cpp
11961197html/LinkIconCollector.cpp
11971198html/LinkRelAttribute.cpp

Source/WebCore/WebCore.xcodeproj/project.pbxproj

78687868 4415292C0E1AE8A000C4A2D0 /* HTMLPlugInImageElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLPlugInImageElement.h; sourceTree = "<group>"; };
78697869 4415292D0E1AE8A000C4A2D0 /* HTMLPlugInImageElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLPlugInImageElement.cpp; sourceTree = "<group>"; };
78707870 442956CA218A6D300080DB54 /* DictionaryLookupLegacy.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DictionaryLookupLegacy.mm; sourceTree = "<group>"; };
 7871 4437C4A724E2AE5F00095128 /* LazyLoadFrameObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LazyLoadFrameObserver.h; sourceTree = "<group>"; };
 7872 4437C4A924E2AE5F00095128 /* LazyLoadFrameObserver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LazyLoadFrameObserver.cpp; sourceTree = "<group>"; };
78717873 443F04260E75C8FB007E5407 /* NetworkStateNotifierIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkStateNotifierIOS.mm; sourceTree = "<group>"; };
78727874 444D4E210F708B2E003158E0 /* WebCoreURLResponseIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreURLResponseIOS.mm; sourceTree = "<group>"; };
78737875 445775E420472F73008DCE5D /* LocalDefaultSystemAppearance.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalDefaultSystemAppearance.h; sourceTree = "<group>"; };

2299122993 450CEBEF15073BBE002BB149 /* LabelableElement.h */,
2299222994 A456FA2411AD4A830020B420 /* LabelsNodeList.cpp */,
2299322995 A456FA2511AD4A830020B420 /* LabelsNodeList.h */,
 22996 4437C4A924E2AE5F00095128 /* LazyLoadFrameObserver.cpp */,
 22997 4437C4A724E2AE5F00095128 /* LazyLoadFrameObserver.h */,
2299422998 AAD9D0B121DFA80C001B11C7 /* LazyLoadImageObserver.cpp */,
2299522999 AAD9D0B321DFA80E001B11C7 /* LazyLoadImageObserver.h */,
2299623000 1A4DA41F1CDD3A8300F4473C /* LinkIconCollector.cpp */,

Source/WebCore/html/HTMLFrameElementBase.cpp

@@bool HTMLFrameElementBase::canLoadScriptURL(const URL& scriptURL) const
5959
6060bool HTMLFrameElementBase::canLoad() const
6161{
62  // FIXME: Why is it valuable to return true when m_URL is empty?
 62 // FIXME: Why is it valuable to return true when m_url is empty?
6363 // FIXME: After openURL replaces an empty URL with the blank URL, this may no longer necessarily return true.
64  return m_URL.isEmpty() || canLoadURL(m_URL);
 64 return m_url.isEmpty() || canLoadURL(m_url);
6565}
6666
6767bool HTMLFrameElementBase::canLoadURL(const String& relativeURL) const

@@void HTMLFrameElementBase::openURL(LockHistory lockHistory, LockBackForwardList
8686 if (!canLoad())
8787 return;
8888
89  if (m_URL.isEmpty())
90  m_URL = aboutBlankURL().string();
 89 if (m_url.isEmpty())
 90 m_url = aboutBlankURL().string();
 91
 92 if (lazyLoadFrame())
 93 return;
9194
9295 RefPtr<Frame> parentFrame = document().frame();
9396 if (!parentFrame)
9497 return;
9598
96  document().willLoadFrameElement(document().completeURL(m_URL));
 99 document().willLoadFrameElement(document().completeURL(m_url));
97100
98101 String frameName = getNameAttribute();
99102 if (frameName.isNull() && UNLIKELY(document().settings().needsFrameNameFallbackToIdQuirk()))
100103 frameName = getIdAttribute();
101104
102  parentFrame->loader().subframeLoader().requestFrame(*this, m_URL, frameName, lockHistory, lockBackForwardList);
 105 parentFrame->loader().subframeLoader().requestFrame(*this, m_url, frameName, lockHistory, lockBackForwardList);
103106}
104107
105108void HTMLFrameElementBase::parseAttribute(const QualifiedName& name, const AtomString& value)

@@URL HTMLFrameElementBase::location() const
159162
160163void HTMLFrameElementBase::setLocation(const String& str)
161164{
162  if (document().settings().needsAcrobatFrameReloadingQuirk() && m_URL == str)
 165 if (document().settings().needsAcrobatFrameReloadingQuirk() && m_url == str)
163166 return;
164167
165  m_URL = AtomString(str);
 168 m_url = AtomString(str);
166169
167170 if (isConnected())
168171 openURL(LockHistory::No, LockBackForwardList::No);

Source/WebCore/html/HTMLFrameElementBase.h

@@protected:
5454 void didFinishInsertingNode() final;
5555 void didAttachRenderers() override;
5656
 57 void openURL(LockHistory = LockHistory::Yes, LockBackForwardList = LockBackForwardList::Yes);
 58
 59 AtomString m_url;
 60
5761private:
5862 bool canLoadScriptURL(const URL&) const final;
5963

@@private:
6771
6872 bool isURLAttribute(const Attribute&) const final;
6973 bool isHTMLContentAttribute(const Attribute&) const final;
70 
71  void openURL(LockHistory = LockHistory::Yes, LockBackForwardList = LockBackForwardList::Yes);
72 
73  AtomString m_URL;
7474};
7575
7676} // namespace WebCore

Source/WebCore/html/HTMLFrameOwnerElement.h

@@public:
6262
6363 virtual ReferrerPolicy referrerPolicy() const { return ReferrerPolicy::EmptyString; }
6464
 65 virtual bool lazyLoadFrame() { return false; }
 66 virtual bool lazyLoadObserverActive() const { return false; }
 67
6568protected:
6669 HTMLFrameOwnerElement(const QualifiedName& tagName, Document&);
6770 void setSandboxFlags(SandboxFlags);

@@private:
7376
7477 Frame* m_contentFrame { nullptr };
7578 SandboxFlags m_sandboxFlags { SandboxNone };
 79
 80protected:
 81 bool m_lazyLoadObserverActive { false };
7682};
7783
7884class SubframeLoadingDisabler {

Source/WebCore/html/HTMLIFrameElement.cpp

2929#include "DOMTokenList.h"
3030#include "Frame.h"
3131#include "HTMLNames.h"
 32#include "LazyLoadFrameObserver.h"
3233#include "RenderIFrame.h"
3334#include "ScriptableDocumentParser.h"
3435#include "Settings.h"
3536#include <wtf/IsoMallocInlines.h>
 37#include <wtf/SetForScope.h>
3638
3739namespace WebCore {
3840

@@void HTMLIFrameElement::parseAttribute(const QualifiedName& name, const AtomStri
102104 setSandboxFlags(value.isNull() ? SandboxNone : SecurityContext::parseSandboxPolicy(value, invalidTokens));
103105 if (!invalidTokens.isNull())
104106 document().addConsoleMessage(MessageSource::Other, MessageLevel::Error, "Error while parsing the 'sandbox' attribute: " + invalidTokens);
105  } else if (name == allowAttr || name == allowfullscreenAttr || name == webkitallowfullscreenAttr)
 107 } else if (name == allowAttr || name == allowfullscreenAttr || name == webkitallowfullscreenAttr) {
106108 m_featurePolicy = WTF::nullopt;
107  else
 109 } else if (name == loadingAttr) {
 110 if (m_lazyLoadFrameObserver && !equalLettersIgnoringASCIICase(value, "lazy")) {
 111 m_lazyLoadFrameObserver->unobserve();
 112 loadDeferredFrame();
 113 }
 114 } else
108115 HTMLFrameElementBase::parseAttribute(name, value);
109116}
110117

@@String HTMLIFrameElement::referrerPolicyForBindings() const
130137
131138ReferrerPolicy HTMLIFrameElement::referrerPolicy() const
132139{
 140 if (m_lazyLoadFrameObserver)
 141 return m_lazyLoadFrameObserver->referrerPolicy();
133142 if (document().settings().referrerPolicyAttributeEnabled())
134143 return parseReferrerPolicy(attributeWithoutSynchronization(referrerpolicyAttr), ReferrerPolicySource::ReferrerPolicyAttribute).valueOr(ReferrerPolicy::EmptyString);
135144 return ReferrerPolicy::EmptyString;

@@const FeaturePolicy& HTMLIFrameElement::featurePolicy() const
142151 return *m_featurePolicy;
143152}
144153
 154const AtomString& HTMLIFrameElement::loadingForBindings() const
 155{
 156 static MainThreadNeverDestroyed<const AtomString> eager("eager", AtomString::ConstructFromLiteral);
 157 static MainThreadNeverDestroyed<const AtomString> lazy("lazy", AtomString::ConstructFromLiteral);
 158 auto& attributeValue = attributeWithoutSynchronization(HTMLNames::loadingAttr);
 159 return equalLettersIgnoringASCIICase(attributeValue, "lazy") ? lazy : eager;
 160}
 161
 162void HTMLIFrameElement::setLoadingForBindings(const AtomString& value)
 163{
 164 setAttributeWithoutSynchronization(loadingAttr, value);
 165}
 166
 167static bool isFrameLazyLoadable(const URL& url, const AtomString& attributeValue)
 168{
 169 if (!url.protocolIsInHTTPFamily())
 170 return false;
 171
 172 return equalLettersIgnoringASCIICase(attributeValue, "lazy");
 173}
 174
 175bool HTMLIFrameElement::lazyLoadFrame()
 176{
 177 if (!m_lazyLoadFrameObserver && document().settings().lazyIframeLoadingEnabled() && isFrameLazyLoadable(document().completeURL(m_url), attributeWithoutSynchronization(HTMLNames::loadingAttr))) {
 178 auto policy = referrerPolicy();
 179 lazyLoadFrameObserver().observe(document().completeURL(m_url).string(), policy);
 180 return true;
 181 }
 182 return false;
 183}
 184
 185bool HTMLIFrameElement::lazyLoadObserverActive() const
 186{
 187 return !!m_lazyLoadFrameObserver;
 188}
 189
 190void HTMLIFrameElement::loadDeferredFrame()
 191{
 192 SetForScope<AtomString> urlScope(m_url);
 193 m_url = m_lazyLoadFrameObserver->url();
 194 openURL();
 195 m_lazyLoadFrameObserver = nullptr;
 196}
 197
 198LazyLoadFrameObserver& HTMLIFrameElement::lazyLoadFrameObserver()
 199{
 200 if (!m_lazyLoadFrameObserver)
 201 m_lazyLoadFrameObserver = LazyLoadFrameObserver::create(*this);
 202 return *m_lazyLoadFrameObserver;
 203}
 204
145205}

Source/WebCore/html/HTMLIFrameElement.h

2929namespace WebCore {
3030
3131class DOMTokenList;
 32class LazyLoadFrameObserver;
3233class RenderIFrame;
3334
3435class HTMLIFrameElement final : public HTMLFrameElementBase {

@@public:
4647
4748 const FeaturePolicy& featurePolicy() const;
4849
 50 const AtomString& loadingForBindings() const;
 51 void setLoadingForBindings(const AtomString&);
 52
 53 LazyLoadFrameObserver& lazyLoadFrameObserver();
 54
 55 void loadDeferredFrame();
 56
4957private:
5058 HTMLIFrameElement(const QualifiedName&, Document&);
5159

@@private:
5967 bool rendererIsNeeded(const RenderStyle&) final;
6068 RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final;
6169
 70 bool lazyLoadFrame() final;
 71 bool lazyLoadObserverActive() const final;
 72
6273 std::unique_ptr<DOMTokenList> m_sandbox;
6374 mutable Optional<FeaturePolicy> m_featurePolicy;
 75 std::unique_ptr<LazyLoadFrameObserver> m_lazyLoadFrameObserver;
6476};
6577
6678} // namespace WebCore

Source/WebCore/html/HTMLIFrameElement.idl

@@interface HTMLIFrameElement : HTMLElement {
4343 [CheckSecurityForNode, MayThrowException] Document getSVGDocument();
4444
4545 [EnabledBySetting=ReferrerPolicyAttribute, ImplementedAs=referrerPolicyForBindings, CEReactions=NotNeeded] attribute DOMString referrerPolicy;
 46
 47 [CEReactions, EnabledBySetting=LazyIframeLoading, ImplementedAs=loadingForBindings] attribute DOMString loading;
4648};

Source/WebCore/html/LazyLoadFrameObserver.cpp

 1/*
 2 * Copyright (C) 2020 Igalia S.L.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "LazyLoadFrameObserver.h"
 28
 29#include "Frame.h"
 30#include "HTMLIFrameElement.h"
 31#include "IntersectionObserverCallback.h"
 32#include "RenderStyle.h"
 33
 34#include <limits>
 35
 36namespace WebCore {
 37
 38class LazyFrameLoadIntersectionObserverCallback final : public IntersectionObserverCallback {
 39public:
 40 static Ref<LazyFrameLoadIntersectionObserverCallback> create(Document& document)
 41 {
 42 return adoptRef(*new LazyFrameLoadIntersectionObserverCallback(document));
 43 }
 44
 45private:
 46 CallbackResult<void> handleEvent(IntersectionObserver&, const Vector<Ref<IntersectionObserverEntry>>& entries, IntersectionObserver&) final
 47 {
 48 ASSERT(!entries.isEmpty());
 49
 50 for (auto& entry : entries) {
 51 if (!entry->isIntersecting())
 52 continue;
 53 auto* element = entry->target();
 54 if (is<HTMLIFrameElement>(element)) {
 55 downcast<HTMLIFrameElement>(*element).lazyLoadFrameObserver().unobserve();
 56 downcast<HTMLIFrameElement>(*element).loadDeferredFrame();
 57 }
 58 }
 59 return { };
 60 }
 61
 62 LazyFrameLoadIntersectionObserverCallback(Document& document)
 63 : IntersectionObserverCallback(&document)
 64 {
 65 }
 66};
 67
 68LazyLoadFrameObserver::LazyLoadFrameObserver(HTMLIFrameElement& element)
 69 : m_element(element)
 70{
 71}
 72
 73void LazyLoadFrameObserver::observe(const AtomString& url, const ReferrerPolicy& referrerPolicy)
 74{
 75 auto& observer = m_element.lazyLoadFrameObserver();
 76 auto* intersectionObserver = observer.intersectionObserver(m_element.document());
 77 if (!intersectionObserver)
 78 return;
 79 m_url = url;
 80 m_referrerPolicy = referrerPolicy;
 81 intersectionObserver->observe(m_element);
 82}
 83
 84void LazyLoadFrameObserver::unobserve()
 85{
 86 auto& observer = m_element.lazyLoadFrameObserver();
 87 ASSERT(observer.isObserved(m_element));
 88 observer.m_lazyLoadIntersectionObserver->unobserve(m_element);
 89}
 90
 91IntersectionObserver* LazyLoadFrameObserver::intersectionObserver(Document& document)
 92{
 93 if (!m_lazyLoadIntersectionObserver) {
 94 auto callback = LazyFrameLoadIntersectionObserverCallback::create(document);
 95 IntersectionObserver::Init options { WTF::nullopt, emptyString(), { } };
 96 auto observer = IntersectionObserver::create(document, WTFMove(callback), WTFMove(options));
 97 if (observer.hasException())
 98 return nullptr;
 99 m_lazyLoadIntersectionObserver = observer.returnValue().ptr();
 100 }
 101 return m_lazyLoadIntersectionObserver.get();
 102}
 103
 104bool LazyLoadFrameObserver::isObserved(Element& element) const
 105{
 106 return m_lazyLoadIntersectionObserver && m_lazyLoadIntersectionObserver->observationTargets().contains(&element);
 107}
 108
 109}

Source/WebCore/html/LazyLoadFrameObserver.h

 1/*
 2 * Copyright (C) 2020 Igalia S.L.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#pragma once
 27
 28#include "IntersectionObserver.h"
 29
 30namespace WebCore {
 31
 32class Document;
 33class Element;
 34class HTMLIFrameElement;
 35
 36class LazyLoadFrameObserver {
 37 WTF_MAKE_FAST_ALLOCATED;
 38public:
 39 void observe(const AtomString& url, const ReferrerPolicy&);
 40 void unobserve();
 41
 42 AtomString url() const { return m_url; }
 43 ReferrerPolicy referrerPolicy() const { return m_referrerPolicy; }
 44
 45private:
 46 friend class HTMLIFrameElement;
 47
 48 static std::unique_ptr<LazyLoadFrameObserver> create(HTMLIFrameElement& element)
 49 {
 50 return std::unique_ptr<LazyLoadFrameObserver>(new LazyLoadFrameObserver(element));
 51 }
 52 LazyLoadFrameObserver(HTMLIFrameElement&);
 53
 54 IntersectionObserver* intersectionObserver(Document&);
 55 bool isObserved(Element&) const;
 56
 57 HTMLIFrameElement& m_element;
 58
 59 AtomString m_url;
 60
 61 ReferrerPolicy m_referrerPolicy;
 62
 63 // The intersection observer responsible for loading the image once it's near the viewport.
 64 RefPtr<IntersectionObserver> m_lazyLoadIntersectionObserver;
 65};
 66
 67} // namespace

Source/WebCore/html/shadow/DateTimeFieldElement.cpp

3636#include "LocalizedStrings.h"
3737#include "PlatformLocale.h"
3838#include "Text.h"
 39#include <wtf/IsoMallocInlines.h>
3940#include <wtf/text/WTFString.h>
4041
4142namespace WebCore {

Source/WebCore/loader/FrameLoader.cpp

@@void FrameLoader::subresourceLoadDone(LoadCompletionType type)
827827bool FrameLoader::allChildrenAreComplete() const
828828{
829829 for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling()) {
830  if (!child->loader().m_isComplete)
 830 if (!child->loader().m_isComplete && (!child->ownerElement() || !child->ownerElement()->lazyLoadObserverActive()))
831831 return false;
832832 }
833833 return true;

LayoutTests/ChangeLog

 12020-09-09 Rob Buis <rbuis@igalia.com>
 2
 3 Implement lazy iframe loading
 4 https://bugs.webkit.org/show_bug.cgi?id=215442
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Unskip iframe-loading-lazy-to-eager.tentative.html and
 9 disable lazy iframe loading tests for WK1.
 10
 11 * TestExpectations:
 12 * platform/mac-wk1/TestExpectations:
 13
1142020-09-08 Ryan Haddad <ryanhaddad@apple.com>
215
316 Unreviewed test gardening after r266761.

LayoutTests/imported/w3c/ChangeLog

 12020-09-09 Rob Buis <rbuis@igalia.com>
 2
 3 Implement lazy iframe loading
 4 https://bugs.webkit.org/show_bug.cgi?id=215442
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Update improved test result.
 9
 10 * web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-base-url-2.tentative-expected.txt:
 11 * web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-base-url.tentative-expected.txt:
 12 * web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-load-event.tentative-expected.txt:
 13 * web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-multiple-times.tentative-expected.txt:
 14 * web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-referrerpolicy-change.sub.tentative-expected.txt:
 15 * web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-to-eager.tentative-expected.txt:
 16
1172020-09-08 Chris Dumez <cdumez@apple.com>
218
319 Unreviewed, rebaseline flaky webaudio WPT tests.

LayoutTests/TestExpectations

@@imported/w3c/web-platform-tests/html/browsers/windows/targeting-cross-origin-nes
568568imported/w3c/web-platform-tests/html/cross-origin-embedder-policy/reporting-to-endpoint.https.html [ Failure Pass ]
569569imported/w3c/web-platform-tests/html/webappapis/update-rendering/child-document-raf-order.html [ Failure Pass ]
570570imported/w3c/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio-lazy.tentative.html [ Failure Pass ]
571 imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-to-eager.tentative.html [ Failure Pass ]
572571imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/image-loading-lazy-to-eager.html [ Failure Pass ]
573572imported/w3c/web-platform-tests/html/semantics/forms/autofocus/update-the-rendering.html [ Failure Pass ]
574573imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/muted-errors.sub.html [ Failure Pass ]

LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-base-url-2.tentative-expected.txt

11
22
3 FAIL When a loading=lazy iframe is loaded, it loads relative to the document's base URL computed at parse-time. assert_true: Below-viewport loading=lazy iframes do not block the window load event expected true got false
 3PASS When a loading=lazy iframe is loaded, it loads relative to the document's base URL computed at parse-time.
44

LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-base-url.tentative-expected.txt

11
22
3 FAIL When a loading=lazy iframe is loaded, it loads relative to the document's base URL computed at parse-time. assert_true: Below-viewport loading=lazy iframes do not block the window load event expected true got false
 3PASS When a loading=lazy iframe is loaded, it loads relative to the document's base URL computed at parse-time.
44

LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-load-event.tentative-expected.txt

11
22
3 FAIL In-viewport loading=lazy iframe does not block the load event assert_true: The visible iframe should not block the load event expected true got false
4 FAIL In-viewport loading=lazy visibility:hidden iframe does not block the load event assert_true: The hidden iframe should not block the load event expected true got false
 3PASS In-viewport loading=lazy iframe does not block the load event
 4PASS In-viewport loading=lazy visibility:hidden iframe does not block the load event
55

LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-multiple-times.tentative-expected.txt

11
22
3 FAIL Iframes with loading='lazy' can be lazy loaded multiple times assert_true: The loading=lazy below-viewport iframe should not block the window load event expected true got false
 3PASS Iframes with loading='lazy' can be lazy loaded multiple times
44

LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-to-eager.tentative-expected.txt

11
22
3 FAIL Below-viewport iframes with loading='lazy' load when set to loading='eager' or the `loading` attribute is removed assert_unreached: #iframe_1 should not load before the window load event Reached unreachable code
 3PASS Below-viewport iframes with loading='lazy' load when set to loading='eager' or the `loading` attribute is removed
44

LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy.tentative-expected.txt

33
44PASS In-viewport iframes load eagerly
55PASS In-viewport srcdoc iframes load eagerly
6 FAIL Below-viewport iframes load lazily assert_true: The window load event should have fired before the below-viewport iframe loads expected true got false
 6PASS Below-viewport iframes load lazily
77FAIL Below-viewport srcdoc iframes load lazily assert_true: The window load event should have fired before the below-viewport srcdoc iframe loads expected true got false
88

LayoutTests/platform/mac-wk1/TestExpectations

@@imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/
179179imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/not-rendered-image-loading-lazy.html [ Skip ]
180180imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/picture-loading-lazy.html [ Skip ]
181181imported/w3c/web-platform-tests/html/semantics/embedded-content/the-img-element/remove-element-and-scroll.html [ Skip ]
 182imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-base-url-2.tentative.html [ Skip ]
 183imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-base-url.tentative.html [ Skip ]
 184imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-load-event.tentative.html [ Skip ]
 185imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-multiple-times.tentative.html [ Skip ]
 186imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-referrerpolicy-change.sub.tentative.html [ Skip ]
 187imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-to-eager.tentative.html [ Skip ]
 188imported/w3c/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy.tentative.html [ Skip ]
182189
183190# testRunner.queueLoad() does not support loading data URLs in Mac WK1
184191http/tests/security/contentSecurityPolicy/navigate-self-to-data-url.html [ Skip ]