WebKit Bugzilla
Attachment 371951 Details for
Bug 196698
: Support lazy image and iframe loading (loading="lazy")
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-196698-20190612162304.patch (text/plain), 176.41 KB, created by
Rob Buis
on 2019-06-12 07:23:07 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Rob Buis
Created:
2019-06-12 07:23:07 PDT
Size:
176.41 KB
patch
obsolete
>Subversion Revision: 246348 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 4a275d05a3013ee7d97a8957a7b907ca116c7d3f..2bbf9924d1de9f608eb80321c69ef39b1a0d9cb6 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,96 @@ >+2019-06-12 Rob Buis <rbuis@igalia.com> >+ >+ Support lazy image and iframe loading (loading="lazy") >+ https://bugs.webkit.org/show_bug.cgi?id=196698 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Implement lazy image loading as specified here [1]. Lazy image loading >+ is controlled by the loading attribute and automatic for CSS >+ background images. When the loading attribute is auto or not >+ specified, the behavior is like before this patch, i.e. loading is >+ eager. >+ >+ [1] https://github.com/whatwg/html/pull/3752/files >+ >+ Tests: http/tests/lazyload/attribute.html >+ http/tests/lazyload/fixed-dimension.html >+ http/tests/lazyload/js-image.html >+ http/tests/lazyload/lazy.html >+ http/tests/lazyload/scroll.html >+ http/tests/lazyload/style-dimension.html >+ imported/w3c/web-platform-tests/loading/lazyload/attribute_off_image.tentative.html >+ imported/w3c/web-platform-tests/loading/lazyload/change_attribute_to_off_image.tentative.html >+ imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_auto_image.tentative.html >+ imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_invalid_image.tentative.html >+ imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_on_image.tentative.html >+ imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_unset_image.tentative.html >+ imported/w3c/web-platform-tests/loading/lazyload/window_load_event_occurs_with_below_viewport_image.tentative.html >+ >+ * Sources.txt: >+ * WebCore.xcodeproj/project.pbxproj: >+ * css/CSSImageValue.cpp: >+ (WebCore::CSSImageValue::loadImage): >+ * css/CSSImageValue.h: >+ * css/parser/CSSParser.cpp: >+ (WebCore::CSSParser::parseInlineStyleDeclaration): >+ * css/parser/CSSParser.h: >+ * css/parser/CSSParserImpl.cpp: >+ (WebCore::CSSParserImpl::parseInlineStyleDeclaration): >+ * css/parser/CSSParserImpl.h: >+ * dom/Document.cpp: >+ (WebCore::Document::ensureLazyLoadImageObserver): >+ * dom/Document.h: >+ * html/HTMLAttributeNames.in: >+ * html/HTMLImageElement.cpp: >+ (WebCore::HTMLImageElement::HTMLImageElement): >+ (WebCore::HTMLImageElement::create): >+ (WebCore::HTMLImageElement::createForJSConstructor): >+ (WebCore::HTMLImageElement::parseAttribute): >+ (WebCore::HTMLImageElement::loadDeferredImage): >+ (WebCore::HTMLImageElement::getAttributeLazyLoadDimensionType): >+ (WebCore::HTMLImageElement::getInlineStyleDimensionsType): >+ * html/HTMLImageElement.h: >+ (WebCore::HTMLImageElement::createdByParser const): >+ * html/HTMLImageElement.idl: >+ * html/HTMLTagNames.in: >+ * html/ImageDocument.cpp: >+ * html/LazyLoadImageObserver.cpp: Added. >+ (WebCore::LazyLoadImageObserver::startMonitoring): >+ (WebCore::LazyLoadImageObserver::stopMonitoring): >+ (WebCore::LazyLoadImageObserver::startMonitoringNearViewport): >+ * html/LazyLoadImageObserver.h: Copied from Tools/DumpRenderTree/TestOptions.h. >+ * html/parser/HTMLPreloadScanner.cpp: >+ (WebCore::TokenPreloadScanner::StartTagScanner::createPreloadRequest): >+ (WebCore::TokenPreloadScanner::StartTagScanner::processAttribute): >+ * html/parser/HTMLPreloadScanner.h: >+ * html/parser/HTMLResourcePreloader.cpp: >+ (WebCore::PreloadRequest::resourceRequest): >+ * html/parser/HTMLResourcePreloader.h: >+ (WebCore::PreloadRequest::setLazyloadImageEnabled): >+ * loader/ImageLoader.cpp: >+ (WebCore::isLazyLoadableImage): >+ (WebCore::isDimensionAbsoluteLarge): >+ (WebCore::ImageLoader::updateFromElement): >+ (WebCore::ImageLoader::notifyFinished): >+ (WebCore::ImageLoader::loadDeferredImage): >+ * loader/ImageLoader.h: >+ * page/RuntimeEnabledFeatures.h: >+ (WebCore::RuntimeEnabledFeatures::setLazyImageLoadingEnabled): >+ (WebCore::RuntimeEnabledFeatures::lazyImageLoadingEnabled const): >+ * page/Settings.yaml: >+ * rendering/style/RenderStyle.cpp: >+ (WebCore::RenderStyle::loadDeferredImages const): >+ * rendering/style/RenderStyle.h: >+ * rendering/style/StyleCachedImage.cpp: >+ (WebCore::StyleCachedImage::addClient): >+ (WebCore::StyleCachedImage::removeClient): >+ (WebCore::StyleCachedImage::loadDeferredImage): >+ * rendering/style/StyleCachedImage.h: >+ * rendering/style/StyleImage.h: >+ (WebCore::StyleImage::isLazyloadPossiblyDeferred const): >+ (WebCore::StyleImage::StyleImage): >+ > 2019-06-11 Wenson Hsieh <wenson_hsieh@apple.com> > > [iOS] Idempotent text autosizing needs to react properly to viewport changes >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 898da324a131510884bc00b5abc847d17e4d7838..7a6d311a42d010d795bbcc6cd2e9de79e7751f85 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,14 @@ >+2019-06-12 Rob Buis <rbuis@igalia.com> >+ >+ Support lazy image and iframe loading (loading="lazy") >+ https://bugs.webkit.org/show_bug.cgi?id=196698 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add LazyImageLoading preference. >+ >+ * Shared/WebPreferences.yaml: >+ > 2019-06-11 Wenson Hsieh <wenson_hsieh@apple.com> > > [iOS] Idempotent text autosizing needs to react properly to viewport changes >diff --git a/Source/WebKitLegacy/mac/ChangeLog b/Source/WebKitLegacy/mac/ChangeLog >index b95d7bb1be74a51602e9409f8c804a64fe29276b..3eed6a7c3170b59ad26e59d5009e24ac00ef367f 100644 >--- a/Source/WebKitLegacy/mac/ChangeLog >+++ b/Source/WebKitLegacy/mac/ChangeLog >@@ -1,3 +1,21 @@ >+2019-06-12 Rob Buis <rbuis@igalia.com> >+ >+ Support lazy image and iframe loading (loading="lazy") >+ https://bugs.webkit.org/show_bug.cgi?id=196698 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Set lazyImageLoading runtime flag is preference is set. >+ >+ * WebView/WebPreferenceKeysPrivate.h: >+ * WebView/WebPreferences.mm: >+ (+[WebPreferences initialize]): >+ (-[WebPreferences lazyImageLoadingEnabled]): >+ (-[WebPreferences setLazyImageLoadingEnabled:]): >+ * WebView/WebPreferencesPrivate.h: >+ * WebView/WebView.mm: >+ (-[WebView _preferencesChanged:]): >+ > 2019-06-10 Sam Weinig <weinig@apple.com> > > Remove Dashboard support >diff --git a/Source/WebKitLegacy/win/ChangeLog b/Source/WebKitLegacy/win/ChangeLog >index fa31067f6bcaaabd461039f72e87e5e73641efd8..183714ef2ecbd1575b20bb65802d5a11527bbf4c 100644 >--- a/Source/WebKitLegacy/win/ChangeLog >+++ b/Source/WebKitLegacy/win/ChangeLog >@@ -1,3 +1,22 @@ >+2019-06-12 Rob Buis <rbuis@igalia.com> >+ >+ Support lazy image and iframe loading (loading="lazy") >+ https://bugs.webkit.org/show_bug.cgi?id=196698 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Set lazyImageLoading runtime flag is preference is set. >+ >+ * Interfaces/IWebPreferencesPrivate.idl: >+ * WebPreferenceKeysPrivate.h: >+ * WebPreferences.cpp: >+ (WebPreferences::initializeDefaultSettings): >+ (WebPreferences::lazyImageLoadingEnabled): >+ (WebPreferences::setLazyImageLoadingEnabled): >+ * WebPreferences.h: >+ * WebView.cpp: >+ (WebView::notifyPreferencesChanged): >+ > 2019-05-31 Don Olmstead <don.olmstead@sony.com> > > [CMake] Add WebKit::WTF target >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index 0d381d38c1d6c9348cc36ae005828bcd6f40a993..bf3be03e39b3f6b21843dbea598510e7191c33b1 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -1188,6 +1188,7 @@ html/InputType.cpp > html/InputTypeNames.cpp > html/LabelableElement.cpp > html/LabelsNodeList.cpp >+html/LazyLoadImageObserver.cpp > html/LinkIconCollector.cpp > html/LinkRelAttribute.cpp > html/MediaController.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index b65799a57d2ed21679394f15aad6888570f41657..c95bed4a3a5c390291ded238ca5450fb1cef5a06 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -3377,6 +3377,7 @@ > AA7FEEAD16A4E74B004C0C33 /* JSSpeechSynthesis.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7FEEAC16A4E74B004C0C33 /* JSSpeechSynthesis.h */; }; > AAA728F716D1D8BC00D3BBC6 /* WebAccessibilityObjectWrapperIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = AAA728F116D1D8BC00D3BBC6 /* WebAccessibilityObjectWrapperIOS.h */; }; > AAC08CF315F941FD00F1E188 /* AccessibilitySVGRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = AAC08CF115F941FC00F1E188 /* AccessibilitySVGRoot.h */; }; >+ AAD9D0B521DFA810001B11C7 /* LazyLoadImageObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = AAD9D0B321DFA80E001B11C7 /* LazyLoadImageObserver.h */; settings = {ATTRIBUTES = (Private, ); }; }; > AB23A32809BBA7D00067CC53 /* BeforeTextInsertedEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = AB23A32609BBA7D00067CC53 /* BeforeTextInsertedEvent.h */; }; > AB247A6D0AFD6383003FA5FD /* RenderSlider.h in Headers */ = {isa = PBXBuildFile; fileRef = AB247A6B0AFD6383003FA5FD /* RenderSlider.h */; }; > AB31C91E10AE1B8E000C7B92 /* LineClampValue.h in Headers */ = {isa = PBXBuildFile; fileRef = AB31C91D10AE1B8E000C7B92 /* LineClampValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -11990,6 +11991,8 @@ > AAA728F316D1D8BC00D3BBC6 /* AXObjectCacheIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AXObjectCacheIOS.mm; sourceTree = "<group>"; }; > AAC08CF015F941FC00F1E188 /* AccessibilitySVGRoot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilitySVGRoot.cpp; sourceTree = "<group>"; }; > AAC08CF115F941FC00F1E188 /* AccessibilitySVGRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilitySVGRoot.h; sourceTree = "<group>"; }; >+ AAD9D0B121DFA80C001B11C7 /* LazyLoadImageObserver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LazyLoadImageObserver.cpp; sourceTree = "<group>"; }; >+ AAD9D0B321DFA80E001B11C7 /* LazyLoadImageObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LazyLoadImageObserver.h; sourceTree = "<group>"; }; > AAE27B7416CBFC0D00623043 /* PlatformSpeechSynthesizerMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformSpeechSynthesizerMock.cpp; sourceTree = "<group>"; }; > AAE27B7516CBFC0D00623043 /* PlatformSpeechSynthesizerMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformSpeechSynthesizerMock.h; sourceTree = "<group>"; }; > AAE3755D17429BCC006200C2 /* PlatformSpeechSynthesizerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSpeechSynthesizerIOS.mm; sourceTree = "<group>"; }; >@@ -21573,6 +21576,8 @@ > 450CEBEF15073BBE002BB149 /* LabelableElement.h */, > A456FA2411AD4A830020B420 /* LabelsNodeList.cpp */, > A456FA2511AD4A830020B420 /* LabelsNodeList.h */, >+ AAD9D0B121DFA80C001B11C7 /* LazyLoadImageObserver.cpp */, >+ AAD9D0B321DFA80E001B11C7 /* LazyLoadImageObserver.h */, > 1A4DA41F1CDD3A8300F4473C /* LinkIconCollector.cpp */, > 1A4DA4201CDD3A8300F4473C /* LinkIconCollector.h */, > 1A250E0C1CDD632000D0BE63 /* LinkIconType.h */, >@@ -30479,6 +30484,7 @@ > 6F7CA3C6208C2957002F29AB /* LayoutState.h in Headers */, > 11310CF220BA4A320065A8D0 /* LayoutTreeBuilder.h in Headers */, > 141DC0481648348F00371E5A /* LayoutUnit.h in Headers */, >+ AAD9D0B521DFA810001B11C7 /* LazyLoadImageObserver.h in Headers */, > CDE8B5ED1A69777300B4B66A /* LegacyCDMPrivateClearKey.h in Headers */, > CDF4B7121E0087AE00E235A2 /* LegacyCDMSession.h in Headers */, > CDE8B5F11A69778B00B4B66A /* LegacyCDMSessionClearKey.h in Headers */, >diff --git a/Source/WebCore/css/CSSImageValue.cpp b/Source/WebCore/css/CSSImageValue.cpp >index e1420d1e835ef757b24490246dc6635c7ec41782..8d666c344c2ade6a72d069b850d07af6577cc31e 100644 >--- a/Source/WebCore/css/CSSImageValue.cpp >+++ b/Source/WebCore/css/CSSImageValue.cpp >@@ -58,14 +58,20 @@ bool CSSImageValue::isPending() const > return !m_accessedImage; > } > >-CachedImage* CSSImageValue::loadImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options) >+CachedImage* CSSImageValue::loadImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options, bool defer) > { >- if (!m_accessedImage) { >+ if (!m_accessedImage || defer) { > m_accessedImage = true; > > ResourceLoaderOptions loadOptions = options; > loadOptions.loadedFromOpaqueSource = m_loadedFromOpaqueSource; >- CachedResourceRequest request(ResourceRequest(loader.document()->completeURL(m_url.string())), loadOptions); >+ ResourceRequest resourceRequest(loader.document()->completeURL(m_url.string())); >+ if (defer) { >+ resourceRequest.setHTTPHeaderField(HTTPHeaderName::Range, "bytes=0-2047"); >+ loadOptions.cache = FetchOptions::Cache::NoStore; >+ } >+ >+ CachedResourceRequest request(WTFMove(resourceRequest), loadOptions); > if (m_initiatorName.isEmpty()) > request.setInitiator(cachedResourceRequestInitiators().css); > else >diff --git a/Source/WebCore/css/CSSImageValue.h b/Source/WebCore/css/CSSImageValue.h >index 59bb71c41ec66ecc3f3b4b737f748163b86a91bd..d11575a78a0f5db531952a53b928eec04e25817f 100644 >--- a/Source/WebCore/css/CSSImageValue.h >+++ b/Source/WebCore/css/CSSImageValue.h >@@ -41,7 +41,7 @@ public: > ~CSSImageValue(); > > bool isPending() const; >- CachedImage* loadImage(CachedResourceLoader&, const ResourceLoaderOptions&); >+ CachedImage* loadImage(CachedResourceLoader&, const ResourceLoaderOptions&, bool defer = false); > CachedImage* cachedImage() const { return m_cachedImage.get(); } > > const URL& url() const { return m_url; } >diff --git a/Source/WebCore/css/parser/CSSParser.cpp b/Source/WebCore/css/parser/CSSParser.cpp >index b4fa697c967a19145c3de332e357c6232d4a9ab2..e3b252f3b791d4d06b47f12eaa7d90371530362b 100644 >--- a/Source/WebCore/css/parser/CSSParser.cpp >+++ b/Source/WebCore/css/parser/CSSParser.cpp >@@ -167,6 +167,11 @@ Ref<ImmutableStyleProperties> CSSParser::parseInlineStyleDeclaration(const Strin > return CSSParserImpl::parseInlineStyleDeclaration(string, element); > } > >+Ref<ImmutableStyleProperties> CSSParser::parseInlineStyleDeclaration(const String& string, const CSSParserMode& mode) >+{ >+ return CSSParserImpl::parseInlineStyleDeclaration(string, mode); >+} >+ > bool CSSParser::parseDeclaration(MutableStyleProperties& declaration, const String& string) > { > return CSSParserImpl::parseDeclarationList(&declaration, string, m_context); >diff --git a/Source/WebCore/css/parser/CSSParser.h b/Source/WebCore/css/parser/CSSParser.h >index 47063cdfb9a255c56bfdc45f6ce4b036441100fa..4b7b79b0d41c3ee377cef34d17d5f0d59a2b7fb0 100644 >--- a/Source/WebCore/css/parser/CSSParser.h >+++ b/Source/WebCore/css/parser/CSSParser.h >@@ -75,6 +75,7 @@ public: > > WEBCORE_EXPORT bool parseDeclaration(MutableStyleProperties&, const String&); > static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, const Element*); >+ static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, const CSSParserMode&); > > void parseSelector(const String&, CSSSelectorList&); > >diff --git a/Source/WebCore/css/parser/CSSParserImpl.cpp b/Source/WebCore/css/parser/CSSParserImpl.cpp >index 4110cd4f554e26767eee69aee48fec38d8d8a61a..2f1c38c240a65e90885ffc720349f27121784ae7 100644 >--- a/Source/WebCore/css/parser/CSSParserImpl.cpp >+++ b/Source/WebCore/css/parser/CSSParserImpl.cpp >@@ -166,6 +166,15 @@ Ref<ImmutableStyleProperties> CSSParserImpl::parseInlineStyleDeclaration(const S > return createStyleProperties(parser.m_parsedProperties, context.mode); > } > >+Ref<ImmutableStyleProperties> CSSParserImpl::parseInlineStyleDeclaration(const String& string, const CSSParserMode& mode) >+{ >+ CSSParserContext context(mode); >+ >+ CSSParserImpl parser(context, string); >+ parser.consumeDeclarationList(parser.tokenizer()->tokenRange(), StyleRule::Style); >+ return createStyleProperties(parser.m_parsedProperties, context.mode); >+} >+ > Ref<ImmutableStyleProperties> CSSParserImpl::parseDeferredDeclaration(CSSParserTokenRange tokenRange, const CSSParserContext& context, StyleSheetContents* styleSheet) > { > if (!styleSheet) { >diff --git a/Source/WebCore/css/parser/CSSParserImpl.h b/Source/WebCore/css/parser/CSSParserImpl.h >index 36e37905e27bd3bc664506595297c218bcc92d78..93ed12a1c5e07f0ad65ce22c5f33d73eff8577e7 100644 >--- a/Source/WebCore/css/parser/CSSParserImpl.h >+++ b/Source/WebCore/css/parser/CSSParserImpl.h >@@ -85,6 +85,7 @@ public: > static CSSParser::ParseResult parseValue(MutableStyleProperties*, CSSPropertyID, const String&, bool important, const CSSParserContext&); > static CSSParser::ParseResult parseCustomPropertyValue(MutableStyleProperties*, const AtomicString& propertyName, const String&, bool important, const CSSParserContext&); > static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, const Element*); >+ static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, const CSSParserMode&); > static bool parseDeclarationList(MutableStyleProperties*, const String&, const CSSParserContext&); > static RefPtr<StyleRuleBase> parseRule(const String&, const CSSParserContext&, StyleSheetContents*, AllowedRulesType); > static void parseStyleSheet(const String&, const CSSParserContext&, StyleSheetContents*, CSSParser::RuleParsing); >diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp >index a2edab1f3f6a05409b649a9f33867d4043db3494..059b151e696ca3b19bb053ab7209102cdc5c1de5 100644 >--- a/Source/WebCore/dom/Document.cpp >+++ b/Source/WebCore/dom/Document.cpp >@@ -117,6 +117,7 @@ > #include "KeyboardEvent.h" > #include "KeyframeEffect.h" > #include "LayoutDisallowedScope.h" >+#include "LazyLoadImageObserver.h" > #include "LibWebRTCProvider.h" > #include "LoaderStrategy.h" > #include "Logging.h" >@@ -8230,4 +8231,11 @@ void Document::setApplePayIsActive() > > #endif > >+LazyLoadImageObserver& Document::ensureLazyLoadImageObserver() >+{ >+ if (!m_lazyLoadImageObserver) >+ m_lazyLoadImageObserver = new LazyLoadImageObserver(); >+ return *m_lazyLoadImageObserver; >+} >+ > } // namespace WebCore >diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h >index 1b6fafd12af3de7cc012508b08da215fd03c5aed..c98be7b81840d3fb1cc06fd815ec4da33f778f14 100644 >--- a/Source/WebCore/dom/Document.h >+++ b/Source/WebCore/dom/Document.h >@@ -147,6 +147,7 @@ class IntPoint; > class JSNode; > class LayoutPoint; > class LayoutRect; >+class LazyLoadImageObserver; > class LiveNodeList; > class Locale; > class Location; >@@ -1522,6 +1523,8 @@ public: > bool inHitTesting() const { return m_inHitTesting; } > #endif > >+ LazyLoadImageObserver& ensureLazyLoadImageObserver(); >+ > protected: > enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 }; > Document(Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0); >@@ -1709,6 +1712,8 @@ private: > > Element* m_cssTarget { nullptr }; > >+ LazyLoadImageObserver* m_lazyLoadImageObserver { nullptr }; >+ > RefPtr<SerializedScriptValue> m_pendingStateObject; > MonotonicTime m_documentCreationTime; > bool m_overMinimumLayoutThreshold { false }; >diff --git a/Source/WebCore/html/HTMLAttributeNames.in b/Source/WebCore/html/HTMLAttributeNames.in >index 1e9a826559e04c738ccab9ac369923edaeb05086..f80d5d6d136b111f0182bebe2fa64419e5fde63f 100644 >--- a/Source/WebCore/html/HTMLAttributeNames.in >+++ b/Source/WebCore/html/HTMLAttributeNames.in >@@ -165,6 +165,7 @@ language > leftmargin > link > list >+loading > longdesc > loop > low >diff --git a/Source/WebCore/html/HTMLImageElement.cpp b/Source/WebCore/html/HTMLImageElement.cpp >index 5cdc709399920d69672a97ce7fe5e831f5892736..4a91fff6d6da1027bf4a0407b46ed6d7714eb07f 100644 >--- a/Source/WebCore/html/HTMLImageElement.cpp >+++ b/Source/WebCore/html/HTMLImageElement.cpp >@@ -55,6 +55,7 @@ > #include "Settings.h" > #include "ShadowRoot.h" > #include "SizesAttributeParser.h" >+#include "StyleProperties.h" > #include <wtf/IsoMallocInlines.h> > #include <wtf/text/StringBuilder.h> > >@@ -68,7 +69,7 @@ WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLImageElement); > > using namespace HTMLNames; > >-HTMLImageElement::HTMLImageElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form) >+HTMLImageElement::HTMLImageElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form, bool createdByParser) > : HTMLElement(tagName, document) > , m_imageLoader(*this) > , m_form(nullptr) >@@ -76,6 +77,7 @@ HTMLImageElement::HTMLImageElement(const QualifiedName& tagName, Document& docum > , m_compositeOperator(CompositeSourceOver) > , m_imageDevicePixelRatio(1.0f) > , m_experimentalImageMenuEnabled(false) >+ , m_createdByParser(createdByParser) > { > ASSERT(hasTagName(imgTag)); > setHasCustomStyleResolveCallbacks(); >@@ -83,12 +85,12 @@ HTMLImageElement::HTMLImageElement(const QualifiedName& tagName, Document& docum > > Ref<HTMLImageElement> HTMLImageElement::create(Document& document) > { >- return adoptRef(*new HTMLImageElement(imgTag, document)); >+ return adoptRef(*new HTMLImageElement(imgTag, document, nullptr, false)); > } > >-Ref<HTMLImageElement> HTMLImageElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form) >+Ref<HTMLImageElement> HTMLImageElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form, bool createdByParser) > { >- return adoptRef(*new HTMLImageElement(tagName, document, form)); >+ return adoptRef(*new HTMLImageElement(tagName, document, form, createdByParser)); > } > > HTMLImageElement::~HTMLImageElement() >@@ -100,7 +102,7 @@ HTMLImageElement::~HTMLImageElement() > > Ref<HTMLImageElement> HTMLImageElement::createForJSConstructor(Document& document, Optional<unsigned> width, Optional<unsigned> height) > { >- auto image = adoptRef(*new HTMLImageElement(imgTag, document)); >+ auto image = adoptRef(*new HTMLImageElement(imgTag, document, nullptr, false)); > if (width) > image->setWidth(width.value()); > if (height) >@@ -240,9 +242,12 @@ void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicStr > m_experimentalImageMenuEnabled = !value.isNull(); > updateImageControls(); > #endif >- } else if (name == x_apple_editable_imageAttr) >+ } else if (name == x_apple_editable_imageAttr) { > updateEditableImage(); >- else { >+ } else if (name == loadingAttr && equalLettersIgnoringASCIICase(value, "eager")) { >+// !GetDocument().IsLazyLoadPolicyEnforced()) { >+ loadDeferredImage(); >+ } else { > if (name == nameAttr) { > bool willHaveName = !value.isNull(); > if (m_hadNameBeforeAttributeChanged != willHaveName && isConnected() && !isInShadowTree() && is<HTMLDocument>(document())) { >@@ -834,4 +839,37 @@ void HTMLImageElement::defaultEventHandler(Event& event) > HTMLElement::defaultEventHandler(event); > } > >+void HTMLImageElement::loadDeferredImage() >+{ >+ m_imageLoader.loadDeferredImage(); >+} >+ >+// Minimum height or width of the image to start lazyloading. >+constexpr int kMinDimensionToLazyLoad = 10; >+ >+HTMLImageElement::LazyLoadDimensionType HTMLImageElement::getAttributeLazyLoadDimensionType(const String& attributeValue) >+{ >+ auto optionalDimension = parseValidHTMLNonNegativeInteger(attributeValue); >+ if (optionalDimension && !attributeValue.endsWith('%')) { >+ return (optionalDimension.value() <= kMinDimensionToLazyLoad) >+ ? LazyLoadDimensionType::AbsoluteSmall >+ : LazyLoadDimensionType::AbsoluteNotSmall; >+ } >+ return LazyLoadDimensionType::NotAbsolute; >+} >+ >+HTMLImageElement::LazyLoadDimensionType HTMLImageElement::getInlineStyleDimensionsType(const StyleProperties* propertySet) >+{ >+ if (!propertySet) >+ return LazyLoadDimensionType::NotAbsolute; >+ auto height = propertySet->getPropertyCSSValue(CSSPropertyHeight); >+ auto width = propertySet->getPropertyCSSValue(CSSPropertyWidth); >+ const auto& widthPrim = downcast<CSSPrimitiveValue>(*width); >+ const auto& heightPrim = downcast<CSSPrimitiveValue>(*height); >+ if (!widthPrim.isPx() || !heightPrim.isPx()) >+ return LazyLoadDimensionType::NotAbsolute; >+ return (heightPrim.doubleValue() <= kMinDimensionToLazyLoad) && (widthPrim.doubleValue() <= kMinDimensionToLazyLoad) >+ ? LazyLoadDimensionType::AbsoluteSmall : LazyLoadDimensionType::AbsoluteNotSmall; >+} >+ > } >diff --git a/Source/WebCore/html/HTMLImageElement.h b/Source/WebCore/html/HTMLImageElement.h >index 1869880df3bf44a122a880feead62cfaef44eb15..3cfff930398a2772622317ba2fa104567acc88ed 100644 >--- a/Source/WebCore/html/HTMLImageElement.h >+++ b/Source/WebCore/html/HTMLImageElement.h >@@ -44,7 +44,7 @@ class HTMLImageElement : public HTMLElement, public FormNamedItem { > friend class HTMLFormElement; > public: > static Ref<HTMLImageElement> create(Document&); >- static Ref<HTMLImageElement> create(const QualifiedName&, Document&, HTMLFormElement*); >+ static Ref<HTMLImageElement> create(const QualifiedName&, Document&, HTMLFormElement*, bool createdByParser); > static Ref<HTMLImageElement> createForJSConstructor(Document&, Optional<unsigned> width, Optional<unsigned> height); > > virtual ~HTMLImageElement(); >@@ -123,8 +123,24 @@ public: > > void defaultEventHandler(Event&) final; > >+ void loadDeferredImage(); >+ >+ bool createdByParser() const { return m_createdByParser; } >+ >+ // Returns dimension type of the attribute value or inline dimensions usable >+ // for LazyLoad, whether the dimension is absolute or not and if the absolute >+ // value is small enough to be skipped for lazyloading. >+ enum class LazyLoadDimensionType { >+ NotAbsolute, >+ AbsoluteNotSmall, >+ AbsoluteSmall, >+ }; >+ >+ static LazyLoadDimensionType getAttributeLazyLoadDimensionType(const String& attributeValue); >+ static LazyLoadDimensionType getInlineStyleDimensionsType(const StyleProperties*); >+ > protected: >- HTMLImageElement(const QualifiedName&, Document&, HTMLFormElement* = 0); >+ HTMLImageElement(const QualifiedName&, Document&, HTMLFormElement*, bool createdByParser); > > void didMoveToNewDocument(Document& oldDocument, Document& newDocument) override; > >@@ -183,6 +199,7 @@ private: > float m_imageDevicePixelRatio; > bool m_experimentalImageMenuEnabled; > bool m_hadNameBeforeAttributeChanged { false }; // FIXME: We only need this because parseAttribute() can't see the old value. >+ bool m_createdByParser { false }; > > RefPtr<EditableImageReference> m_editableImage; > WeakPtr<HTMLPictureElement> m_pictureElement; >diff --git a/Source/WebCore/html/HTMLImageElement.idl b/Source/WebCore/html/HTMLImageElement.idl >index 03d6e2c04b773d6c2b2bf60cb9e8e8f3be9c3c02..0924eea8abf7760a1cce4cb9f900637cc371434f 100644 >--- a/Source/WebCore/html/HTMLImageElement.idl >+++ b/Source/WebCore/html/HTMLImageElement.idl >@@ -44,6 +44,8 @@ > > [Conditional=ATTACHMENT_ELEMENT, EnabledAtRuntime=AttachmentElement] readonly attribute DOMString attachmentIdentifier; > >+ [EnabledAtRuntime=LazyImageLoading, CEReactions, Reflect] attribute DOMString loading; >+ > // Extensions > readonly attribute boolean complete; > [CEReactions=NotNeeded, Reflect, URL] attribute USVString lowsrc; >diff --git a/Source/WebCore/html/HTMLTagNames.in b/Source/WebCore/html/HTMLTagNames.in >index dc75f122cdb265134b72ed06913d90ad9954eb78..88d69b24761bed9d171a1f9e3466a2f998828497 100644 >--- a/Source/WebCore/html/HTMLTagNames.in >+++ b/Source/WebCore/html/HTMLTagNames.in >@@ -67,7 +67,7 @@ html > i interfaceName=HTMLElement > iframe interfaceName=HTMLIFrameElement > image interfaceName=HTMLUnknownElement >-img interfaceName=HTMLImageElement, constructorNeedsFormElement >+img interfaceName=HTMLImageElement, constructorNeedsFormElement, constructorNeedsCreatedByParser > input constructorNeedsFormElement, constructorNeedsCreatedByParser > ins interfaceName=HTMLModElement > kbd interfaceName=HTMLElement >diff --git a/Source/WebCore/html/ImageDocument.cpp b/Source/WebCore/html/ImageDocument.cpp >index 151f44c9cd6e1553ed85ad78924082da5e582fb0..58a96aced8f1bd3d450023124a61c93b658c484c 100644 >--- a/Source/WebCore/html/ImageDocument.cpp >+++ b/Source/WebCore/html/ImageDocument.cpp >@@ -103,7 +103,7 @@ public: > > private: > ImageDocumentElement(ImageDocument& document) >- : HTMLImageElement(imgTag, document) >+ : HTMLImageElement(imgTag, document, nullptr, false) > , m_imageDocument(&document) > { > } >diff --git a/Source/WebCore/html/LazyLoadImageObserver.cpp b/Source/WebCore/html/LazyLoadImageObserver.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..9c173066ad9a7da1b7b801560fae55f6181eebcc >--- /dev/null >+++ b/Source/WebCore/html/LazyLoadImageObserver.cpp >@@ -0,0 +1,109 @@ >+/* >+ * Copyright (C) 2019 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "LazyLoadImageObserver.h" >+ >+#include "Frame.h" >+#include "HTMLImageElement.h" >+#include "IntersectionObserverCallback.h" >+#include "RenderStyle.h" >+ >+#include <limits> >+ >+namespace WebCore { >+ >+class IntersectionObserverCallbackImpl final : public IntersectionObserverCallback { >+public: >+ static Ref<IntersectionObserverCallbackImpl> create(Document* document) >+ { >+ return adoptRef(*new IntersectionObserverCallbackImpl(document)); >+ } >+ IntersectionObserverCallbackImpl(Document* document) >+ : IntersectionObserverCallback(document), m_document(document) >+ { >+ } >+ CallbackResult<void> handleEvent(const Vector<Ref<IntersectionObserverEntry>>& entries, IntersectionObserver&) >+ { >+ ASSERT(!entries.isEmpty()); >+ >+ for (auto& entry : entries) { >+ if (!entry->isIntersecting()) >+ continue; >+ Element* element = entry->target(); >+ if (is<HTMLImageElement>(element)) >+ downcast<HTMLImageElement>(*element).loadDeferredImage(); >+ >+ // Load the background image if the element has one deferred. >+ if (const auto* style = element->computedStyle()) >+ style->loadDeferredImages(*m_document); >+ >+ m_document->ensureLazyLoadImageObserver().stopMonitoring(*element); >+ } >+ return { }; >+ } >+private: >+ Document* m_document; >+}; >+ >+namespace { >+ >+Document* getRootDocumentOrNull(const Element& element) >+{ >+ if (Frame* frame = element.document().frame()) >+ return frame->tree().top().document(); >+ return nullptr; >+} >+ >+} // namespace >+ >+void LazyLoadImageObserver::startMonitoring(Element& element) >+{ >+ if (Document* document = getRootDocumentOrNull(element)) >+ document->ensureLazyLoadImageObserver().startMonitoringNearViewport(document, element); >+} >+ >+void LazyLoadImageObserver::stopMonitoring(Element& element) >+{ >+ if (Document* document = getRootDocumentOrNull(element)) >+ document->ensureLazyLoadImageObserver().m_lazyLoadIntersectionObserver->unobserve(element); >+} >+ >+LazyLoadImageObserver::LazyLoadImageObserver() = default; >+ >+void LazyLoadImageObserver::startMonitoringNearViewport(Document* rootDocument, Element& element) >+{ >+ if (!m_lazyLoadIntersectionObserver) { >+ auto callback = IntersectionObserverCallbackImpl::create(rootDocument); >+ auto options = IntersectionObserver::Init { nullptr, "", { } }; >+ auto observer = IntersectionObserver::create(*rootDocument, WTFMove(callback), WTFMove(options)); >+ if (observer.hasException()) >+ return; >+ m_lazyLoadIntersectionObserver = observer.returnValue().ptr(); >+ } >+ m_lazyLoadIntersectionObserver->observe(element); >+} >+ >+} >diff --git a/Source/WebCore/html/LazyLoadImageObserver.h b/Source/WebCore/html/LazyLoadImageObserver.h >new file mode 100644 >index 0000000000000000000000000000000000000000..03c81a282bd36c3b67fed02c8cfe7b176cd9178b >--- /dev/null >+++ b/Source/WebCore/html/LazyLoadImageObserver.h >@@ -0,0 +1,50 @@ >+/* >+ * Copyright (C) 2019 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include "IntersectionObserver.h" >+ >+namespace WebCore { >+ >+class Document; >+class Element; >+ >+class LazyLoadImageObserver { >+public: >+ LazyLoadImageObserver(); >+ >+ static void startMonitoring(Element&); >+ static void stopMonitoring(Element&); >+ >+private: >+ void startMonitoringNearViewport(Document*, Element&); >+ >+ // The intersection observer responsible for loading the image once it's near >+ // the viewport. >+ RefPtr<IntersectionObserver> m_lazyLoadIntersectionObserver; >+}; >+ >+} // namespace >diff --git a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp b/Source/WebCore/html/parser/HTMLPreloadScanner.cpp >index d71ec552505745816d55364e3fab6eb1c8e90c0b..07f73f9f6ad396decc40ec5528aae2e0759e2ef8 100644 >--- a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp >+++ b/Source/WebCore/html/parser/HTMLPreloadScanner.cpp >@@ -28,6 +28,7 @@ > #include "config.h" > #include "HTMLPreloadScanner.h" > >+#include "HTMLImageElement.h" > #include "HTMLNames.h" > #include "HTMLParserIdioms.h" > #include "HTMLSrcsetParser.h" >@@ -43,6 +44,7 @@ > #include "RenderView.h" > #include "RuntimeEnabledFeatures.h" > #include "SizesAttributeParser.h" >+#include "StyleProperties.h" > #include <wtf/MainThread.h> > > namespace WebCore { >@@ -161,10 +163,26 @@ public: > if (!LinkLoader::isSupportedType(type.value(), m_typeAttribute)) > return nullptr; > >+ // LazyLoad: Do not preload if absolute dimensions are mentioned in width >+ // and height attributes or in the inline style, and the dimensions are not >+ // small enough. >+ if (((m_widthAttrDimensionType == HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall >+ && m_heightAttrDimensionType == HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall) >+ || m_inlineStyleDimensionsType == HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall)) { >+ return nullptr; >+ } >+ > auto request = std::make_unique<PreloadRequest>(initiatorFor(m_tagId), m_urlToLoad, predictedBaseURL, type.value(), m_mediaAttribute, m_moduleScript); > request->setCrossOriginMode(m_crossOriginMode); > request->setNonce(m_nonceAttribute); > >+ if (equalLettersIgnoringASCIICase(m_lazyloadAttribute, "lazy") >+ && ((m_widthAttrDimensionType == HTMLImageElement::LazyLoadDimensionType::NotAbsolute >+ && m_heightAttrDimensionType == HTMLImageElement::LazyLoadDimensionType::NotAbsolute) >+ || m_inlineStyleDimensionsType == HTMLImageElement::LazyLoadDimensionType::NotAbsolute)) { >+ request->setLazyloadImageEnabled(true); >+ } >+ > // According to the spec, the module tag ignores the "charset" attribute as the same to the worker's > // importScript. But WebKit supports the "charset" for importScript intentionally. So to be consistent, > // even for the module tags, we handle the "charset" attribute. >@@ -206,6 +224,26 @@ private: > m_sizesAttribute = attributeValue; > break; > } >+ if (match(attributeName, loadingAttr) && m_lazyloadAttribute.isNull()) { >+ m_lazyloadAttribute = attributeValue; >+ break; >+ } >+ if (RuntimeEnabledFeatures::sharedFeatures().lazyImageLoadingEnabled()) { >+ if (match(attributeName, widthAttr) && m_widthAttrDimensionType == HTMLImageElement::LazyLoadDimensionType::NotAbsolute) { >+ m_widthAttrDimensionType = HTMLImageElement::getAttributeLazyLoadDimensionType(attributeValue); >+ break; >+ } >+ if (match(attributeName, heightAttr) && m_heightAttrDimensionType == HTMLImageElement::LazyLoadDimensionType::NotAbsolute) { >+ m_heightAttrDimensionType = HTMLImageElement::getAttributeLazyLoadDimensionType(attributeValue); >+ break; >+ } >+ if (match(attributeName, styleAttr) && m_inlineStyleDimensionsType == HTMLImageElement::LazyLoadDimensionType::NotAbsolute) { >+ CSSParserMode mode = /*media_values_->StrictMode() ? HTMLStandardMode :*/ HTMLQuirksMode; >+ const auto propertySet = CSSParser::parseInlineStyleDeclaration(attributeValue, mode); >+ m_inlineStyleDimensionsType = HTMLImageElement::getInlineStyleDimensionsType(propertySet.ptr()); >+ } >+ } >+ > processImageAndScriptAttribute(attributeName, attributeValue); > break; > case TagId::Source: >@@ -365,9 +403,13 @@ private: > String m_metaContent; > String m_asAttribute; > String m_typeAttribute; >+ String m_lazyloadAttribute; > bool m_metaIsViewport; > bool m_metaIsDisabledAdaptations; > bool m_inputIsImage; >+ HTMLImageElement::LazyLoadDimensionType m_widthAttrDimensionType { HTMLImageElement::LazyLoadDimensionType::NotAbsolute }; >+ HTMLImageElement::LazyLoadDimensionType m_heightAttrDimensionType { HTMLImageElement::LazyLoadDimensionType::NotAbsolute }; >+ HTMLImageElement::LazyLoadDimensionType m_inlineStyleDimensionsType { HTMLImageElement::LazyLoadDimensionType::NotAbsolute }; > float m_deviceScaleFactor; > PreloadRequest::ModuleScript m_moduleScript { PreloadRequest::ModuleScript::No }; > }; >diff --git a/Source/WebCore/html/parser/HTMLPreloadScanner.h b/Source/WebCore/html/parser/HTMLPreloadScanner.h >index 8181da74a29f7a5b49af4f9f87f649ca83d62d03..cdb19b84ed9ecb0e7ff6dd60ee4f72b517d0e5c3 100644 >--- a/Source/WebCore/html/parser/HTMLPreloadScanner.h >+++ b/Source/WebCore/html/parser/HTMLPreloadScanner.h >@@ -81,6 +81,12 @@ private: > unsigned m_templateCount { 0 }; > }; > >+enum class LazyLoadImageSetting { >+ Disabled, >+ EnabledExplicit, >+ EnabledAutomatic >+}; >+ > class HTMLPreloadScanner { > WTF_MAKE_FAST_ALLOCATED; > public: >diff --git a/Source/WebCore/html/parser/HTMLResourcePreloader.cpp b/Source/WebCore/html/parser/HTMLResourcePreloader.cpp >index 3d006ab04bf528764f9f0c844abf46e0d63631ff..5b7adb920de81a834d096d5f9527ad63a4a26730 100644 >--- a/Source/WebCore/html/parser/HTMLResourcePreloader.cpp >+++ b/Source/WebCore/html/parser/HTMLResourcePreloader.cpp >@@ -54,12 +54,18 @@ CachedResourceRequest PreloadRequest::resourceRequest(Document& document) > if (skipContentSecurityPolicyCheck) > options.contentSecurityPolicyImposition = ContentSecurityPolicyImposition::SkipPolicyCheck; > >+ ResourceRequest resourceRequest(completeURL(document)); >+ if (m_lazyloadImageEnabled) { >+ resourceRequest.setHTTPHeaderField(HTTPHeaderName::Range, "bytes=0-2047"); >+ options.cache = FetchOptions::Cache::NoStore; >+ } >+ > String crossOriginMode = m_crossOriginMode; > if (m_moduleScript == ModuleScript::Yes) { > if (crossOriginMode.isNull()) > crossOriginMode = "omit"_s; > } >- auto request = createPotentialAccessControlRequest(completeURL(document), document, crossOriginMode, WTFMove(options)); >+ auto request = createPotentialAccessControlRequest(WTFMove(resourceRequest), document, crossOriginMode, WTFMove(options)); > request.setInitiator(m_initiator); > return request; > } >diff --git a/Source/WebCore/html/parser/HTMLResourcePreloader.h b/Source/WebCore/html/parser/HTMLResourcePreloader.h >index dae7464b38387c475618af3169ef31f5f047deeb..1c57e679ea482a044696a32ecdff6a734fd750ce 100644 >--- a/Source/WebCore/html/parser/HTMLResourcePreloader.h >+++ b/Source/WebCore/html/parser/HTMLResourcePreloader.h >@@ -54,6 +54,7 @@ public: > void setCharset(const String& charset) { m_charset = charset.isolatedCopy(); } > void setCrossOriginMode(const String& mode) { m_crossOriginMode = mode; } > void setNonce(const String& nonce) { m_nonceAttribute = nonce; } >+ void setLazyloadImageEnabled(bool enabled) { m_lazyloadImageEnabled = enabled; } > CachedResource::Type resourceType() const { return m_resourceType; } > > private: >@@ -68,6 +69,7 @@ private: > String m_crossOriginMode; > String m_nonceAttribute; > ModuleScript m_moduleScript; >+ bool m_lazyloadImageEnabled { false }; > }; > > typedef Vector<std::unique_ptr<PreloadRequest>> PreloadRequestStream; >diff --git a/Source/WebCore/loader/ImageLoader.cpp b/Source/WebCore/loader/ImageLoader.cpp >index 03fbb318c3e2d3608e77463277d1613803b3e00c..962b644291654c8d781bceb992c98fc72237eb59 100644 >--- a/Source/WebCore/loader/ImageLoader.cpp >+++ b/Source/WebCore/loader/ImageLoader.cpp >@@ -38,9 +38,12 @@ > #include "HTMLObjectElement.h" > #include "HTMLParserIdioms.h" > #include "InspectorInstrumentation.h" >+#include "LazyLoadImageObserver.h" > #include "Page.h" > #include "RenderImage.h" > #include "RenderSVGImage.h" >+#include "RuntimeEnabledFeatures.h" >+#include "StyleProperties.h" > #include <wtf/NeverDestroyed.h> > > #if ENABLE(VIDEO) >@@ -66,6 +69,28 @@ template<> struct ValueCheck<WebCore::ImageLoader*> { > > namespace WebCore { > >+static bool isLazyLoadableImage(const HTMLImageElement& htmlImage, const URL& url) >+{ >+ // Do not lazyload image elements created from javascript. >+ if (!htmlImage.createdByParser()) >+ return false; >+ if (!url.protocolIsInHTTPFamily()) >+ return false; >+ if (!equalLettersIgnoringASCIICase(htmlImage.attributeWithoutSynchronization(HTMLNames::loadingAttr), "lazy")) >+ return false; >+ // Avoid lazyloading if width and height attributes are small. This >+ // heuristic helps avoid double fetching tracking pixels. >+ if (HTMLImageElement::getAttributeLazyLoadDimensionType(htmlImage.attributeWithoutSynchronization(HTMLNames::widthAttr)) == HTMLImageElement::LazyLoadDimensionType::AbsoluteSmall >+ && HTMLImageElement::getAttributeLazyLoadDimensionType(htmlImage.attributeWithoutSynchronization(HTMLNames::heightAttr)) == HTMLImageElement::LazyLoadDimensionType::AbsoluteSmall) { >+ return false; >+ } >+ // Avoid lazyloading if width or height is specified in inline style and is >+ // small enough. This heuristic helps avoid double fetching tracking pixels. >+ if (HTMLImageElement::getInlineStyleDimensionsType(htmlImage.inlineStyle()) == HTMLImageElement::LazyLoadDimensionType::AbsoluteSmall) >+ return false; >+ return true; >+} >+ > static ImageEventSender& beforeLoadEventSender() > { > static NeverDestroyed<ImageEventSender> sender(eventNames().beforeloadEvent); >@@ -157,6 +182,21 @@ void ImageLoader::clearImageWithoutConsideringPendingLoadEvent() > imageResource->resetAnimation(); > } > >+// Returns true if absolute dimension is specified in the width and height >+// attributes or in the inline style. >+bool isDimensionAbsoluteLarge(const HTMLImageElement& htmlImage) >+{ >+ if ((HTMLImageElement::getAttributeLazyLoadDimensionType(htmlImage.attributeWithoutSynchronization(HTMLNames::widthAttr)) == >+ HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall) >+ || (HTMLImageElement::getAttributeLazyLoadDimensionType(htmlImage.attributeWithoutSynchronization(HTMLNames::heightAttr)) == >+ HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall)) { >+ return true; >+ } >+ if (HTMLImageElement::getInlineStyleDimensionsType(htmlImage.inlineStyle()) == HTMLImageElement::LazyLoadDimensionType::AbsoluteNotSmall) >+ return true; >+ return false; >+} >+ > void ImageLoader::updateFromElement() > { > // If we're not making renderers for the page, then don't load images. We don't want to slow >@@ -183,6 +223,18 @@ void ImageLoader::updateFromElement() > > ResourceRequest resourceRequest(document.completeURL(sourceURI(attr))); > resourceRequest.setInspectorInitiatorNodeIdentifier(InspectorInstrumentation::identifierForNode(m_element)); >+ if (m_lazyImageLoadState == LazyImageLoadState::kNone) { >+ if (is<HTMLImageElement>(element())) { >+ if (isLazyLoadableImage(downcast<HTMLImageElement>(element()), resourceRequest.url()) >+ && RuntimeEnabledFeatures::sharedFeatures().lazyImageLoadingEnabled()) { >+ m_lazyImageLoadState = LazyImageLoadState::kDeferred; >+ if (isDimensionAbsoluteLarge(downcast<HTMLImageElement>(element()))) { >+ resourceRequest.setHTTPHeaderField(HTTPHeaderName::Range, "bytes=0-2047"); >+ options.cache = FetchOptions::Cache::NoStore; >+ } >+ } >+ } >+ } > > auto request = createPotentialAccessControlRequest(WTFMove(resourceRequest), document, crossOriginAttribute, WTFMove(options)); > request.setInitiator(element()); >@@ -250,6 +302,8 @@ void ImageLoader::updateFromElement() > } else > updateRenderer(); > >+ if (m_lazyImageLoadState == LazyImageLoadState::kDeferred) >+ LazyLoadImageObserver::startMonitoring(element()); > // If newImage is cached, addClient() will result in the load event > // being queued to fire. Ensure this happens after beforeload is > // dispatched. >@@ -280,6 +334,21 @@ void ImageLoader::notifyFinished(CachedResource& resource) > ASSERT(m_failedLoadURL.isEmpty()); > ASSERT_UNUSED(resource, &resource == m_image.get()); > >+ if (m_lazyImageLoadState == LazyImageLoadState::kDeferred) { >+ // LazyImages: if a placeholder is loaded, suppress load events and do not >+ // consider the image as loaded, except for unblocking document load events. >+ // The final image load (including load events) occurs when the >+ // non-placeholder image loading (triggered by loadDeferredImage()) is >+ // finished. >+ if (resource.response().httpStatusCode() == 206) >+ return; >+ // A placeholder was requested, but the result was an error or a full image. >+ // In these cases, consider this as the final image and suppress further >+ // reloading and proceed to the image load completion process below. >+ LazyLoadImageObserver::stopMonitoring(element()); >+ m_lazyImageLoadState = LazyImageLoadState::kFullImage; >+ } >+ > m_imageComplete = true; > if (!hasPendingBeforeLoadEvent()) > updateRenderer(); >@@ -542,4 +611,12 @@ inline void ImageLoader::clearFailedLoadURL() > m_failedLoadURL = nullAtom(); > } > >+void ImageLoader::loadDeferredImage() >+{ >+ if (m_lazyImageLoadState != LazyImageLoadState::kDeferred) >+ return; >+ m_lazyImageLoadState = LazyImageLoadState::kFullImage; >+ updateFromElement(); >+} >+ > } >diff --git a/Source/WebCore/loader/ImageLoader.h b/Source/WebCore/loader/ImageLoader.h >index bd4ba9e664dacc066969fdffa3bc51c39b964cae..1d280be3df2056b3c33c0531f00c87af155fa0cf 100644 >--- a/Source/WebCore/loader/ImageLoader.h >+++ b/Source/WebCore/loader/ImageLoader.h >@@ -74,11 +74,16 @@ public: > static void dispatchPendingLoadEvents(); > static void dispatchPendingErrorEvents(); > >+ void loadDeferredImage(); >+ > protected: > explicit ImageLoader(Element&); > void notifyFinished(CachedResource&) override; > > private: >+ // LazyImages: Defer the image load until the image is near the viewport. >+ enum class LazyImageLoadState { kNone, kDeferred, kFullImage }; >+ > virtual void dispatchLoadEvent() = 0; > virtual String sourceURI(const AtomicString&) const = 0; > >@@ -112,6 +117,7 @@ private: > bool m_imageComplete : 1; > bool m_loadManually : 1; > bool m_elementIsProtected : 1; >+ LazyImageLoadState m_lazyImageLoadState { LazyImageLoadState::kNone }; > }; > > } >diff --git a/Source/WebCore/page/RuntimeEnabledFeatures.h b/Source/WebCore/page/RuntimeEnabledFeatures.h >index 1b9ddaccb8cf3bcdafd70904688cfee466944599..9ec76b6692022b496abfca404d8b03c9bd84530d 100644 >--- a/Source/WebCore/page/RuntimeEnabledFeatures.h >+++ b/Source/WebCore/page/RuntimeEnabledFeatures.h >@@ -363,6 +363,9 @@ public: > bool linkPreloadResponsiveImagesEnabled() const { return m_linkPreloadResponsiveImagesEnabled; } > void setLinkPreloadResponsiveImagesEnabled(bool isEnabled) { m_linkPreloadResponsiveImagesEnabled = isEnabled; } > >+ void setLazyImageLoadingEnabled(bool areEnabled) { m_lazyImageLoadingEnabled = areEnabled; } >+ bool lazyImageLoadingEnabled() const { return m_lazyImageLoadingEnabled; } >+ > WEBCORE_EXPORT static RuntimeEnabledFeatures& sharedFeatures(); > > private: >@@ -550,6 +553,8 @@ private: > > bool m_linkPreloadResponsiveImagesEnabled { false }; > >+ bool m_lazyImageLoadingEnabled { false }; >+ > friend class WTF::NeverDestroyed<RuntimeEnabledFeatures>; > }; > >diff --git a/Source/WebCore/page/Settings.yaml b/Source/WebCore/page/Settings.yaml >index f77fca3a4c2a196b7e951717426aad170f71a720..7fff829cd044dd620dc93e5a7249a005260e12bf 100644 >--- a/Source/WebCore/page/Settings.yaml >+++ b/Source/WebCore/page/Settings.yaml >@@ -736,6 +736,9 @@ resizeObserverEnabled: > initial: false > conditional: RESIZE_OBSERVER > >+lazyImageLoadingEnabled: >+ initial: false >+ > # Only set by Layout Tests. > mediaTypeOverride: > type: String >diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp >index 0aa79711e9be4458ca7567233493251bef8b7d90..fdc3f3081d0edee2de04f6a64460e4b77761370c 100644 >--- a/Source/WebCore/rendering/style/RenderStyle.cpp >+++ b/Source/WebCore/rendering/style/RenderStyle.cpp >@@ -28,6 +28,7 @@ > #include "CSSParser.h" > #include "CSSPropertyNames.h" > #include "CSSPropertyParser.h" >+#include "CachedImage.h" > #include "ContentData.h" > #include "CursorList.h" > #include "FloatRoundedRect.h" >@@ -42,6 +43,7 @@ > #include "ScaleTransformOperation.h" > #include "ShadowData.h" > #include "StyleBuilderConverter.h" >+#include "StyleCachedImage.h" > #include "StyleImage.h" > #include "StyleInheritedData.h" > #include "StyleResolver.h" >@@ -2457,4 +2459,14 @@ Color RenderStyle::computedStrokeColor() const > return visitedDependentColor(propertyID); > } > >+void RenderStyle::loadDeferredImages(Document& document) const >+{ >+ if (hasBackgroundImage()) { >+ for (auto* layer = &backgroundLayers(); layer; layer = layer->next()) { >+ if (layer->image() && is<StyleCachedImage>(*layer->image())) >+ downcast<StyleCachedImage>(*layer->image()).loadDeferredImage(document); >+ } >+ } >+} >+ > } // namespace WebCore >diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h >index 2c55d012de2be8d7903908d1e641d2dc52f78afd..12b6096757703de98125f0d2ab217b89852446cf 100644 >--- a/Source/WebCore/rendering/style/RenderStyle.h >+++ b/Source/WebCore/rendering/style/RenderStyle.h >@@ -1440,7 +1440,9 @@ public: > > void setHasExplicitlyInheritedProperties() { m_nonInheritedFlags.hasExplicitlyInheritedProperties = true; } > bool hasExplicitlyInheritedProperties() const { return m_nonInheritedFlags.hasExplicitlyInheritedProperties; } >- >+ >+ void loadDeferredImages(Document&) const; >+ > // Initial values for all the properties > static Overflow initialOverflowX() { return Overflow::Visible; } > static Overflow initialOverflowY() { return Overflow::Visible; } >diff --git a/Source/WebCore/rendering/style/StyleCachedImage.cpp b/Source/WebCore/rendering/style/StyleCachedImage.cpp >index d447205ca6c48ef684e1ebb195532c0b9ce4ed08..92a27c2a9112e4f35835820ee4fad4f7f1d606fc 100644 >--- a/Source/WebCore/rendering/style/StyleCachedImage.cpp >+++ b/Source/WebCore/rendering/style/StyleCachedImage.cpp >@@ -28,6 +28,7 @@ > #include "CSSImageSetValue.h" > #include "CSSImageValue.h" > #include "CachedImage.h" >+#include "LazyLoadImageObserver.h" > #include "RenderElement.h" > #include "RenderView.h" > >@@ -192,6 +193,8 @@ void StyleCachedImage::addClient(RenderElement* renderer) > return; > ASSERT(renderer); > m_cachedImage->addClient(*renderer); >+ if (isLazyloadPossiblyDeferred() && is<CSSImageValue>(m_cssValue) && renderer->element()) >+ LazyLoadImageObserver::startMonitoring(*renderer->element()); > } > > void StyleCachedImage::removeClient(RenderElement* renderer) >@@ -202,6 +205,8 @@ void StyleCachedImage::removeClient(RenderElement* renderer) > ASSERT(renderer); > > m_cachedImage->removeClient(*renderer); >+ if (isLazyloadPossiblyDeferred() && is<CSSImageValue>(m_cssValue) && renderer->element()) >+ LazyLoadImageObserver::stopMonitoring(*renderer->element()); > } > > RefPtr<Image> StyleCachedImage::image(RenderElement* renderer, const FloatSize&) const >@@ -224,4 +229,15 @@ bool StyleCachedImage::knownToBeOpaque(const RenderElement* renderer) const > return m_cachedImage->currentFrameKnownToBeOpaque(renderer); > } > >+void StyleCachedImage::loadDeferredImage(Document& document) >+{ >+ if (!is<CSSImageValue>(m_cssValue)) >+ return; >+ ResourceLoaderOptions options; >+ options.cache = FetchOptions::Cache::Reload; >+ auto& imageValue = downcast<CSSImageValue>(m_cssValue.get()); >+ m_cachedImage = imageValue.loadImage(document.cachedResourceLoader(), options, !imageURL().protocolIsInHTTPFamily()); >+ m_cachedImage->setLoading(true); >+} >+ > } >diff --git a/Source/WebCore/rendering/style/StyleCachedImage.h b/Source/WebCore/rendering/style/StyleCachedImage.h >index 10f86c70b7f9520cc39a9f291aef224fb45038c1..ab9559b071743fd70ee2c4a1384f51488a5004b6 100644 >--- a/Source/WebCore/rendering/style/StyleCachedImage.h >+++ b/Source/WebCore/rendering/style/StyleCachedImage.h >@@ -63,6 +63,8 @@ public: > float imageScaleFactor() const final; > bool knownToBeOpaque(const RenderElement*) const final; > >+ void loadDeferredImage(Document&); >+ > private: > StyleCachedImage(CSSValue&); > URL imageURL(); >diff --git a/Source/WebCore/rendering/style/StyleImage.h b/Source/WebCore/rendering/style/StyleImage.h >index 9b8353bbaa4dd654517caa6dce6237bb17e5c388..6a60d1a6d42b6de33bbb0d78e94643b44bbe9d67 100644 >--- a/Source/WebCore/rendering/style/StyleImage.h >+++ b/Source/WebCore/rendering/style/StyleImage.h >@@ -71,14 +71,18 @@ public: > ALWAYS_INLINE bool isCachedImage() const { return m_isCachedImage; } > ALWAYS_INLINE bool isGeneratedImage() const { return m_isGeneratedImage; } > >+ bool isLazyloadPossiblyDeferred() const { return m_isLazyloadPossiblyDeferred; } >+ > protected: > StyleImage() > : m_isCachedImage(false) > , m_isGeneratedImage(false) >+ , m_isLazyloadPossiblyDeferred(false) > { > } > bool m_isCachedImage : 1; > bool m_isGeneratedImage : 1; >+ bool m_isLazyloadPossiblyDeferred : 1; > }; > > } // namespace WebCore >diff --git a/Source/WebKit/Shared/WebPreferences.yaml b/Source/WebKit/Shared/WebPreferences.yaml >index 5ec408bf75c7ad61cfdd98c99ebfe196d7f64951..dad7bd1366c7aa9b432c02504366a540c5e641ef 100644 >--- a/Source/WebKit/Shared/WebPreferences.yaml >+++ b/Source/WebKit/Shared/WebPreferences.yaml >@@ -1710,3 +1710,11 @@ MediaCaptureRequiresSecureConnection: > type: bool > defaultValue: true > condition: ENABLE(MEDIA_STREAM) >+ >+LazyImageLoadingEnabled: >+ type: bool >+ defaultValue: false >+ humanReadableName: "Lazy Image Loading" >+ humanReadableDescription: "Enable Lazy Image Loading support" >+ category: experimental >+ webcoreBinding: RuntimeEnabledFeatures >diff --git a/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h b/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h >index 3b21e6405e224d71a0d43ad4615da91d66fcf295..9b1b2953b8974515d7175b29522c3007a20baea9 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h >+++ b/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h >@@ -270,4 +270,5 @@ > #define WebKitResizeObserverEnabledPreferenceKey @"WebKitResizeObserverEnabled" > #define WebKitCoreMathMLEnabledPreferenceKey @"WebKitCoreMathMLEnabled" > #define WebKitLinkPreloadResponsiveImagesEnabledPreferenceKey @"WebKitLinkPreloadResponsiveImagesEnabled" >+#define WebKitLazyImageLoadingEnabledPreferenceKey @"WebKitLazyImageLoadingEnabled" > >diff --git a/Source/WebKitLegacy/mac/WebView/WebPreferences.mm b/Source/WebKitLegacy/mac/WebView/WebPreferences.mm >index 81877304a01d9a9f6823c871c30341e2d9397647..b90ab1a803ca9674449fc0b5f6b642b9e18a4cec 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebPreferences.mm >+++ b/Source/WebKitLegacy/mac/WebView/WebPreferences.mm >@@ -690,6 +690,7 @@ public: > #if ENABLE(RESIZE_OBSERVER) > @NO, WebKitResizeObserverEnabledPreferenceKey, > #endif >+ @NO, WebKitLazyImageLoadingEnabledPreferenceKey, > @NO, WebKitCoreMathMLEnabledPreferenceKey, > @NO, WebKitLinkPreloadResponsiveImagesEnabledPreferenceKey, > nil]; >@@ -3478,6 +3479,16 @@ static NSString *classIBCreatorID = nil; > [self _setBoolValue:flag forKey:WebKitLinkPreloadResponsiveImagesEnabledPreferenceKey]; > } > >+- (BOOL)lazyImageLoadingEnabled >+{ >+ return [self _boolValueForKey:WebKitLazyImageLoadingEnabledPreferenceKey]; >+} >+ >+- (void)setLazyImageLoadingEnabled:(BOOL)flag >+{ >+ [self _setBoolValue:flag forKey:WebKitLazyImageLoadingEnabledPreferenceKey]; >+} >+ > @end > > @implementation WebPreferences (WebInternal) >diff --git a/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h b/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h >index 1229edf9e6d6b2d4d1cb731b14168f58f0f17175..427ec5c3bd9be1d8269cf0cf62b408decaa9c250 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h >+++ b/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h >@@ -643,6 +643,7 @@ extern NSString *WebPreferencesCacheModelChangedInternalNotification WEBKIT_DEPR > @property (nonatomic) BOOL resizeObserverEnabled; > @property (nonatomic) BOOL coreMathMLEnabled; > @property (nonatomic) BOOL linkPreloadResponsiveImagesEnabled; >+@property (nonatomic) BOOL lazyImageLoadingEnabled; > > #if TARGET_OS_IPHONE > @property (nonatomic) BOOL quickLookDocumentSavingEnabled; >diff --git a/Source/WebKitLegacy/mac/WebView/WebView.mm b/Source/WebKitLegacy/mac/WebView/WebView.mm >index 38de68b3e0e9dda18edccbdd456117211a9f4602..520485c1b113a23ba21f65275705b3ef48486980 100644 >--- a/Source/WebKitLegacy/mac/WebView/WebView.mm >+++ b/Source/WebKitLegacy/mac/WebView/WebView.mm >@@ -3178,6 +3178,7 @@ static bool needsSelfRetainWhileLoadingQuirk() > RuntimeEnabledFeatures::sharedFeatures().setFetchAPIKeepAliveEnabled([preferences fetchAPIKeepAliveEnabled]); > RuntimeEnabledFeatures::sharedFeatures().setReferrerPolicyAttributeEnabled([preferences referrerPolicyAttributeEnabled]); > RuntimeEnabledFeatures::sharedFeatures().setLinkPreloadResponsiveImagesEnabled([preferences linkPreloadResponsiveImagesEnabled]); >+ RuntimeEnabledFeatures::sharedFeatures().setLazyImageLoadingEnabled([preferences referrerPolicyAttributeEnabled]); > > #if ENABLE(LEGACY_ENCRYPTED_MEDIA) > RuntimeEnabledFeatures::sharedFeatures().setLegacyEncryptedMediaAPIEnabled(preferences.legacyEncryptedMediaAPIEnabled); >@@ -3232,6 +3233,8 @@ static bool needsSelfRetainWhileLoadingQuirk() > #if ENABLE(RESIZE_OBSERVER) > settings.setResizeObserverEnabled([preferences resizeObserverEnabled]); > #endif >+ >+ settings.setLazyImageLoadingEnabled([preferences lazyImageLoadingEnabled]); > } > > static inline IMP getMethod(id o, SEL s) >diff --git a/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl b/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl >index cb8dda4aefbdaa68b17beebe7195d0cbba2534cf..4f3a563cb6665f42b72e68d13da4c96a54f21688 100644 >--- a/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl >+++ b/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl >@@ -242,4 +242,6 @@ interface IWebPreferencesPrivate7 : IWebPreferencesPrivate6 > HRESULT setResizeObserverEnabled([in] BOOL enabled); > HRESULT coreMathMLEnabled([out, retval] BOOL* enabled); > HRESULT setCoreMathMLEnabled([in] BOOL enabled); >+ HRESULT lazyImageLoadingEnabled([out, retval] BOOL*); >+ HRESULT setLazyImageLoadingEnabled([in] BOOL enabled); > } >diff --git a/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h b/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h >index ba662703ab86791702bad561e794a3878de8cf02..47ea93bc39701b32d65d672636c503b3b2435b66 100644 >--- a/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h >+++ b/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h >@@ -209,3 +209,5 @@ > #define WebKitResizeObserverEnabledPreferenceKey "WebKitResizeObserverEnabled" > > #define WebKitCoreMathMLEnabledPreferenceKey "WebKitCoreMathMLEnabled" >+ >+#define WebKitLazyImageLoadingEnabledPreferenceKey "WebKitLazyImageLoadingEnabled" >diff --git a/Source/WebKitLegacy/win/WebPreferences.cpp b/Source/WebKitLegacy/win/WebPreferences.cpp >index 13948686bcfa140da9de9289c6ac4b46c40581da..c3485d559f29c08654a270de59a639f57ebe1d95 100644 >--- a/Source/WebKitLegacy/win/WebPreferences.cpp >+++ b/Source/WebKitLegacy/win/WebPreferences.cpp >@@ -333,6 +333,8 @@ void WebPreferences::initializeDefaultSettings() > > CFDictionaryAddValue(defaults, CFSTR(WebKitCoreMathMLEnabledPreferenceKey), kCFBooleanFalse); > >+ CFDictionaryAddValue(defaults, CFSTR(WebKitLazyImageLoadingEnabledPreferenceKey), kCFBooleanFalse); >+ > defaultSettings = defaults; > } > >@@ -2292,3 +2294,17 @@ HRESULT WebPreferences::setResizeObserverEnabled(BOOL enabled) > setBoolValue(WebKitResizeObserverEnabledPreferenceKey, enabled); > return S_OK; > } >+ >+HRESULT WebPreferences::lazyImageLoadingEnabled(_Out_ BOOL* enabled) >+{ >+ if (!enabled) >+ return E_POINTER; >+ *enabled = boolValueForKey(WebKitLazyImageLoadingEnabledPreferenceKey); >+ return S_OK; >+} >+ >+HRESULT WebPreferences::setLazyImageLoadingEnabled(BOOL enabled) >+{ >+ setBoolValue(WebKitLazyImageLoadingEnabledPreferenceKey, enabled); >+ return S_OK; >+} >diff --git a/Source/WebKitLegacy/win/WebPreferences.h b/Source/WebKitLegacy/win/WebPreferences.h >index 5ee6427b3532cd838c867296b4c3ace57b87f638..e1ad5cb8e2c8c69b819055e8f20e9cf123ff3749 100644 >--- a/Source/WebKitLegacy/win/WebPreferences.h >+++ b/Source/WebKitLegacy/win/WebPreferences.h >@@ -287,6 +287,8 @@ public: > virtual HRESULT STDMETHODCALLTYPE setResizeObserverEnabled(BOOL); > virtual HRESULT STDMETHODCALLTYPE coreMathMLEnabled(_Out_ BOOL*); > virtual HRESULT STDMETHODCALLTYPE setCoreMathMLEnabled(BOOL); >+ virtual HRESULT STDMETHODCALLTYPE lazyImageLoadingEnabled(_Out_ BOOL*); >+ virtual HRESULT STDMETHODCALLTYPE setLazyImageLoadingEnabled(BOOL); > > // WebPreferences > >diff --git a/Source/WebKitLegacy/win/WebView.cpp b/Source/WebKitLegacy/win/WebView.cpp >index a89acc000d5ee7b42e717c4e9f36d28cd5ca4a81..7cdf90805d9e1b271c49e556ae24dab40e2c0ba8 100644 >--- a/Source/WebKitLegacy/win/WebView.cpp >+++ b/Source/WebKitLegacy/win/WebView.cpp >@@ -5606,6 +5606,11 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification) > return hr; > settings.setCoreMathMLEnabled(!!enabled); > >+ hr = prefsPrivate->lazyImageLoadingEnabled(&enabled); >+ if (FAILED(hr)) >+ return hr; >+ RuntimeEnabledFeatures::sharedFeatures().setLazyImageLoadingEnabled(!!enabled); >+ > return S_OK; > } > >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 07732108afeed8f55cfb6fe20a303efb4b95662d..a664365d073d3bddc60595ac4038d4a15ae9779e 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,21 @@ >+2019-06-12 Rob Buis <rbuis@igalia.com> >+ >+ Support lazy image and iframe loading (loading="lazy") >+ https://bugs.webkit.org/show_bug.cgi?id=196698 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Set lazyImageLoading preference as part of experimental features. >+ >+ * DumpRenderTree/TestOptions.cpp: >+ (TestOptions::TestOptions): >+ * DumpRenderTree/TestOptions.h: >+ * DumpRenderTree/mac/DumpRenderTree.mm: >+ (enableExperimentalFeatures): >+ (setWebPreferencesForTestOptions): >+ * DumpRenderTree/win/DumpRenderTree.cpp: >+ (enableExperimentalFeatures): >+ > 2019-06-11 Keith Rollin <krollin@apple.com> > > Open up xcfilelist processing to more platforms >diff --git a/Tools/DumpRenderTree/TestOptions.cpp b/Tools/DumpRenderTree/TestOptions.cpp >index aaa5e72d4eb8990d58a17a107061cab3abe28a59..24623b1ade7aecb9286806bdea80e200de4a85f1 100644 >--- a/Tools/DumpRenderTree/TestOptions.cpp >+++ b/Tools/DumpRenderTree/TestOptions.cpp >@@ -117,6 +117,8 @@ TestOptions::TestOptions(const std::string& pathOrURL, const std::string& absolu > enableResizeObserver = parseBooleanTestHeaderValue(value); > else if (key == "experimental:CoreMathMLEnabled") > enableCoreMathML = parseBooleanTestHeaderValue(value); >+ else if (key == "experimental:LazyImageLoadingEnabled") >+ enableLazyImageLoading = parseBooleanTestHeaderValue(value); > pairStart = pairEnd + 1; > } > } >diff --git a/Tools/DumpRenderTree/TestOptions.h b/Tools/DumpRenderTree/TestOptions.h >index d16f758a366ae191edd0b9bfc41c8fe44d5c9acb..558aabad3767c0f662e984b69ed344a114850873 100644 >--- a/Tools/DumpRenderTree/TestOptions.h >+++ b/Tools/DumpRenderTree/TestOptions.h >@@ -48,6 +48,7 @@ struct TestOptions { > bool adClickAttributionEnabled { false }; > bool enableResizeObserver { false }; > bool enableCoreMathML { false }; >+ bool enableLazyImageLoading { false }; > std::string jscOptions; > std::string additionalSupportedImageTypes; > >diff --git a/Tools/DumpRenderTree/mac/DumpRenderTree.mm b/Tools/DumpRenderTree/mac/DumpRenderTree.mm >index 6660c32d9215a2c73717d9c336fbb780126eff5e..e2f65ff042239ea7832baf5756f06870f8738c19 100644 >--- a/Tools/DumpRenderTree/mac/DumpRenderTree.mm >+++ b/Tools/DumpRenderTree/mac/DumpRenderTree.mm >@@ -875,7 +875,7 @@ static void enableExperimentalFeatures(WebPreferences* preferences) > [preferences setCSSOMViewScrollingAPIEnabled:YES]; > [preferences setMediaRecorderEnabled:YES]; > [preferences setReferrerPolicyAttributeEnabled:YES]; >- [preferences setReferrerPolicyAttributeEnabled:YES]; >+ [preferences setLazyImageLoadingEnabled:YES]; > [preferences setLinkPreloadResponsiveImagesEnabled:YES]; > } > >@@ -1022,6 +1022,7 @@ static void setWebPreferencesForTestOptions(const TestOptions& options) > preferences.adClickAttributionEnabled = options.adClickAttributionEnabled; > preferences.resizeObserverEnabled = options.enableResizeObserver; > preferences.coreMathMLEnabled = options.enableCoreMathML; >+ preferences.lazyImageLoadingEnabled = options.enableLazyImageLoading; > } > > // Called once on DumpRenderTree startup. >diff --git a/Tools/DumpRenderTree/win/DumpRenderTree.cpp b/Tools/DumpRenderTree/win/DumpRenderTree.cpp >index 6d213859becfa4332fd61644a4da0332fbd37488..cd3c59c2035e4774110c2bad616c9d88cb2722fe 100644 >--- a/Tools/DumpRenderTree/win/DumpRenderTree.cpp >+++ b/Tools/DumpRenderTree/win/DumpRenderTree.cpp >@@ -793,6 +793,7 @@ static void enableExperimentalFeatures(IWebPreferences* preferences) > prefsPrivate->setResizeObserverEnabled(TRUE); > prefsPrivate->setWebAnimationsEnabled(TRUE); > prefsPrivate->setServerTimingEnabled(TRUE); >+ prefsPrivate->setLazyImageLoadingEnabled(TRUE); > // FIXME: WebGL2 > // FIXME: WebRTC > } >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 004c5671b3f5f4dc4190dbf8372dbd6f2bfc87e8..4d48257acdd51fbc8957537516e2862b60d9eee9 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,31 @@ >+2019-06-12 Rob Buis <rbuis@igalia.com> >+ >+ Support lazy image and iframe loading (loading="lazy") >+ https://bugs.webkit.org/show_bug.cgi?id=196698 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add lazyload tests. >+ >+ * http/tests/lazyload/attribute-expected.txt: Added. >+ * http/tests/lazyload/attribute.html: Added. >+ * http/tests/lazyload/fixed-dimension-expected.txt: Added. >+ * http/tests/lazyload/fixed-dimension.html: Added. >+ * http/tests/lazyload/js-image-expected.txt: Added. >+ * http/tests/lazyload/js-image.html: Added. >+ * http/tests/lazyload/lazy-expected.txt: Added. >+ * http/tests/lazyload/lazy.html: Added. >+ * http/tests/lazyload/placeholder.js: Added. >+ (is_image_fully_loaded): >+ * http/tests/lazyload/scroll-expected.txt: Added. >+ * http/tests/lazyload/scroll.html: Added. >+ * http/tests/lazyload/style-dimension-expected.txt: Added. >+ * http/tests/lazyload/style-dimension.html: Added. >+ * platform/ios-simulator-wk2/TestExpectations: >+ * platform/mac-wk1/TestExpectations: >+ * platform/win/TestExpectations: >+ * platform/wincairo-wk1/TestExpectations: >+ > 2019-06-11 Wenson Hsieh <wenson_hsieh@apple.com> > > [iOS] Idempotent text autosizing needs to react properly to viewport changes >diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog >index ddcfdb4edd0ce2080d38a71cb5129486ef3f9dee..e2f63687202fb262fd5f5447ac332cc83abfe28c 100644 >--- a/LayoutTests/imported/w3c/ChangeLog >+++ b/LayoutTests/imported/w3c/ChangeLog >@@ -1,3 +1,35 @@ >+2019-06-12 Rob Buis <rbuis@igalia.com> >+ >+ Support lazy image and iframe loading (loading="lazy") >+ https://bugs.webkit.org/show_bug.cgi?id=196698 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Import lazyload WPT tests. >+ >+ * web-platform-tests/loading/lazyload/attribute_off_image.tentative-expected.txt: Added. >+ * web-platform-tests/loading/lazyload/attribute_off_image.tentative.html: Added. >+ * web-platform-tests/loading/lazyload/change_attribute_to_off_image.tentative-expected.txt: Added. >+ * web-platform-tests/loading/lazyload/change_attribute_to_off_image.tentative.html: Added. >+ * web-platform-tests/loading/lazyload/resources/image_1.png: Added. >+ * web-platform-tests/loading/lazyload/resources/image_2.png: Added. >+ * web-platform-tests/loading/lazyload/resources/image_3.png: Added. >+ * web-platform-tests/loading/lazyload/resources/image_4.png: Added. >+ * web-platform-tests/loading/lazyload/resources/subframe_1.html: Added. >+ * web-platform-tests/loading/lazyload/resources/subframe_2.html: Added. >+ * web-platform-tests/loading/lazyload/resources/subframe_3.html: Added. >+ * web-platform-tests/loading/lazyload/resources/subframe_4.html: Added. >+ * web-platform-tests/loading/lazyload/scroll_to_attribute_auto_image.tentative-expected.txt: Added. >+ * web-platform-tests/loading/lazyload/scroll_to_attribute_auto_image.tentative.html: Added. >+ * web-platform-tests/loading/lazyload/scroll_to_attribute_invalid_image.tentative-expected.txt: Added. >+ * web-platform-tests/loading/lazyload/scroll_to_attribute_invalid_image.tentative.html: Added. >+ * web-platform-tests/loading/lazyload/scroll_to_attribute_on_image.tentative-expected.txt: Added. >+ * web-platform-tests/loading/lazyload/scroll_to_attribute_on_image.tentative.html: Added. >+ * web-platform-tests/loading/lazyload/scroll_to_attribute_unset_image.tentative-expected.txt: Added. >+ * web-platform-tests/loading/lazyload/scroll_to_attribute_unset_image.tentative.html: Added. >+ * web-platform-tests/loading/lazyload/window_load_event_occurs_with_below_viewport_image.tentative-expected.txt: Added. >+ * web-platform-tests/loading/lazyload/window_load_event_occurs_with_below_viewport_image.tentative.html: Added. >+ > 2019-06-11 Devin Rousso <drousso@apple.com> > > Sort the computed styles list >diff --git a/LayoutTests/http/tests/lazyload/attribute-expected.txt b/LayoutTests/http/tests/lazyload/attribute-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..318e403166ef3dc080077c92ceeace66918c345c >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/attribute-expected.txt >@@ -0,0 +1,15 @@ >+CONSOLE MESSAGE: line 2451: Error: assert_equals: expected (object) null but got (string) "eager" >+CONSOLE MESSAGE: line 2451: Error: assert_equals: expected "auto" but got "eager" >+CONSOLE MESSAGE: line 2451: Error: assert_equals: expected "invalid-value-default" but got "eager" >+ >+ >+Harness Error (FAIL), message = Error: assert_equals: expected "invalid-value-default" but got "eager" >+ >+PASS Test that document load event is fired >+PASS Test that <img> with loading=lazy or auto or no attribute or invalid value are loaded as a placeholder >+PASS Test that <img> with loading=eager is fully loaded, and not a placeholder >+PASS Test that <img> with no loading attribute is fully loaded, and not a placeholder >+PASS Test that <img> with loading=auto is fully loaded, and not a placeholder >+PASS Test that <img> with invalid loading attribute is fully loaded, and not a placeholder >+PASS Test that deferred <img> are fully loaded when lazyload is turned off >+ >diff --git a/LayoutTests/http/tests/lazyload/attribute.html b/LayoutTests/http/tests/lazyload/attribute.html >new file mode 100644 >index 0000000000000000000000000000000000000000..33a6abc47286c88eb5acc2c751fc923911d5f43a >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/attribute.html >@@ -0,0 +1,91 @@ >+<!DOCTYPE html><!-- webkit-test-runner [ experimental:LazyImageLoadingEnabled=true ] --> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<script src="placeholder.js"></script> >+ >+<body> >+ <div style="height:10000px;"></div> >+ <img id="no_attribute_img" src='../loading/resources/base-image1.png'> >+ <img loading="auto" id="auto_attribute_img" src='../loading/resources/base-image2.png'> >+ <img loading="invalid-value-default" id="invalid_attribute_img" src='../loading/resources/base-image3.png'> >+ <img loading="lazy" id="lazy_attribute_img" src='../loading/resources/dup-image1.png'> >+ <img loading="eager" id="eager_attribute_img" src='../loading/resources/dup-image2.png'> >+</body> >+ >+<script> >+ var no_attribute_img = document.getElementById("no_attribute_img"); >+ var auto_attribute_img = document.getElementById("auto_attribute_img"); >+ var invalid_attribute_img = document.getElementById("invalid_attribute_img"); >+ var lazy_attribute_img = document.getElementById("lazy_attribute_img"); >+ var eager_attribute_img = document.getElementById("eager_attribute_img"); >+ >+ async_test(function(t) { >+ window.addEventListener("load", t.step_func_done()); >+ }, "Test that document load event is fired"); >+ >+ async_test(function(t) { >+ window.addEventListener("load", t.step_func_done(function() { >+ assert_false(is_image_fully_loaded(lazy_attribute_img)); >+ assert_true(is_image_fully_loaded(no_attribute_img)); >+ })); >+ lazy_attribute_img.addEventListener("load", >+ t.unreached_func("Load event should not be fired for below viewport image with loading=lazy")); >+ }, "Test that <img> with loading=lazy or auto or no attribute or invalid value are loaded as a placeholder"); >+ >+ async_test(function(t) { >+ eager_attribute_img.addEventListener("load", >+ t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(eager_attribute_img)); >+ })); >+ }, "Test that <img> with loading=eager is fully loaded, and not a placeholder"); >+ >+ async_test(function(t) { >+ no_attribute_img.addEventListener("load", >+ t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(eager_attribute_img)); >+ })); >+ }, "Test that <img> with no loading attribute is fully loaded, and not a placeholder"); >+ >+ async_test(function(t) { >+ auto_attribute_img.addEventListener("load", >+ t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(eager_attribute_img)); >+ })); >+ }, "Test that <img> with loading=auto is fully loaded, and not a placeholder"); >+ >+ async_test(function(t) { >+ invalid_attribute_img.addEventListener("load", >+ t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(eager_attribute_img)); >+ })); >+ }, "Test that <img> with invalid loading attribute is fully loaded, and not a placeholder"); >+ >+ async_test(function(t) { >+ var complete = 0; >+ var onload_callback = function() { >+ if (++complete == 4) { >+ // The four images with loading=lazy,auto or default or invalid attribute are loaded. >+ assert_true(is_image_fully_loaded(no_attribute_img)); >+ assert_true(is_image_fully_loaded(lazy_attribute_img)); >+ assert_true(is_image_fully_loaded(auto_attribute_img)); >+ assert_true(is_image_fully_loaded(invalid_attribute_img)); >+ t.done(); >+ } >+ assert_equals("eager", this.getAttribute('loading')); >+ }; >+ no_attribute_img.addEventListener("load", onload_callback); >+ lazy_attribute_img.addEventListener("load", onload_callback); >+ auto_attribute_img.addEventListener("load", onload_callback); >+ invalid_attribute_img.addEventListener("load", onload_callback); >+ window.addEventListener("load", t.step_func(function() { >+ assert_equals(null, no_attribute_img.getAttribute('loading')); >+ assert_equals("lazy", lazy_attribute_img.getAttribute('loading')); >+ assert_equals("auto", auto_attribute_img.getAttribute('loading')); >+ assert_equals("invalid-value-default", invalid_attribute_img.getAttribute('loading')); >+ no_attribute_img.setAttribute('loading', 'eager'); >+ lazy_attribute_img.setAttribute('loading', 'eager'); >+ auto_attribute_img.setAttribute('loading', 'eager'); >+ invalid_attribute_img.setAttribute('loading', 'eager'); >+ })); >+ }, "Test that deferred <img> are fully loaded when lazyload is turned off"); >+</script> >diff --git a/LayoutTests/http/tests/lazyload/fixed-dimension-expected.txt b/LayoutTests/http/tests/lazyload/fixed-dimension-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..ed2172cc239f6a148d6075990cb6a5dfb77fcf02 >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/fixed-dimension-expected.txt >@@ -0,0 +1,6 @@ >+ >+ >+PASS Test that document load event is fired >+PASS Test that small <img> with fixed height and width is loaded, and not a placeholder >+PASS Test that <img> with non fixed height and width below the viewport is loaded as placeholder >+ >diff --git a/LayoutTests/http/tests/lazyload/fixed-dimension.html b/LayoutTests/http/tests/lazyload/fixed-dimension.html >new file mode 100644 >index 0000000000000000000000000000000000000000..543bb746dde935c5c1727f008db74e6df5cbe3b5 >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/fixed-dimension.html >@@ -0,0 +1,48 @@ >+<!DOCTYPE html> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<script src="placeholder.js"></script> >+ >+<body> >+ <div style="height:10000px;"></div> >+ <img id="fixed_dimension_img" src='../loading/resources/base-image1.png' width="10" height="10" loading="lazy"> >+ <img id="large_dimension_img" src='../loading/resources/base-image2.png' width="100" height="100" loading="lazy"> >+ <img id="percent_dimension_img" src='../loading/resources/base-image3.png' width="10%" height="10%" loading="lazy"> >+ <img id="fixed_width_only_img" src='../loading/resources/dup-image1.png' width="10" loading="lazy"> >+ <img id="fixed_height_only_img" src='../loading/resources/dup-image2.png' height="10" loading="lazy"> >+</body> >+ >+<script> >+ async_test(function(t) { >+ window.addEventListener("load", t.step_func_done()); >+ }, "Test that document load event is fired"); >+ >+ async_test(function(t) { >+ var fixed_dimension_img = document.getElementById("fixed_dimension_img"); >+ fixed_dimension_img.addEventListener("load", >+ t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(fixed_dimension_img)); >+ })); >+ }, "Test that small <img> with fixed height and width is loaded, and not a placeholder"); >+ >+ async_test(function(t) { >+ var large_dimension_img = document.getElementById("large_dimension_img"); >+ var percent_dimension_img = document.getElementById("percent_dimension_img"); >+ var fixed_width_only_img = document.getElementById("fixed_width_only_img"); >+ var fixed_height_only_img = document.getElementById("fixed_height_only_img"); >+ window.addEventListener("load", t.step_func_done(function() { >+ assert_false(is_image_fully_loaded(large_dimension_img)); >+ assert_false(is_image_fully_loaded(percent_dimension_img)); >+ assert_false(is_image_fully_loaded(fixed_width_only_img)); >+ assert_false(is_image_fully_loaded(fixed_height_only_img)); >+ })); >+ large_dimension_img.addEventListener("load", >+ t.unreached_func("Load event should not be fired for below viewport image with large fixed dimension")); >+ percent_dimension_img.addEventListener("load", >+ t.unreached_func("Load event should not be fired for below viewport image with percentage dimension")); >+ fixed_width_only_img.addEventListener("load", >+ t.unreached_func("Load event should not be fired for below viewport image with only fixed width")); >+ fixed_height_only_img.addEventListener("load", >+ t.unreached_func("Load event should not be fired for below viewport image with only fixed height")); >+ }, "Test that <img> with non fixed height and width below the viewport is loaded as placeholder"); >+</script> >diff --git a/LayoutTests/http/tests/lazyload/js-image-expected.txt b/LayoutTests/http/tests/lazyload/js-image-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..df61349d0157ba94b93a594fe44bc88cbe5d7fb8 >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/js-image-expected.txt >@@ -0,0 +1,5 @@ >+ >+ >+PASS Test that load event is fired for JS Image() fetches >+PASS Test that load event is fired for <img> created via JS and attached below viewport >+ >diff --git a/LayoutTests/http/tests/lazyload/js-image.html b/LayoutTests/http/tests/lazyload/js-image.html >new file mode 100644 >index 0000000000000000000000000000000000000000..7374dc6f312be88d4e64f8495f6ca0124561692e >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/js-image.html >@@ -0,0 +1,27 @@ >+<!DOCTYPE html><!-- webkit-test-runner [ experimental:LazyImageLoadingEnabled=true ] --> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<script src="placeholder.js"></script> >+ >+<body> >+ <div style="height:10000px;"></div> >+</body> >+ >+<script> >+ async_test(function(t) { >+ const img = new Image(); >+ img.onload = t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(img)); >+ }); >+ img.src = '../loading/resources/base-image1.png'; >+ }, "Test that load event is fired for JS Image() fetches"); >+ >+ async_test(function(t) { >+ const attached_img = document.createElement("IMG"); >+ document.body.appendChild(attached_img); >+ attached_img.onload = t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(attached_img)); >+ }); >+ attached_img.src = "../loading/resources/base-image2.png"; >+ }, "Test that load event is fired for <img> created via JS and attached below viewport"); >+</script> >diff --git a/LayoutTests/http/tests/lazyload/lazy-expected.txt b/LayoutTests/http/tests/lazyload/lazy-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..490a89baa026b37eab325927726444678394f45e >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/lazy-expected.txt >@@ -0,0 +1,7 @@ >+ >+ >+ >+PASS Test that document load event is fired >+PASS Test that <img> in viewport is loaded, and not a placeholder >+PASS Test that <img> below viewport is a placeholder, with lazyimage enabled >+ >diff --git a/LayoutTests/http/tests/lazyload/lazy.html b/LayoutTests/http/tests/lazyload/lazy.html >new file mode 100644 >index 0000000000000000000000000000000000000000..216861e3b62edd674f693060039f387603c1744a >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/lazy.html >@@ -0,0 +1,41 @@ >+<!DOCTYPE html><!-- webkit-test-runner [ experimental:LazyImageLoadingEnabled=true ] --> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<script src="placeholder.js"></script> >+ >+<body> >+ <img id="in_viewport" src='../loading/resources/base-image1.png' loading="lazy"> >+ <div style="height:10000px;"></div> >+ <img id="below_viewport" src='../loading/resources/base-image2.png' loading="lazy"> >+</body> >+ >+<script> >+ var in_viewport_element = document.getElementById("in_viewport"); >+ var below_viewport_element = document.getElementById("below_viewport"); >+ async_test(function(t) { >+ window.addEventListener("load", t.step_func_done()); >+ }, "Test that document load event is fired"); >+ >+ async_test(function(t) { >+ in_viewport_element.addEventListener("load", >+ t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(in_viewport_element)); >+ })); >+ }, "Test that <img> in viewport is loaded, and not a placeholder"); >+ >+ async_test(function(t) { >+ var complete = 0; >+ var onload_callback = function() { >+ if (++complete == 2) { >+ // Document and the above viewport image has loaded. >+ assert_false(is_image_fully_loaded(below_viewport_element)); >+ t.done(); >+ } >+ }; >+ window.addEventListener("load", t.step_func(onload_callback)); >+ in_viewport_element.addEventListener("load", >+ t.step_func(onload_callback)); >+ below_viewport_element.addEventListener("load", >+ t.unreached_func("Load event should not be fired for below viewport image")); >+ }, "Test that <img> below viewport is a placeholder, with lazyimage enabled"); >+</script> >diff --git a/LayoutTests/http/tests/lazyload/placeholder.js b/LayoutTests/http/tests/lazyload/placeholder.js >new file mode 100644 >index 0000000000000000000000000000000000000000..e3a2236bddbfe8761888bd1b8354897f6eb6f511 >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/placeholder.js >@@ -0,0 +1,16 @@ >+// Returns if the image is complete and fully loaded as a non-placeholder image. >+function is_image_fully_loaded(image) { >+ if (!image.complete) { >+ return false; >+ } >+ >+ let canvas = document.createElement('canvas'); >+ canvas.width = canvas.height = 1; >+ let canvasContext = canvas.getContext("2d"); >+ canvasContext.drawImage(image, 0, 0); >+ let data = canvasContext.getImageData(0, 0, canvas.width, canvas.height).data; >+ >+ // Fully loaded image should not be a placeholder which is drawn as a >+ // translucent gray rectangle in placeholder_image.cc >+ return data[0] != 0xd9 || data[1] != 0xd9 || data[2] != 0xd9; >+} >diff --git a/LayoutTests/http/tests/lazyload/scroll-expected.txt b/LayoutTests/http/tests/lazyload/scroll-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..88f97a64e3bbfd60551cd470c5b542337ffb0f11 >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/scroll-expected.txt >@@ -0,0 +1,7 @@ >+ >+ >+ >+PASS Test that document load event is fired >+PASS Test that <img> in viewport is loaded, and not a placeholder >+PASS Test that <img> below viewport is loaded when scrolled near, and not a placeholder >+ >diff --git a/LayoutTests/http/tests/lazyload/scroll.html b/LayoutTests/http/tests/lazyload/scroll.html >new file mode 100644 >index 0000000000000000000000000000000000000000..f29bc718ca8143fd3c7e412e97dcb5402a65ddf6 >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/scroll.html >@@ -0,0 +1,35 @@ >+<!DOCTYPE html><!-- webkit-test-runner [ experimental:LazyImageLoadingEnabled=true ] --> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<script src="placeholder.js"></script> >+ >+<body> >+ <img id="in_viewport" src='../loading/resources/base-image1.png'> >+ <div style="height:10000px;"></div> >+ <img id="below_viewport" src='../loading/resources/base-image2.png'> >+</body> >+ >+<script> >+ var in_viewport_element = document.getElementById("in_viewport"); >+ var below_viewport_element = document.getElementById("below_viewport"); >+ async_test(function(t) { >+ window.addEventListener("load", t.step_func_done()); >+ }, "Test that document load event is fired"); >+ >+ async_test(function(t) { >+ in_viewport_element.addEventListener("load", >+ t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(in_viewport_element)); >+ })); >+ }, "Test that <img> in viewport is loaded, and not a placeholder"); >+ >+ async_test(function(t) { >+ in_viewport_element.addEventListener("load", t.step_func(function() { >+ below_viewport_element.scrollIntoView(); >+ })); >+ below_viewport_element.addEventListener("load", >+ t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(below_viewport_element)); >+ })); >+ }, "Test that <img> below viewport is loaded when scrolled near, and not a placeholder"); >+</script> >diff --git a/LayoutTests/http/tests/lazyload/style-dimension-expected.txt b/LayoutTests/http/tests/lazyload/style-dimension-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..8662ca743ddaf7540f9e25f0a5660bb2d3a54b2f >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/style-dimension-expected.txt >@@ -0,0 +1,6 @@ >+ >+ >+PASS Test that document load event is fired >+PASS Test that small <img> with width and height mentioned in inline dimensions is not deferred by lazyload >+PASS Test that <img> with non small height or width below the viewport is loaded as placeholder >+ >diff --git a/LayoutTests/http/tests/lazyload/style-dimension.html b/LayoutTests/http/tests/lazyload/style-dimension.html >new file mode 100644 >index 0000000000000000000000000000000000000000..2a532c4d4c7ca95a76fd0db66609c79546ab0cf0 >--- /dev/null >+++ b/LayoutTests/http/tests/lazyload/style-dimension.html >@@ -0,0 +1,48 @@ >+<!DOCTYPE html><!-- webkit-test-runner [ experimental:LazyImageLoadingEnabled=true ] --> >+<script src="/resources/testharness.js"></script> >+<script src="/resources/testharnessreport.js"></script> >+<script src="placeholder.js"></script> >+ >+<body> >+ <div style="height:10000px;"></div> >+ <img id="small_dimension_img" style="height:1px; width:10px" src='../loading/resources/base-image1.png' loading="lazy"> >+ <img id="large_dimension_img" src='../loading/resources/base-image2.png' style="height:20px; width:20px" loading="lazy"> >+ <img id="height_only_img" src='../loading/resources/base-image3.png' style="height:1px;" loading='lazy'> >+ <img id="width_only_img" src='../loading/resources/dup-image1.png' style="width:1px;" loading='lazy'> >+ <img id="percent_dimension_img" src='../loading/resources/dup-image2.png' style="height:10%; width:10%" loading="lazy"> >+</body> >+ >+<script> >+ async_test(function(t) { >+ window.addEventListener("load", t.step_func_done()); >+ }, "Test that document load event is fired"); >+ >+ async_test(function(t) { >+ var small_dimension_img = document.getElementById("small_dimension_img"); >+ small_dimension_img.addEventListener("load", >+ t.step_func_done(function() { >+ assert_true(is_image_fully_loaded(small_dimension_img)); >+ })); >+ }, "Test that small <img> with width and height mentioned in inline dimensions is not deferred by lazyload "); >+ >+ async_test(function(t) { >+ var large_dimension_img = document.getElementById("large_dimension_img"); >+ var height_only_img = document.getElementById("height_only_img"); >+ var width_only_img = document.getElementById("width_only_img"); >+ var percent_dimension_img = document.getElementById("percent_dimension_img"); >+ window.addEventListener("load", t.step_func_done(function() { >+ assert_false(is_image_fully_loaded(large_dimension_img)); >+ assert_false(is_image_fully_loaded(height_only_img)); >+ assert_false(is_image_fully_loaded(width_only_img)); >+ assert_false(is_image_fully_loaded(percent_dimension_img)); >+ })); >+ large_dimension_img.addEventListener("load", >+ t.unreached_func("Load event should not be fired for below viewport image with large inline dimension")); >+ height_only_img.addEventListener("load", >+ t.unreached_func("Load event should not be fired for below viewport image with only inline height")); >+ width_only_img.addEventListener("load", >+ t.unreached_func("Load event should not be fired for below viewport image with only inline width")); >+ percent_dimension_img.addEventListener("load", >+ t.unreached_func("Load event should not be fired for below viewport image with percentage inline dimension")); >+ }, "Test that <img> with non small height or width below the viewport is loaded as placeholder"); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/attribute_off_image.tentative-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/attribute_off_image.tentative-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..8b291ee4127dc057e64420a390b28dd4b5639c15 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/attribute_off_image.tentative-expected.txt >@@ -0,0 +1,11 @@ >+main frame - didStartProvisionalLoadForFrame >+main frame - didCommitLoadForFrame >+main frame - didReceiveTitle: Loading images with loading="eager" >+main frame - didFinishDocumentLoadForFrame >+main frame - didHandleOnloadEventsForFrame >+main frame - didFinishLoadForFrame >+ >+ >+ >+PASS Test that both images load immediately and block the window's load event. >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/attribute_off_image.tentative.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/attribute_off_image.tentative.html >new file mode 100644 >index 0000000000000000000000000000000000000000..52e3ed592b90d3e5ce6d935707fabd9a7af9418a >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/attribute_off_image.tentative.html >@@ -0,0 +1,41 @@ >+<!DOCTYPE html> >+<head> >+ <title>Loading images with loading="eager"</title> >+ <link rel="author" title="Scott Little" href="mailto:sclittle@chromium.org"> >+ <link rel="help" href="https://github.com/whatwg/html/pull/3752"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+ >+<!-- >+Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed. >+--> >+ >+<body> >+ <img id="in_viewport" src="resources/image_1.png" loading="eager"> >+ <div style="height:10000px;"></div> >+ <img id="below_viewport" src="resources/image_2.png" loading="eager"> >+</body> >+ >+<script> >+ var t = async_test("Test that both images load immediately and block the window's load event."); >+ >+ var has_in_viewport_image_loaded = false; >+ document.getElementById("in_viewport").addEventListener("load", >+ t.step_func(function() { >+ assert_false(has_in_viewport_image_loaded); >+ has_in_viewport_image_loaded = true; >+ })); >+ >+ var has_below_viewport_image_loaded = false; >+ document.getElementById("below_viewport").addEventListener("load", >+ t.step_func(function() { >+ assert_false(has_below_viewport_image_loaded); >+ has_below_viewport_image_loaded = true; >+ })); >+ >+ window.addEventListener("load", t.step_func_done(function() { >+ assert_true(has_in_viewport_image_loaded); >+ assert_true(has_below_viewport_image_loaded); >+ })); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/change_attribute_to_off_image.tentative-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/change_attribute_to_off_image.tentative-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..85db797f03d03023c23d561e3c02caa037ab1d8c >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/change_attribute_to_off_image.tentative-expected.txt >@@ -0,0 +1,10 @@ >+main frame - didStartProvisionalLoadForFrame >+main frame - didCommitLoadForFrame >+main frame - didReceiveTitle: Images load immediately when load attribute is changed to "off" >+main frame - didFinishDocumentLoadForFrame >+main frame - didHandleOnloadEventsForFrame >+main frame - didFinishLoadForFrame >+ >+ >+PASS Test that a below viewport image that has its load attribute changed to off is loaded. >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/change_attribute_to_off_image.tentative.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/change_attribute_to_off_image.tentative.html >new file mode 100644 >index 0000000000000000000000000000000000000000..1ada34bc74ccc093d5ff014cc4132cfc67c71c95 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/change_attribute_to_off_image.tentative.html >@@ -0,0 +1,66 @@ >+<!DOCTYPE html> >+<head> >+ <title>Images load immediately when load attribute is changed to "off"</title> >+ <link rel="author" title="Scott Little" href="mailto:sclittle@chromium.org"> >+ <link rel="help" href="https://github.com/whatwg/html/pull/3752"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+ >+<!-- >+Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed. >+--> >+ >+<body> >+ <div style="height:10000px;"></div> >+ <img id="attribute_unset" src="resources/image_1.png"> >+ <img id="attribute_invalid" src="resources/image_2.png" load="invalid_value"> >+ <img id="attribute_auto" src="resources/image_3.png" load="auto"> >+ <img id="attribute_on" src="resources/image_4.png" load="lazy"> >+</body> >+ >+<script> >+ var t = async_test("Test that a below viewport image that has its load attribute changed to off is loaded."); >+ >+ var has_attribute_unset_loaded = false; >+ var has_attribute_invalid_loaded = false; >+ var has_attribute_auto_loaded = false; >+ var has_attribute_on_loaded = false; >+ >+ function checkIfDone() { >+ if (has_attribute_unset_loaded && >+ has_attribute_invalid_loaded && >+ has_attribute_auto_loaded && >+ has_attribute_on_loaded) { >+ t.done(); >+ } >+ } >+ >+ document.getElementById("attribute_unset").addEventListener("load", t.step_func(function() { >+ assert_false(has_attribute_unset_loaded); >+ has_attribute_unset_loaded = true; >+ checkIfDone(); >+ })); >+ document.getElementById("attribute_invalid").addEventListener("load", t.step_func(function() { >+ assert_false(has_attribute_invalid_loaded); >+ has_attribute_invalid_loaded = true; >+ checkIfDone(); >+ })); >+ document.getElementById("attribute_auto").addEventListener("load", t.step_func(function() { >+ assert_false(has_attribute_auto_loaded); >+ has_attribute_auto_loaded = true; >+ checkIfDone(); >+ })); >+ document.getElementById("attribute_on").addEventListener("load", t.step_func(function() { >+ assert_false(has_attribute_on_loaded); >+ has_attribute_on_loaded = true; >+ checkIfDone(); >+ })); >+ >+ window.addEventListener("load", t.step_func_done(function() { >+ document.getElementById("attribute_unset").setAttribute("load", "eager"); >+ document.getElementById("attribute_invalid").setAttribute("load", "eager"); >+ document.getElementById("attribute_auto").setAttribute("load", "eager"); >+ document.getElementById("attribute_on").setAttribute("load", "eager"); >+ })); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/image_1.png b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/image_1.png >new file mode 100644 >index 0000000000000000000000000000000000000000..b712825093805d1052b01047b1dbb102f0af8f0f >GIT binary patch >literal 11493 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 > >literal 0 >HcmV?d00001 > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/image_2.png b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/image_2.png >new file mode 100644 >index 0000000000000000000000000000000000000000..b712825093805d1052b01047b1dbb102f0af8f0f >GIT binary patch >literal 11493 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 > >literal 0 >HcmV?d00001 > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/image_3.png b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/image_3.png >new file mode 100644 >index 0000000000000000000000000000000000000000..b712825093805d1052b01047b1dbb102f0af8f0f >GIT binary patch >literal 11493 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 > >literal 0 >HcmV?d00001 > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/image_4.png b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/image_4.png >new file mode 100644 >index 0000000000000000000000000000000000000000..b712825093805d1052b01047b1dbb102f0af8f0f >GIT binary patch >literal 11493 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 > >literal 0 >HcmV?d00001 > >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_1.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_1.html >new file mode 100644 >index 0000000000000000000000000000000000000000..98c0cec670823a701e77bf93b608f2d2c338397e >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_1.html >@@ -0,0 +1,5 @@ >+<html> >+ <body> >+ <p>Subframe 1.</p> >+ </body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_2.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_2.html >new file mode 100644 >index 0000000000000000000000000000000000000000..47c3c711ef504570f75ff3d3f1c236df8282089e >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_2.html >@@ -0,0 +1,5 @@ >+<html> >+ <body> >+ <p>Subframe 2.</p> >+ </body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_3.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_3.html >new file mode 100644 >index 0000000000000000000000000000000000000000..9ab310578111274deec5319e50141076c69201ac >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_3.html >@@ -0,0 +1,5 @@ >+<html> >+ <body> >+ <p>Subframe 3.</p> >+ </body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_4.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_4.html >new file mode 100644 >index 0000000000000000000000000000000000000000..b1299fb4023ca49969e76896dbdd179b13d8bd3a >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/resources/subframe_4.html >@@ -0,0 +1,5 @@ >+<html> >+ <body> >+ <p>Subframe 4.</p> >+ </body> >+</html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_auto_image.tentative-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_auto_image.tentative-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..b37929d0b924cee988ca0844e74f34c87b731314 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_auto_image.tentative-expected.txt >@@ -0,0 +1,11 @@ >+main frame - didStartProvisionalLoadForFrame >+main frame - didCommitLoadForFrame >+main frame - didReceiveTitle: Images with loading="auto" load when in the viewport >+main frame - didFinishDocumentLoadForFrame >+main frame - didHandleOnloadEventsForFrame >+main frame - didFinishLoadForFrame >+ >+ >+ >+PASS Test that images with loading='auto' that enter the viewport get loaded. >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_auto_image.tentative.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_auto_image.tentative.html >new file mode 100644 >index 0000000000000000000000000000000000000000..44be9e9a3470358d4a7d66db706cd0fa1fba4f09 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_auto_image.tentative.html >@@ -0,0 +1,47 @@ >+<!DOCTYPE html> >+<head> >+ <title>Images with loading="auto" load when in the viewport</title> >+ <link rel="author" title="Scott Little" href="mailto:sclittle@chromium.org"> >+ <link rel="help" href="https://github.com/whatwg/html/pull/3752"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+ >+<!-- >+Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed. >+--> >+ >+<body> >+ <img id="in_viewport" src="resources/image_1.png" loading="auto"> >+ <div style="height:10000px;"></div> >+ <img id="below_viewport" src="resources/image_2.png" loading="auto"> >+</body> >+ >+<script> >+ var t = async_test("Test that images with loading='auto' that enter the viewport get loaded."); >+ >+ var has_in_viewport_loaded = false; >+ var has_below_viewport_loaded = false; >+ >+ document.getElementById("in_viewport").addEventListener("load", t.step_func(function() { >+ assert_false(has_in_viewport_loaded); >+ has_in_viewport_loaded = true; >+ if (has_below_viewport_loaded) { >+ // Note that the below_viewport element's load event could happen before >+ // the window.load event occurs, if the browser decides to load it >+ // immediately instead of lazily loading. This is valid behavior, so the >+ // test has passed if the below_viewport element has loaded. >+ t.done(); >+ } else { >+ document.getElementById("below_viewport").scrollIntoView(); >+ } >+ })); >+ >+ document.getElementById("below_viewport").addEventListener("load", t.step_func(function() { >+ assert_false(has_below_viewport_loaded); >+ has_below_viewport_loaded = true; >+ if (has_in_viewport_loaded) { >+ t.done(); >+ } >+ })); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_invalid_image.tentative-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_invalid_image.tentative-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..22d7fedef069d943bc0161ed59f1f2e6a868f35c >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_invalid_image.tentative-expected.txt >@@ -0,0 +1,11 @@ >+main frame - didStartProvisionalLoadForFrame >+main frame - didCommitLoadForFrame >+main frame - didReceiveTitle: Images with an invalid loading attribute load when in the viewport >+main frame - didFinishDocumentLoadForFrame >+main frame - didHandleOnloadEventsForFrame >+main frame - didFinishLoadForFrame >+ >+ >+ >+PASS Test that images with invalid loading attributes that enter the viewport get loaded. >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_invalid_image.tentative.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_invalid_image.tentative.html >new file mode 100644 >index 0000000000000000000000000000000000000000..dc730bd1d45960fa6e695028cc85f67ca614b23b >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_invalid_image.tentative.html >@@ -0,0 +1,47 @@ >+<!DOCTYPE html> >+<head> >+ <title>Images with an invalid loading attribute load when in the viewport</title> >+ <link rel="author" title="Scott Little" href="mailto:sclittle@chromium.org"> >+ <link rel="help" href="https://github.com/whatwg/html/pull/3752"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+ >+<!-- >+Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed. >+--> >+ >+<body> >+ <img id="in_viewport" src="resources/image_1.png" loading="invalid_value"> >+ <div style="height:10000px;"></div> >+ <img id="below_viewport" src="resources/image_2.png" loading="invalid_value"> >+</body> >+ >+<script> >+ var t = async_test("Test that images with invalid loading attributes that enter the viewport get loaded."); >+ >+ var has_in_viewport_loaded = false; >+ var has_below_viewport_loaded = false; >+ >+ document.getElementById("in_viewport").addEventListener("load", t.step_func(function() { >+ assert_false(has_in_viewport_loaded); >+ has_in_viewport_loaded = true; >+ if (has_below_viewport_loaded) { >+ // Note that the below_viewport element's load event could happen before >+ // the window.load event occurs, if the browser decides to load it >+ // immediately instead of lazily loading. This is valid behavior, so the >+ // test has passed if the below_viewport element has loaded. >+ t.done(); >+ } else { >+ document.getElementById("below_viewport").scrollIntoView(); >+ } >+ })); >+ >+ document.getElementById("below_viewport").addEventListener("load", t.step_func(function() { >+ assert_false(has_below_viewport_loaded); >+ has_below_viewport_loaded = true; >+ if (has_in_viewport_loaded) { >+ t.done(); >+ } >+ })); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_on_image.tentative-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_on_image.tentative-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..a0ae6bb5a81be4ababcbbb0a4c5a7ee187f4ce61 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_on_image.tentative-expected.txt >@@ -0,0 +1,11 @@ >+main frame - didStartProvisionalLoadForFrame >+main frame - didCommitLoadForFrame >+main frame - didReceiveTitle: Images with loading="lazy" load when in the viewport >+main frame - didFinishDocumentLoadForFrame >+main frame - didHandleOnloadEventsForFrame >+main frame - didFinishLoadForFrame >+ >+ >+ >+PASS Test that images with loading='lazy' that enter the viewport get loaded. >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_on_image.tentative.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_on_image.tentative.html >new file mode 100644 >index 0000000000000000000000000000000000000000..95f42b05e4f0ef2dc21c6f3239bc738307cab489 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_on_image.tentative.html >@@ -0,0 +1,47 @@ >+<!DOCTYPE html> >+<head> >+ <title>Images with loading="lazy" load when in the viewport</title> >+ <link rel="author" title="Scott Little" href="mailto:sclittle@chromium.org"> >+ <link rel="help" href="https://github.com/whatwg/html/pull/3752"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+ >+<!-- >+Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed. >+--> >+ >+<body> >+ <img id="in_viewport" src="resources/image_1.png" loading="lazy"> >+ <div style="height:10000px;"></div> >+ <img id="below_viewport" src="resources/image_2.png" loading="lazy"> >+</body> >+ >+<script> >+ var t = async_test("Test that images with loading='lazy' that enter the viewport get loaded."); >+ >+ var has_in_viewport_loaded = false; >+ var has_below_viewport_loaded = false; >+ >+ document.getElementById("in_viewport").addEventListener("load", t.step_func(function() { >+ assert_false(has_in_viewport_loaded); >+ has_in_viewport_loaded = true; >+ if (has_below_viewport_loaded) { >+ // Note that the below_viewport element's load event could happen before >+ // the window.load event occurs, if the browser decides to load it >+ // immediately instead of lazily loading. This is valid behavior, so the >+ // test has passed if the below_viewport element has loaded. >+ t.done(); >+ } else { >+ document.getElementById("below_viewport").scrollIntoView(); >+ } >+ })); >+ >+ document.getElementById("below_viewport").addEventListener("load", t.step_func(function() { >+ assert_false(has_below_viewport_loaded); >+ has_below_viewport_loaded = true; >+ if (has_in_viewport_loaded) { >+ t.done(); >+ } >+ })); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_unset_image.tentative-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_unset_image.tentative-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..7ed4dc2e6002aa88aca2c4c22cf029b1dcfa10bc >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_unset_image.tentative-expected.txt >@@ -0,0 +1,11 @@ >+main frame - didStartProvisionalLoadForFrame >+main frame - didCommitLoadForFrame >+main frame - didReceiveTitle: Images without a lazyload attribute load when in the viewport >+main frame - didFinishDocumentLoadForFrame >+main frame - didHandleOnloadEventsForFrame >+main frame - didFinishLoadForFrame >+ >+ >+ >+PASS Test that images without a lazyload attribute that enter the viewport get loaded. >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_unset_image.tentative.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_unset_image.tentative.html >new file mode 100644 >index 0000000000000000000000000000000000000000..5ac8a78d652766f60df84c754a71d789b1b689e8 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_unset_image.tentative.html >@@ -0,0 +1,47 @@ >+<!DOCTYPE html> >+<head> >+ <title>Images without a lazyload attribute load when in the viewport</title> >+ <link rel="author" title="Scott Little" href="mailto:sclittle@chromium.org"> >+ <link rel="help" href="https://github.com/whatwg/html/pull/3752"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+ >+<!-- >+Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed. >+--> >+ >+<body> >+ <img id="in_viewport" src="resources/image_1.png"> >+ <div style="height:10000px;"></div> >+ <img id="below_viewport" src="resources/image_2.png"> >+</body> >+ >+<script> >+ var t = async_test("Test that images without a lazyload attribute that enter the viewport get loaded."); >+ >+ var has_in_viewport_loaded = false; >+ var has_below_viewport_loaded = false; >+ >+ document.getElementById("in_viewport").addEventListener("load", t.step_func(function() { >+ assert_false(has_in_viewport_loaded); >+ has_in_viewport_loaded = true; >+ if (has_below_viewport_loaded) { >+ // Note that the below_viewport element's load event could happen before >+ // the window.load event occurs, if the browser decides to load it >+ // immediately instead of lazily loading. This is valid behavior, so the >+ // test has passed if the below_viewport element has loaded. >+ t.done(); >+ } else { >+ document.getElementById("below_viewport").scrollIntoView(); >+ } >+ })); >+ >+ document.getElementById("below_viewport").addEventListener("load", t.step_func(function() { >+ assert_false(has_below_viewport_loaded); >+ has_below_viewport_loaded = true; >+ if (has_in_viewport_loaded) { >+ t.done(); >+ } >+ })); >+</script> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/window_load_event_occurs_with_below_viewport_image.tentative-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/window_load_event_occurs_with_below_viewport_image.tentative-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..9c98f198c9f83f4eba4fd55ccc0ad76e7524abdb >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/window_load_event_occurs_with_below_viewport_image.tentative-expected.txt >@@ -0,0 +1,10 @@ >+main frame - didStartProvisionalLoadForFrame >+main frame - didCommitLoadForFrame >+main frame - didReceiveTitle: Below-viewport images don't endlessly delay the window load event. >+main frame - didFinishDocumentLoadForFrame >+main frame - didHandleOnloadEventsForFrame >+main frame - didFinishLoadForFrame >+ >+ >+PASS Test that below-viewport images don't endlessly delay the window load event. >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/window_load_event_occurs_with_below_viewport_image.tentative.html b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/window_load_event_occurs_with_below_viewport_image.tentative.html >new file mode 100644 >index 0000000000000000000000000000000000000000..d56485e04a07f6eb9fb0a230988811b3be1fd408 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/loading/lazyload/window_load_event_occurs_with_below_viewport_image.tentative.html >@@ -0,0 +1,34 @@ >+<!DOCTYPE html> >+<head> >+ <title>Below-viewport images don't endlessly delay the window load event.</title> >+ <link rel="author" title="Scott Little" href="mailto:sclittle@chromium.org"> >+ <link rel="help" href="https://github.com/whatwg/html/pull/3752"> >+ <script src="/resources/testharness.js"></script> >+ <script src="/resources/testharnessreport.js"></script> >+</head> >+ >+<!-- >+Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed. >+--> >+ >+<body> >+ <div style="height:10000px;"></div> >+ <img id="attribute_unset" src="resources/image_1.png"> >+ <img id="attribute_invalid" src="resources/image_2.png" loading="invalid_value"> >+ <img id="attribute_auto" src="resources/image_3.png" loading="auto"> >+ <img id="attribute_on" src="resources/image_4.png" loading="lazy"> >+</body> >+ >+<script> >+ var t = async_test("Test that below-viewport images don't endlessly delay the window load event."); >+ >+ // Note that the below-viewport elements' load events could happen before the >+ // window.load event occurs, if the browser decides to load immediately >+ // instead of lazily loading. This is valid behavior, since loading="lazy" is >+ // only a strong hint to the browser that the element is well suited to being >+ // lazily loaded, so the browser is not required to lazily load it. The unset, >+ // invalid, and "auto" attribute values similarly leave it up to the browser >+ // to decide whether or not to lazily load the element. As a result, the test >+ // passes once the below-viewport elements load. >+ window.addEventListener("load", t.step_func_done()); >+</script> >diff --git a/LayoutTests/platform/ios-simulator-wk2/TestExpectations b/LayoutTests/platform/ios-simulator-wk2/TestExpectations >index a6141b75ea7170d13b1f1bf5ef033cbeabe0f17f..4e6834ad6d9c61ecd4a814e02dadb0e390f613fe 100644 >--- a/LayoutTests/platform/ios-simulator-wk2/TestExpectations >+++ b/LayoutTests/platform/ios-simulator-wk2/TestExpectations >@@ -90,4 +90,6 @@ webkit.org/b/182849 imported/w3c/web-platform-tests/xhr/event-upload-progress-cr > > imported/w3c/web-platform-tests/IndexedDB/keypath-special-identifiers.htm [ Slow ] > >-webkit.org/b/198185 http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration.html [ Skip ] >\ No newline at end of file >+webkit.org/b/198185 http/tests/resourceLoadStatistics/website-data-removal-for-site-navigated-to-with-link-decoration.html [ Skip ] >+ >+webkit.org/b/196698 http/tests/lazyload/attribute.html [ Skip ] >diff --git a/LayoutTests/platform/mac-wk1/TestExpectations b/LayoutTests/platform/mac-wk1/TestExpectations >index af247e89ed9b1529e578a1364eca641352b9f9bf..45b99f64b451915b688c3d39122d0d58c5896462 100644 >--- a/LayoutTests/platform/mac-wk1/TestExpectations >+++ b/LayoutTests/platform/mac-wk1/TestExpectations >@@ -723,4 +723,7 @@ webkit.org/b/198177 pointerevents/mouse/compatibility-mouse-events-prevention-mo > webkit.org/b/198459 [ HighSierra Debug ] inspector/canvas/recording-2d-full.html [ Slow ] > webkit.org/b/198459 [ HighSierra Debug ] inspector/canvas/recording-webgl-full.html [ Slow ] > >-webkit.org/b/196508 compositing/repaint/scroller-with-foreground-layer-repaints.html [ Pass Failure ] >\ No newline at end of file >+webkit.org/b/196508 compositing/repaint/scroller-with-foreground-layer-repaints.html [ Pass Failure ] >+ >+webkit.org/b/196698 http/tests/lazyload/lazy.html [ Skip ] >+webkit.org/b/196698 imported/w3c/web-platform-tests/loading/lazyload/scroll_to_attribute_on_image.tentative.html [ Skip ] >diff --git a/LayoutTests/platform/win/TestExpectations b/LayoutTests/platform/win/TestExpectations >index 720ca6927a9f7c24a07e88c6ddf4e93e7ebdbc2c..0cdb317dfa66cad9f5c945edde6202607a424d07 100644 >--- a/LayoutTests/platform/win/TestExpectations >+++ b/LayoutTests/platform/win/TestExpectations >@@ -4409,3 +4409,5 @@ webkit.org/b/195623 http/tests/cache/link-prefetch-main-resource-iframe.html [ S > webkit.org/b/198112 http/tests/security/showModalDialog-sync-cross-origin-page-load2.html [ Skip ] > > webkit.org/b/198679 fast/events/fire-mousedown-while-pressing-mouse-button.html [ Failure ] >+ >+webkit.org/b/196698 http/tests/lazyload/lazy.html [ Skip ] >diff --git a/LayoutTests/platform/wincairo-wk1/TestExpectations b/LayoutTests/platform/wincairo-wk1/TestExpectations >index 9a53fb8751dfca3b30e103f1e584e5464f3e7eb0..c8ecb8fdc663d4bf59173e86425dfdc813e3f7b8 100644 >--- a/LayoutTests/platform/wincairo-wk1/TestExpectations >+++ b/LayoutTests/platform/wincairo-wk1/TestExpectations >@@ -339,3 +339,4 @@ fast/css/transition-color-unspecified.html [ Skip ] > fast/filter-image/filter-image-animation.html [ Skip ] > resize-observer/modify-frametree-in-callback.html [ Skip ] > resize-observer/multi-frames.html [ Skip ] >+http/tests/lazyload/lazy.html [ Skip ]
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 196698
:
367803
|
367818
|
367871
|
367889
|
367907
|
367908
|
367909
|
367913
|
367938
|
368017
|
368018
|
368020
|
368023
|
368034
|
368038
|
368042
|
368051
|
368059
|
368067
|
368084
|
368103
|
368109
|
368239
|
368244
|
368248
|
368250
|
368252
|
368270
|
368394
|
368396
|
368397
|
368398
|
368399
|
368651
|
368652
|
368653
|
368654
|
368656
|
368657
|
368659
|
368661
|
368663
|
368665
|
368666
|
368673
|
371939
|
371941
|
371951
|
371967
|
371972
|
371974
|
371978
|
371979
|
371980
|
372030
|
372041
|
372050
|
376011
|
376015
|
376033
|
376034
|
376035
|
376036
|
376039
|
376040
|
376158
|
376167
|
376176
|
376180
|
376246
|
376259