Title: [230788] trunk
Revision
230788
Author
d...@apple.com
Date
2018-04-18 15:13:50 -0700 (Wed, 18 Apr 2018)

Log Message

Detect system preview links
https://bugs.webkit.org/show_bug.cgi?id=184753
<rdar://problem/39500514>

Reviewed by Antoine Quint.

Source/WebCore:

Detect a special type of link anchor, which we're calling System Previews.
Ultimately this will allow WebKit to present such links in a special
way.

A System Preview link is an <a> element, with a rel attribute that
includes "system-preview". It has a single element child, which is
either an <img> or a <picture>.

Test: system-preview/detection.html

* html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::relList): Add braces.
(WebCore::HTMLAnchorElement::isSystemPreviewLink const): New
function.
* html/HTMLAnchorElement.h:

* html/HTMLImageElement.cpp:
(WebCore::HTMLImageElement::isSystemPreviewImage const): Ask the
parent if it is a system preview link.
* html/HTMLImageElement.h:
* html/HTMLPictureElement.cpp:
(WebCore::HTMLPictureElement::isSystemPreviewImage const): Ditto.
* html/HTMLPictureElement.h:

* testing/Internals.cpp: Testing helpers.
(WebCore::Internals::systemPreviewRelType):
(WebCore::Internals::isSystemPreviewLink const):
(WebCore::Internals::isSystemPreviewImage const):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

* system-preview/detection-expected.txt: Added.
* system-preview/detection.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (230787 => 230788)


--- trunk/LayoutTests/ChangeLog	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/LayoutTests/ChangeLog	2018-04-18 22:13:50 UTC (rev 230788)
@@ -1,3 +1,14 @@
+2018-04-18  Dean Jackson  <d...@apple.com>
+
+        Detect system preview links
+        https://bugs.webkit.org/show_bug.cgi?id=184753
+        <rdar://problem/39500514>
+
+        Reviewed by Antoine Quint.
+
+        * system-preview/detection-expected.txt: Added.
+        * system-preview/detection.html: Added.
+
 2018-04-18  Ryan Haddad  <ryanhad...@apple.com>
 
         Skip animations/missing-from-to.html on mac-wk1 debug.

Added: trunk/LayoutTests/system-preview/detection-expected.txt (0 => 230788)


--- trunk/LayoutTests/system-preview/detection-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/system-preview/detection-expected.txt	2018-04-18 22:13:50 UTC (rev 230788)
@@ -0,0 +1,39 @@
+This test only works in WKTR or DRT.
+
+Valid system preview
+
+ 
+Result: Link element present. Identified as system preview. Child 0 is an image inside a system preview.
+
+Valid system preview (multiple rel values)
+
+ 
+Result: Link element present. Identified as system preview. Child 0 is an image inside a system preview.
+
+Valid system preview (picture child)
+
+Result: Link element present. Identified as system preview. Child 0 is an image inside a system preview.
+
+Invalid system preview (wrong rel value)
+
+ 
+Result: Link element present. Not identified as system preview. Child 0 is not an image inside a system preview.
+
+Invalid system preview (wrong children)
+
+hello
+Result: Link element present. Not identified as system preview. Child 0 is not an image inside a system preview.
+
+Invalid system preview (too many children)
+
+hello  
+Result: Link element present. Not identified as system preview. Child 0 is not an image inside a system preview. Child 1 is not an image inside a system preview.
+
+Invalid system preview (no children)
+
+Result: Link element present. Not identified as system preview.
+
+Invalid system preview (just an image)
+
+
+Result: No link. Child is not an image inside a system preview.
Property changes on: trunk/LayoutTests/system-preview/detection-expected.txt
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: svn:keywords

+Date Revision \ No newline at end of property

Added: svn:mime-type

+text/plain \ No newline at end of property

Added: trunk/LayoutTests/system-preview/detection.html (0 => 230788)


--- trunk/LayoutTests/system-preview/detection.html	                        (rev 0)
+++ trunk/LayoutTests/system-preview/detection.html	2018-04-18 22:13:50 UTC (rev 230788)
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner)
+    window.testRunner.dumpAsText();
+
+function getSystemPreviewData(id)
+{
+    const container = document.getElementById(id);
+    const link = container.querySelector("a");
+    let children = [];
+    if (link)
+        children = link.children;
+    const result = container.querySelectorAll("p")[1];
+    return [link, children, result];
+}
+
+function addResult(resultElement, txt)
+{
+    resultElement.textContent += txt;
+}
+
+const TESTS = ["valid-1", "valid-2", "valid-3", "invalid-1", "invalid-2", "invalid-3", "invalid-4", "invalid-5"];
+
+window.addEventListener("load", () => {
+    if (!window.internals)
+        return;
+
+    const relValue = internals.systemPreviewRelType();
+    TESTS.forEach(id => {
+        const [link, children, result] = getSystemPreviewData(id);
+        if (link) {
+            addResult(result, "Link element present.");
+
+            if (id != "invalid-1")
+                link.rel += " " + relValue;
+
+            if (internals.isSystemPreviewLink(link))
+                addResult(result, " Identified as system preview.");
+            else
+                addResult(result, " Not identified as system preview.");
+
+        } else
+            addResult(result, "No link.");
+
+        if (children && children.length > 0) {
+            for (let i = 0; i < children.length; i++) {
+                if (internals.isSystemPreviewImage(children[i]))
+                    addResult(result, ` Child ${i} is an image inside a system preview.`);
+                else
+                    addResult(result, ` Child ${i} is not an image inside a system preview.`);
+            }
+        }
+
+        // Specific test for the case that is just an image.
+        if (id == "invalid-5") {
+            const child = document.getElementById(id).children[0];
+            if (internals.isSystemPreviewImage(child))
+                addResult(result, ` Child is an image inside a system preview.`);
+            else
+                addResult(result, ` Child is not an image inside a system preview.`);
+        }
+    });
+}, false);
+</script>
+<p>This test only works in WKTR or DRT.</p>
+<div id="valid-1">
+<p>Valid system preview</p>
+<a href="" rel="">
+    <img>
+</a>
+<p>Result: </p>
+</div>
+
+<div id="valid-2">
+<p>Valid system preview (multiple rel values)</p>
+<a href="" rel="foo">
+    <img>
+</a>
+<p>Result: </p>
+</div>
+
+<div id="valid-3">
+<p>Valid system preview (picture child)</p>
+<a href="" rel="">
+    <picture></picture>
+</a>
+<p>Result: </p>
+</div>
+
+<div id="invalid-1">
+<p>Invalid system preview (wrong rel value)</p>
+<a href="" rel="">
+    <img>
+</a>
+<p>Result: </p>
+</div>
+
+<div id="invalid-2">
+<p>Invalid system preview (wrong children)</p>
+<a href="" rel="">
+    <span>hello</span>
+</a>
+<p>Result: </p>
+</div>
+
+<div id="invalid-3">
+<p>Invalid system preview (too many children)</p>
+<a href="" rel="">
+    <span>hello</span>
+    <img>
+</a>
+<p>Result: </p>
+</div>
+
+<div id="invalid-4">
+<p>Invalid system preview (no children)</p>
+<a href="" rel="">
+</a>
+<p>Result: </p>
+</div>
+
+<div id="invalid-5">
+<p>Invalid system preview (just an image)</p>
+<img>
+<p>Result: </p>
+</div>
Property changes on: trunk/LayoutTests/system-preview/detection.html
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: svn:keywords

+Date Revision \ No newline at end of property

Added: svn:mime-type

+text/html \ No newline at end of property

Modified: trunk/Source/WebCore/ChangeLog (230787 => 230788)


--- trunk/Source/WebCore/ChangeLog	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/Source/WebCore/ChangeLog	2018-04-18 22:13:50 UTC (rev 230788)
@@ -1,3 +1,42 @@
+2018-04-18  Dean Jackson  <d...@apple.com>
+
+        Detect system preview links
+        https://bugs.webkit.org/show_bug.cgi?id=184753
+        <rdar://problem/39500514>
+
+        Reviewed by Antoine Quint.
+
+        Detect a special type of link anchor, which we're calling System Previews.
+        Ultimately this will allow WebKit to present such links in a special
+        way.
+
+        A System Preview link is an <a> element, with a rel attribute that
+        includes "system-preview". It has a single element child, which is
+        either an <img> or a <picture>.
+
+        Test: system-preview/detection.html
+
+        * html/HTMLAnchorElement.cpp:
+        (WebCore::HTMLAnchorElement::relList): Add braces.
+        (WebCore::HTMLAnchorElement::isSystemPreviewLink const): New
+        function.
+        * html/HTMLAnchorElement.h:
+
+        * html/HTMLImageElement.cpp:
+        (WebCore::HTMLImageElement::isSystemPreviewImage const): Ask the
+        parent if it is a system preview link.
+        * html/HTMLImageElement.h:
+        * html/HTMLPictureElement.cpp:
+        (WebCore::HTMLPictureElement::isSystemPreviewImage const): Ditto.
+        * html/HTMLPictureElement.h:
+
+        * testing/Internals.cpp: Testing helpers.
+        (WebCore::Internals::systemPreviewRelType):
+        (WebCore::Internals::isSystemPreviewLink const):
+        (WebCore::Internals::isSystemPreviewImage const):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2018-04-18  Antti Koivisto  <an...@apple.com>
 
         :active pseudo class doesn't deactivate when using pressure sensitive trackpad

Modified: trunk/Source/WebCore/html/HTMLAnchorElement.cpp (230787 => 230788)


--- trunk/Source/WebCore/html/HTMLAnchorElement.cpp	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/Source/WebCore/html/HTMLAnchorElement.cpp	2018-04-18 22:13:50 UTC (rev 230788)
@@ -36,6 +36,7 @@
 #include "HTMLCanvasElement.h"
 #include "HTMLImageElement.h"
 #include "HTMLParserIdioms.h"
+#include "HTMLPictureElement.h"
 #include "KeyboardEvent.h"
 #include "MouseEvent.h"
 #include "PingLoader.h"
@@ -52,6 +53,10 @@
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/text/StringBuilder.h>
 
+#if USE(APPLE_INTERNAL_SDK)
+#import <WebKitAdditions/SystemPreviewDetection.cpp>
+#endif
+
 namespace WebCore {
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLAnchorElement);
@@ -304,12 +309,13 @@
     return m_linkRelations.contains(relation);
 }
 
-DOMTokenList& HTMLAnchorElement::relList()
+DOMTokenList& HTMLAnchorElement::relList() const
 {
-    if (!m_relList) 
-        m_relList = std::make_unique<DOMTokenList>(*this, HTMLNames::relAttr, [](Document&, StringView token) {
+    if (!m_relList) {
+        m_relList = std::make_unique<DOMTokenList>(const_cast<HTMLAnchorElement&>(*this), HTMLNames::relAttr, [](Document&, StringView token) {
             return equalIgnoringASCIICase(token, "noreferrer") || equalIgnoringASCIICase(token, "noopener");
         });
+    }
     return *m_relList;
 }
 
@@ -362,6 +368,30 @@
         PingLoader::sendPing(*document().frame(), document().completeURL(pingURLs[i]), destinationURL);
 }
 
+bool HTMLAnchorElement::isSystemPreviewLink() const
+{
+#if USE(APPLE_INTERNAL_SDK)
+    auto systemPreviewRelValue = getSystemPreviewRelValue();
+#else
+    auto systemPreviewRelValue = String { ASCIILiteral("system-preview") };
+#endif
+
+    // The relList is created on demand, which means that calling relList()
+    // is only available in a non-const method.
+    if (!relList().contains(systemPreviewRelValue))
+        return false;
+
+    if (auto* child = firstElementChild()) {
+        if (is<HTMLImageElement>(child) || is<HTMLPictureElement>(child)) {
+            auto numChildren = childElementCount();
+            // FIXME: Should only be 1.
+            return numChildren == 1 || numChildren == 2;
+        }
+    }
+
+    return false;
+}
+
 void HTMLAnchorElement::handleClick(Event& event)
 {
     event.setDefaultHandled();

Modified: trunk/Source/WebCore/html/HTMLAnchorElement.h (230787 => 230788)


--- trunk/Source/WebCore/html/HTMLAnchorElement.h	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/Source/WebCore/html/HTMLAnchorElement.h	2018-04-18 22:13:50 UTC (rev 230788)
@@ -66,8 +66,10 @@
     SharedStringHash visitedLinkHash() const;
     void invalidateCachedVisitedLinkHash() { m_cachedVisitedLinkHash = 0; }
 
-    WEBCORE_EXPORT DOMTokenList& relList();
+    WEBCORE_EXPORT DOMTokenList& relList() const;
 
+    WEBCORE_EXPORT bool isSystemPreviewLink() const;
+
 protected:
     HTMLAnchorElement(const QualifiedName&, Document&);
 
@@ -107,7 +109,7 @@
     OptionSet<Relation> m_linkRelations;
     mutable SharedStringHash m_cachedVisitedLinkHash;
 
-    std::unique_ptr<DOMTokenList> m_relList;
+    mutable std::unique_ptr<DOMTokenList> m_relList;
 };
 
 inline SharedStringHash HTMLAnchorElement::visitedLinkHash() const

Modified: trunk/Source/WebCore/html/HTMLImageElement.cpp (230787 => 230788)


--- trunk/Source/WebCore/html/HTMLImageElement.cpp	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/Source/WebCore/html/HTMLImageElement.cpp	2018-04-18 22:13:50 UTC (rev 230788)
@@ -27,6 +27,7 @@
 #include "CSSValueKeywords.h"
 #include "CachedImage.h"
 #include "FrameView.h"
+#include "HTMLAnchorElement.h"
 #include "HTMLDocument.h"
 #include "HTMLFormElement.h"
 #include "HTMLParserIdioms.h"
@@ -676,4 +677,12 @@
 }
 #endif
 
+bool HTMLImageElement::isSystemPreviewImage() const
+{
+    const auto* parent = parentElement();
+    if (!is<HTMLAnchorElement>(parent))
+        return false;
+    return downcast<HTMLAnchorElement>(parent)->isSystemPreviewLink();
 }
+
+}

Modified: trunk/Source/WebCore/html/HTMLImageElement.h (230787 => 230788)


--- trunk/Source/WebCore/html/HTMLImageElement.h	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/Source/WebCore/html/HTMLImageElement.h	2018-04-18 22:13:50 UTC (rev 230788)
@@ -100,6 +100,8 @@
     HTMLPictureElement* pictureElement() const;
     void setPictureElement(HTMLPictureElement*);
 
+    WEBCORE_EXPORT bool isSystemPreviewImage() const;
+
 protected:
     HTMLImageElement(const QualifiedName&, Document&, HTMLFormElement* = 0);
 

Modified: trunk/Source/WebCore/html/HTMLPictureElement.cpp (230787 => 230788)


--- trunk/Source/WebCore/html/HTMLPictureElement.cpp	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/Source/WebCore/html/HTMLPictureElement.cpp	2018-04-18 22:13:50 UTC (rev 230788)
@@ -27,6 +27,7 @@
 #include "HTMLPictureElement.h"
 
 #include "ElementChildIterator.h"
+#include "HTMLAnchorElement.h"
 #include "HTMLImageElement.h"
 #include "Logging.h"
 #include <wtf/IsoMallocInlines.h>
@@ -75,5 +76,13 @@
     return false;
 }
 
+bool HTMLPictureElement::isSystemPreviewImage() const
+{
+    const auto* parent = parentElement();
+    if (!is<HTMLAnchorElement>(parent))
+        return false;
+    return downcast<HTMLAnchorElement>(parent)->isSystemPreviewLink();
 }
 
+}
+

Modified: trunk/Source/WebCore/html/HTMLPictureElement.h (230787 => 230788)


--- trunk/Source/WebCore/html/HTMLPictureElement.h	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/Source/WebCore/html/HTMLPictureElement.h	2018-04-18 22:13:50 UTC (rev 230788)
@@ -46,6 +46,8 @@
 
     WeakPtr<HTMLPictureElement> createWeakPtr() { return m_weakFactory.createWeakPtr(*this); }
 
+    WEBCORE_EXPORT bool isSystemPreviewImage() const;
+
 private:
     HTMLPictureElement(const QualifiedName&, Document&);
 

Modified: trunk/Source/WebCore/testing/Internals.cpp (230787 => 230788)


--- trunk/Source/WebCore/testing/Internals.cpp	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/Source/WebCore/testing/Internals.cpp	2018-04-18 22:13:50 UTC (rev 230788)
@@ -72,6 +72,7 @@
 #include "FrameView.h"
 #include "GCObservation.h"
 #include "GridPosition.h"
+#include "HTMLAnchorElement.h"
 #include "HTMLCanvasElement.h"
 #include "HTMLIFrameElement.h"
 #include "HTMLImageElement.h"
@@ -78,6 +79,7 @@
 #include "HTMLInputElement.h"
 #include "HTMLLinkElement.h"
 #include "HTMLNames.h"
+#include "HTMLPictureElement.h"
 #include "HTMLPlugInElement.h"
 #include "HTMLPreloadScanner.h"
 #include "HTMLSelectElement.h"
@@ -262,6 +264,10 @@
 #include "MockCredentialsMessenger.h"
 #endif
 
+#if USE(APPLE_INTERNAL_SDK)
+#import <WebKitAdditions/SystemPreviewDetection.cpp>
+#endif
+
 using JSC::CallData;
 using JSC::CallType;
 using JSC::CodeBlock;
@@ -4464,4 +4470,27 @@
 }
 #endif
 
+String Internals::systemPreviewRelType()
+{
+#if USE(APPLE_INTERNAL_SDK)
+    return getSystemPreviewRelValue();
+#else
+    return ASCIILiteral("system-preview");
+#endif
+}
+
+bool Internals::isSystemPreviewLink(Element& element) const
+{
+    return is<HTMLAnchorElement>(element) && downcast<HTMLAnchorElement>(element).isSystemPreviewLink();
+}
+
+bool Internals::isSystemPreviewImage(Element& element) const
+{
+    if (is<HTMLImageElement>(element))
+        return downcast<HTMLImageElement>(element).isSystemPreviewImage();
+    if (is<HTMLPictureElement>(element))
+        return downcast<HTMLPictureElement>(element).isSystemPreviewImage();
+    return false;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/testing/Internals.h (230787 => 230788)


--- trunk/Source/WebCore/testing/Internals.h	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/Source/WebCore/testing/Internals.h	2018-04-18 22:13:50 UTC (rev 230788)
@@ -56,10 +56,12 @@
 class File;
 class Frame;
 class GCObservation;
+class HTMLAnchorElement;
 class HTMLImageElement;
 class HTMLInputElement;
 class HTMLLinkElement;
 class HTMLMediaElement;
+class HTMLPictureElement;
 class HTMLSelectElement;
 class ImageData;
 class InspectorStubFrontend;
@@ -655,6 +657,10 @@
     MockCredentialsMessenger& mockCredentialsMessenger() const;
 #endif
 
+    String systemPreviewRelType();
+    bool isSystemPreviewLink(Element&) const;
+    bool isSystemPreviewImage(Element&) const;
+
 private:
     explicit Internals(Document&);
     Document* contextDocument() const;

Modified: trunk/Source/WebCore/testing/Internals.idl (230787 => 230788)


--- trunk/Source/WebCore/testing/Internals.idl	2018-04-18 22:03:44 UTC (rev 230787)
+++ trunk/Source/WebCore/testing/Internals.idl	2018-04-18 22:13:50 UTC (rev 230788)
@@ -588,4 +588,8 @@
     [EnabledAtRuntime=WebAnimations] void setTimelineCurrentTime(AnimationTimeline timeline, double currentTime);
     [Conditional=APPLE_PAY] readonly attribute MockPaymentCoordinator mockPaymentCoordinator;
     [Conditional=WEB_AUTHN] readonly attribute MockCredentialsMessenger mockCredentialsMessenger;
+
+    DOMString systemPreviewRelType();
+    boolean isSystemPreviewLink(Element element);
+    boolean isSystemPreviewImage(Element element);
 };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to