Title: [291634] branches/safari-613-branch
Revision
291634
Author
alanc...@apple.com
Date
2022-03-22 10:54:38 -0700 (Tue, 22 Mar 2022)

Log Message

Cherry-pick r290519. rdar://problem/89148022

    Re-add YouTubePluginReplacement, removed in r285252
    https://bugs.webkit.org/show_bug.cgi?id=237182
    Source/WebCore:

    <rdar://89148022>

    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
    Reviewed by Chris Dumez.

    Tests: security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html
           security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html
           security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html
           security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html

    Its removal broke webpages that work in Chrome and Firefox, so back it comes.

    * Headers.cmake:
    * Modules/plugins: Copied from Source/WebCore/Modules/plugins.
    * SourcesCocoa.txt:
    * WebCore.xcodeproj/project.pbxproj:
    * bindings/js/JSPluginElementFunctions.cpp:
    (WebCore::pluginScriptObject):
    * bindings/scripts/CodeGeneratorJS.pm:
    (GenerateImplementation):
    * bindings/scripts/test/JS/JSTestPluginInterface.cpp:
    (WebCore::JSTestPluginInterface::visitChildrenImpl):
    * html/HTMLPlugInElement.cpp:
    (WebCore::HTMLPlugInElement::createElementRenderer):
    (WebCore::HTMLPlugInElement::didAddUserAgentShadowRoot):
    (WebCore::registrar):
    (WebCore::pluginReplacementForType):
    (WebCore::HTMLPlugInElement::requestObject):
    (WebCore::HTMLPlugInElement::scriptObjectForPluginReplacement):
    * html/HTMLPlugInElement.h:
    (WebCore::HTMLPlugInElement::pluginReplacementScriptObject):
    * html/shadow/ShadowPseudoIds.cpp:
    (WebCore::ShadowPseudoIds::webkitPluginReplacement):
    * html/shadow/ShadowPseudoIds.h:
    * html/shadow/YouTubeEmbedShadowElement.cpp:
    * html/shadow/YouTubeEmbedShadowElement.h:
    * page/Settings.yaml:

    Tools:

    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
    Reviewed by Chris Dumez.

    * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
    * TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp:

    LayoutTests:

    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
    Reviewed by Chris Dumez.

    * TestExpectations:
    * platform/ios-wk2/TestExpectations:
    * platform/win/TestExpectations:
    * security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt.
    * security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html.
    * security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt.
    * security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html.
    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt.
    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt.
    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html.
    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html.

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@290519 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Modified Paths

Added Paths

Diff

Modified: branches/safari-613-branch/LayoutTests/ChangeLog (291633 => 291634)


--- branches/safari-613-branch/LayoutTests/ChangeLog	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/LayoutTests/ChangeLog	2022-03-22 17:54:38 UTC (rev 291634)
@@ -1,3 +1,95 @@
+2022-03-21  Alan Coon  <alanc...@apple.com>
+
+        Cherry-pick r290519. rdar://problem/89148022
+
+    Re-add YouTubePluginReplacement, removed in r285252
+    https://bugs.webkit.org/show_bug.cgi?id=237182
+    Source/WebCore:
+    
+    <rdar://89148022>
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
+    Reviewed by Chris Dumez.
+    
+    Tests: security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html
+           security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html
+           security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html
+           security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html
+    
+    Its removal broke webpages that work in Chrome and Firefox, so back it comes.
+    
+    * Headers.cmake:
+    * Modules/plugins: Copied from Source/WebCore/Modules/plugins.
+    * SourcesCocoa.txt:
+    * WebCore.xcodeproj/project.pbxproj:
+    * bindings/js/JSPluginElementFunctions.cpp:
+    (WebCore::pluginScriptObject):
+    * bindings/scripts/CodeGeneratorJS.pm:
+    (GenerateImplementation):
+    * bindings/scripts/test/JS/JSTestPluginInterface.cpp:
+    (WebCore::JSTestPluginInterface::visitChildrenImpl):
+    * html/HTMLPlugInElement.cpp:
+    (WebCore::HTMLPlugInElement::createElementRenderer):
+    (WebCore::HTMLPlugInElement::didAddUserAgentShadowRoot):
+    (WebCore::registrar):
+    (WebCore::pluginReplacementForType):
+    (WebCore::HTMLPlugInElement::requestObject):
+    (WebCore::HTMLPlugInElement::scriptObjectForPluginReplacement):
+    * html/HTMLPlugInElement.h:
+    (WebCore::HTMLPlugInElement::pluginReplacementScriptObject):
+    * html/shadow/ShadowPseudoIds.cpp:
+    (WebCore::ShadowPseudoIds::webkitPluginReplacement):
+    * html/shadow/ShadowPseudoIds.h:
+    * html/shadow/YouTubeEmbedShadowElement.cpp:
+    * html/shadow/YouTubeEmbedShadowElement.h:
+    * page/Settings.yaml:
+    
+    Tools:
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
+    Reviewed by Chris Dumez.
+    
+    * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+    * TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp:
+    
+    LayoutTests:
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
+    Reviewed by Chris Dumez.
+    
+    * TestExpectations:
+    * platform/ios-wk2/TestExpectations:
+    * platform/win/TestExpectations:
+    * security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt.
+    * security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html.
+    * security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt.
+    * security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html.
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@290519 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2022-02-25  Alex Christensen  <achristen...@webkit.org>
+
+            Re-add YouTubePluginReplacement, removed in r285252
+            https://bugs.webkit.org/show_bug.cgi?id=237182
+
+            Reviewed by Chris Dumez.
+
+            * TestExpectations:
+            * platform/ios-wk2/TestExpectations:
+            * platform/win/TestExpectations:
+            * security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt.
+            * security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html.
+            * security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt.
+            * security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html.
+            * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt.
+            * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt.
+            * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html.
+            * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html.
+
 2022-03-09  Russell Epstein  <repst...@apple.com>
 
         Cherry-pick r290515. rdar://problem/89376484

Modified: branches/safari-613-branch/LayoutTests/TestExpectations (291633 => 291634)


--- branches/safari-613-branch/LayoutTests/TestExpectations	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/LayoutTests/TestExpectations	2022-03-22 17:54:38 UTC (rev 291634)
@@ -5191,4 +5191,8 @@
 imported/blink/http/tests/plugins [ Skip ]
 imported/blink/plugins [ Skip ]
 js/dom/reflect-set-onto-dom.html [ Skip ]
+security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html [ Skip ]
+security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html [ Skip ]
+security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html [ Skip ]
+security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html [ Skip ]
 userscripts/user-script-plugin-document.html [ Skip ]

Modified: branches/safari-613-branch/LayoutTests/platform/ios-wk2/TestExpectations (291633 => 291634)


--- branches/safari-613-branch/LayoutTests/platform/ios-wk2/TestExpectations	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/LayoutTests/platform/ios-wk2/TestExpectations	2022-03-22 17:54:38 UTC (rev 291634)
@@ -2028,6 +2028,8 @@
 
 webkit.org/b/214955 fast/parser/xml-colon-entity.html [ Failure ]
 
+webkit.org/b/223750 [ Debug ] security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html [ Pass Crash ]
+
 webkit.org/b/155196 security/contentSecurityPolicy/video-with-file-url-allowed-by-media-src-star-with-AllowContentSecurityPolicySourceStarToMatchAnyProtocol-enabled.html [ Pass ImageOnlyFailure ]
 webkit.org/b/155196 security/contentSecurityPolicy/video-with-file-url-allowed-by-media-src-star.html [ Pass ImageOnlyFailure ]
 

Modified: branches/safari-613-branch/LayoutTests/platform/win/TestExpectations (291633 => 291634)


--- branches/safari-613-branch/LayoutTests/platform/win/TestExpectations	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/LayoutTests/platform/win/TestExpectations	2022-03-22 17:54:38 UTC (rev 291634)
@@ -3280,6 +3280,7 @@
 pageoverlay/overlay-installation.html [ Failure ]
 pageoverlay/overlay-large-document-scrolled.html [ Failure ]
 pageoverlay/overlay-large-document.html [ Failure ]
+security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html [ Failure ]
 storage/indexeddb/modern/blob-cursor.html [ Failure ]
 streams/readable-byte-stream-controller.html [ Failure ]
 streams/readable-byte-stream-controller-worker.html [ Failure ]

Added: branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt (0 => 291634)


--- branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt	                        (rev 0)
+++ branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,2 @@
+CONSOLE MESSAGE: Refused to load https://www.youtube.com/v/UF8uR6Z6KLc because it does not appear in the object-src directive of the Content Security Policy.
+

Added: branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html (0 => 291634)


--- branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html	                        (rev 0)
+++ branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Security-Policy" content="object-src 'none'">
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+if (window.internals)
+    window.internals.settings.setYouTubeFlashPluginReplacementEnabled(true);
+
+function done()
+{
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+document.addEventListener("securitypolicyviolation", done, false);
+</script>
+</head>
+<body>
+<object width="425" height="350" classid=""
+    codebase=""
+    <embed width="425" height="350" type="application/x-shockwave-flash" src=""
+</object>
+</body>
+</html>

Added: branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt (0 => 291634)


--- branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt	                        (rev 0)
+++ branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,2 @@
+Blocked access to external URL https://www.youtube.com/embed/UF8uR6Z6KLc
+

Added: branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html (0 => 291634)


--- branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html	                        (rev 0)
+++ branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Security-Policy" content="plugin-types application/x-shockwave-flash">
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+if (window.internals)
+    window.internals.settings.setYouTubeFlashPluginReplacementEnabled(true);
+
+// Waiting at least 100ms seems to ensure that YouTube plugin replacement has loaded.
+window.setTimeout(function () {
+    if (window.testRunner)
+        testRunner.notifyDone();
+}, 100);
+</script>
+</head>
+<body>
+<object width="425" height="350" classid=""
+    codebase=""
+    <embed width="425" height="350" type="application/x-shockwave-flash" src=""
+</object>
+</body>
+</html>

Added: branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt (0 => 291634)


--- branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt	                        (rev 0)
+++ branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,2 @@
+CONSOLE MESSAGE: Refused to load https://www.youtube.com/v/UF8uR6Z6KLc because its MIME type does not appear in the plugin-types directive of the Content Security Policy.
+

Added: branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt (0 => 291634)


--- branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt	                        (rev 0)
+++ branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,2 @@
+CONSOLE MESSAGE: Refused to load https://www.youtube.com/v/UF8uR6Z6KLc because its MIME type does not appear in the plugin-types directive of the Content Security Policy.
+

Added: branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html (0 => 291634)


--- branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html	                        (rev 0)
+++ branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Security-Policy" content="plugin-types text/html">
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+if (window.internals)
+    window.internals.settings.setYouTubeFlashPluginReplacementEnabled(true);
+
+function done()
+{
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+document.addEventListener("securitypolicyviolation", done, false);
+</script>
+</head>
+<body>
+<object width="425" height="350" classid=""
+    codebase=""
+    <embed width="425" height="350" src=""
+</object>
+</body>
+</html>

Added: branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html (0 => 291634)


--- branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html	                        (rev 0)
+++ branches/safari-613-branch/LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Security-Policy" content="plugin-types text/html">
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+if (window.internals)
+    window.internals.settings.setYouTubeFlashPluginReplacementEnabled(true);
+
+function done()
+{
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+document.addEventListener("securitypolicyviolation", done, false);
+</script>
+</head>
+<body>
+<object width="425" height="350" classid=""
+    codebase=""
+    <embed width="425" height="350" type="application/x-shockwave-flash" src=""
+</object>
+</body>
+</html>

Modified: branches/safari-613-branch/Source/WebCore/ChangeLog (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/ChangeLog	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/ChangeLog	2022-03-22 17:54:38 UTC (rev 291634)
@@ -1,5 +1,119 @@
 2022-03-21  Alan Coon  <alanc...@apple.com>
 
+        Cherry-pick r290519. rdar://problem/89148022
+
+    Re-add YouTubePluginReplacement, removed in r285252
+    https://bugs.webkit.org/show_bug.cgi?id=237182
+    Source/WebCore:
+    
+    <rdar://89148022>
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
+    Reviewed by Chris Dumez.
+    
+    Tests: security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html
+           security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html
+           security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html
+           security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html
+    
+    Its removal broke webpages that work in Chrome and Firefox, so back it comes.
+    
+    * Headers.cmake:
+    * Modules/plugins: Copied from Source/WebCore/Modules/plugins.
+    * SourcesCocoa.txt:
+    * WebCore.xcodeproj/project.pbxproj:
+    * bindings/js/JSPluginElementFunctions.cpp:
+    (WebCore::pluginScriptObject):
+    * bindings/scripts/CodeGeneratorJS.pm:
+    (GenerateImplementation):
+    * bindings/scripts/test/JS/JSTestPluginInterface.cpp:
+    (WebCore::JSTestPluginInterface::visitChildrenImpl):
+    * html/HTMLPlugInElement.cpp:
+    (WebCore::HTMLPlugInElement::createElementRenderer):
+    (WebCore::HTMLPlugInElement::didAddUserAgentShadowRoot):
+    (WebCore::registrar):
+    (WebCore::pluginReplacementForType):
+    (WebCore::HTMLPlugInElement::requestObject):
+    (WebCore::HTMLPlugInElement::scriptObjectForPluginReplacement):
+    * html/HTMLPlugInElement.h:
+    (WebCore::HTMLPlugInElement::pluginReplacementScriptObject):
+    * html/shadow/ShadowPseudoIds.cpp:
+    (WebCore::ShadowPseudoIds::webkitPluginReplacement):
+    * html/shadow/ShadowPseudoIds.h:
+    * html/shadow/YouTubeEmbedShadowElement.cpp:
+    * html/shadow/YouTubeEmbedShadowElement.h:
+    * page/Settings.yaml:
+    
+    Tools:
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
+    Reviewed by Chris Dumez.
+    
+    * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+    * TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp:
+    
+    LayoutTests:
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
+    Reviewed by Chris Dumez.
+    
+    * TestExpectations:
+    * platform/ios-wk2/TestExpectations:
+    * platform/win/TestExpectations:
+    * security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt.
+    * security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html.
+    * security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt.
+    * security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html.
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@290519 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2022-02-25  Alex Christensen  <achristen...@webkit.org>
+
+            Re-add YouTubePluginReplacement, removed in r285252
+            https://bugs.webkit.org/show_bug.cgi?id=237182
+            <rdar://89148022>
+
+            Reviewed by Chris Dumez.
+
+            Tests: security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html
+                   security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html
+                   security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html
+                   security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html
+
+            Its removal broke webpages that work in Chrome and Firefox, so back it comes.
+
+            * Headers.cmake:
+            * Modules/plugins: Copied from Source/WebCore/Modules/plugins.
+            * SourcesCocoa.txt:
+            * WebCore.xcodeproj/project.pbxproj:
+            * bindings/js/JSPluginElementFunctions.cpp:
+            (WebCore::pluginScriptObject):
+            * bindings/scripts/CodeGeneratorJS.pm:
+            (GenerateImplementation):
+            * bindings/scripts/test/JS/JSTestPluginInterface.cpp:
+            (WebCore::JSTestPluginInterface::visitChildrenImpl):
+            * html/HTMLPlugInElement.cpp:
+            (WebCore::HTMLPlugInElement::createElementRenderer):
+            (WebCore::HTMLPlugInElement::didAddUserAgentShadowRoot):
+            (WebCore::registrar):
+            (WebCore::pluginReplacementForType):
+            (WebCore::HTMLPlugInElement::requestObject):
+            (WebCore::HTMLPlugInElement::scriptObjectForPluginReplacement):
+            * html/HTMLPlugInElement.h:
+            (WebCore::HTMLPlugInElement::pluginReplacementScriptObject):
+            * html/shadow/ShadowPseudoIds.cpp:
+            (WebCore::ShadowPseudoIds::webkitPluginReplacement):
+            * html/shadow/ShadowPseudoIds.h:
+            * html/shadow/YouTubeEmbedShadowElement.cpp:
+            * html/shadow/YouTubeEmbedShadowElement.h:
+            * page/Settings.yaml:
+
+2022-03-21  Alan Coon  <alanc...@apple.com>
+
         Cherry-pick r288662. rdar://problem/89582442
 
     [WP] Avoid calling IOSurfaceAlignProperty

Modified: branches/safari-613-branch/Source/WebCore/Headers.cmake (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/Headers.cmake	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/Headers.cmake	2022-03-22 17:54:38 UTC (rev 291634)
@@ -294,6 +294,9 @@
     Modules/permissions/PermissionObserver.h
     Modules/permissions/PermissionState.h
 
+    Modules/plugins/PluginReplacement.h
+    Modules/plugins/YouTubePluginReplacement.h
+
     Modules/push-api/PushCrypto.h
     Modules/push-api/PushMessageCrypto.h
     Modules/push-api/PushPermissionState.h

Added: branches/safari-613-branch/Source/WebCore/Modules/plugins/PluginReplacement.h (0 => 291634)


--- branches/safari-613-branch/Source/WebCore/Modules/plugins/PluginReplacement.h	                        (rev 0)
+++ branches/safari-613-branch/Source/WebCore/Modules/plugins/PluginReplacement.h	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * 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. ``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
+ * 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 "RenderPtr.h"
+#include <_javascript_Core/JSCJSValue.h>
+#include <_javascript_Core/JSCJSValueInlines.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+class JSObject;
+}
+
+namespace WebCore {
+
+class HTMLPlugInElement;
+class RenderElement;
+class RenderStyle;
+class RenderTreePosition;
+class Settings;
+class ShadowRoot;
+
+class PluginReplacement : public RefCounted<PluginReplacement> {
+public:
+    virtual ~PluginReplacement() = default;
+
+    struct InstallResult {
+        bool success;
+#if PLATFORM(COCOA)
+        JSC::JSValue scriptObject { };
+#endif
+    };
+
+    virtual InstallResult installReplacement(ShadowRoot&) = 0;
+
+    virtual bool willCreateRenderer() { return false; }
+    virtual RenderPtr<RenderElement> createElementRenderer(HTMLPlugInElement&, RenderStyle&&, const RenderTreePosition&) = 0;
+};
+
+typedef Ref<PluginReplacement> (*CreatePluginReplacement)(HTMLPlugInElement&, const Vector<String>& paramNames, const Vector<String>& paramValues);
+typedef bool (*PluginReplacementSupportsType)(const String&);
+typedef bool (*PluginReplacementSupportsFileExtension)(const String&);
+typedef bool (*PluginReplacementSupportsURL)(const URL&);
+typedef bool (*PluginReplacementEnabledForSettings)(const Settings&);
+
+class ReplacementPlugin {
+public:
+    ReplacementPlugin(CreatePluginReplacement constructor, PluginReplacementSupportsType supportsType, PluginReplacementSupportsFileExtension supportsFileExtension, PluginReplacementSupportsURL supportsURL, PluginReplacementEnabledForSettings isEnabledBySettings)
+        : m_constructor(constructor)
+        , m_supportsType(supportsType)
+        , m_supportsFileExtension(supportsFileExtension)
+        , m_supportsURL(supportsURL)
+        , m_isEnabledBySettings(isEnabledBySettings)
+    {
+    }
+
+    explicit ReplacementPlugin(const ReplacementPlugin& other)
+        : m_constructor(other.m_constructor)
+        , m_supportsType(other.m_supportsType)
+        , m_supportsFileExtension(other.m_supportsFileExtension)
+        , m_supportsURL(other.m_supportsURL)
+        , m_isEnabledBySettings(other.m_isEnabledBySettings)
+    {
+    }
+
+    Ref<PluginReplacement> create(HTMLPlugInElement& element, const Vector<String>& paramNames, const Vector<String>& paramValues) const { return m_constructor(element, paramNames, paramValues); }
+    bool supportsType(const String& mimeType) const { return m_supportsType(mimeType); }
+    bool supportsFileExtension(const String& extension) const { return m_supportsFileExtension(extension); }
+    bool supportsURL(const URL& url) const { return m_supportsURL(url); }
+    bool isEnabledBySettings(const Settings& settings) const { return m_isEnabledBySettings(settings); };
+
+private:
+    CreatePluginReplacement m_constructor;
+    PluginReplacementSupportsType m_supportsType;
+    PluginReplacementSupportsFileExtension m_supportsFileExtension;
+    PluginReplacementSupportsURL m_supportsURL;
+    PluginReplacementEnabledForSettings m_isEnabledBySettings;
+};
+
+typedef void (*PluginReplacementRegistrar)(const ReplacementPlugin&);
+
+}

Added: branches/safari-613-branch/Source/WebCore/Modules/plugins/YouTubePluginReplacement.cpp (0 => 291634)


--- branches/safari-613-branch/Source/WebCore/Modules/plugins/YouTubePluginReplacement.cpp	                        (rev 0)
+++ branches/safari-613-branch/Source/WebCore/Modules/plugins/YouTubePluginReplacement.cpp	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * 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. ``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
+ * 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 "YouTubePluginReplacement.h"
+
+#include "HTMLIFrameElement.h"
+#include "HTMLNames.h"
+#include "HTMLParserIdioms.h"
+#include "HTMLPlugInElement.h"
+#include "RenderElement.h"
+#include "Settings.h"
+#include "ShadowRoot.h"
+#include "YouTubeEmbedShadowElement.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+void YouTubePluginReplacement::registerPluginReplacement(PluginReplacementRegistrar registrar)
+{
+    registrar(ReplacementPlugin(create, supportsMIMEType, supportsFileExtension, supportsURL, isEnabledBySettings));
+}
+
+Ref<PluginReplacement> YouTubePluginReplacement::create(HTMLPlugInElement& plugin, const Vector<String>& paramNames, const Vector<String>& paramValues)
+{
+    return adoptRef(*new YouTubePluginReplacement(plugin, paramNames, paramValues));
+}
+
+bool YouTubePluginReplacement::supportsMIMEType(const String& mimeType)
+{
+    return equalLettersIgnoringASCIICase(mimeType, "application/x-shockwave-flash")
+        || equalLettersIgnoringASCIICase(mimeType, "application/futuresplash");
+}
+
+bool YouTubePluginReplacement::supportsFileExtension(const String& extension)
+{
+    return equalLettersIgnoringASCIICase(extension, "spl") || equalLettersIgnoringASCIICase(extension, "swf");
+}
+
+YouTubePluginReplacement::YouTubePluginReplacement(HTMLPlugInElement& plugin, const Vector<String>& paramNames, const Vector<String>& paramValues)
+    : m_parentElement(plugin)
+{
+    ASSERT(paramNames.size() == paramValues.size());
+    for (size_t i = 0; i < paramNames.size(); ++i)
+        m_attributes.add(paramNames[i], paramValues[i]);
+}
+
+RenderPtr<RenderElement> YouTubePluginReplacement::createElementRenderer(HTMLPlugInElement& plugin, RenderStyle&& style, const RenderTreePosition& insertionPosition)
+{
+    ASSERT_UNUSED(plugin, m_parentElement == &plugin);
+
+    if (!m_embedShadowElement)
+        return nullptr;
+    
+    return m_embedShadowElement->createElementRenderer(WTFMove(style), insertionPosition);
+}
+
+auto YouTubePluginReplacement::installReplacement(ShadowRoot& root) -> InstallResult
+{
+    m_embedShadowElement = YouTubeEmbedShadowElement::create(m_parentElement->document());
+
+    root.appendChild(*m_embedShadowElement);
+
+    auto iframeElement = HTMLIFrameElement::create(HTMLNames::iframeTag, m_parentElement->document());
+    if (m_attributes.contains("width"))
+        iframeElement->setAttributeWithoutSynchronization(HTMLNames::widthAttr, AtomString("100%", AtomString::ConstructFromLiteral));
+
+    const auto& heightValue = m_attributes.find("height");
+    if (heightValue != m_attributes.end()) {
+        iframeElement->setAttribute(HTMLNames::styleAttr, AtomString("max-height: 100%", AtomString::ConstructFromLiteral));
+        iframeElement->setAttributeWithoutSynchronization(HTMLNames::heightAttr, heightValue->value);
+    }
+
+    iframeElement->setAttributeWithoutSynchronization(HTMLNames::srcAttr, youTubeURL(m_attributes.get("src")));
+    iframeElement->setAttributeWithoutSynchronization(HTMLNames::frameborderAttr, AtomString("0", AtomString::ConstructFromLiteral));
+    
+    // Disable frame flattening for this iframe.
+    iframeElement->setAttributeWithoutSynchronization(HTMLNames::scrollingAttr, AtomString("no", AtomString::ConstructFromLiteral));
+    m_embedShadowElement->appendChild(iframeElement);
+
+    return { true };
+}
+    
+static URL createYouTubeURL(StringView videoID, StringView timeID)
+{
+    ASSERT(!videoID.isEmpty());
+    ASSERT(videoID != "/");
+    return URL(URL(), makeString("youtube:", videoID, timeID.isEmpty() ? "" : "t=", timeID));
+}
+
+static YouTubePluginReplacement::KeyValueMap queryKeysAndValues(StringView queryString)
+{
+    YouTubePluginReplacement::KeyValueMap queryDictionary;
+    
+    size_t queryLength = queryString.length();
+    if (!queryLength)
+        return queryDictionary;
+    
+    size_t equalSearchLocation = 0;
+    size_t equalSearchLength = queryLength;
+    
+    while (equalSearchLocation < queryLength - 1 && equalSearchLength) {
+        
+        // Search for "=".
+        size_t equalLocation = queryString.find('=', equalSearchLocation);
+        if (equalLocation == notFound)
+            break;
+        
+        size_t indexAfterEqual = equalLocation + 1;
+        if (indexAfterEqual > queryLength - 1)
+            break;
+        
+        // Get the key before the "=".
+        size_t keyLocation = equalSearchLocation;
+        size_t keyLength = equalLocation - equalSearchLocation;
+        
+        // Seach for the ampersand.
+        size_t ampersandLocation = queryString.find('&', indexAfterEqual);
+        
+        // Get the value after the "=", before the ampersand.
+        size_t valueLocation = indexAfterEqual;
+        size_t valueLength;
+        if (ampersandLocation != notFound)
+            valueLength = ampersandLocation - indexAfterEqual;
+        else
+            valueLength = queryLength - indexAfterEqual;
+        
+        // Save the key and the value.
+        if (keyLength && valueLength) {
+            String key = queryString.substring(keyLocation, keyLength).convertToASCIILowercase();
+            String value = queryString.substring(valueLocation, valueLength).toString();
+            value.replace('+', ' ');
+
+            if (!key.isEmpty() && !value.isEmpty())
+                queryDictionary.add(key, value);
+        }
+        
+        if (ampersandLocation == notFound)
+            break;
+        
+        // Continue searching after the ampersand.
+        size_t indexAfterAmpersand = ampersandLocation + 1;
+        equalSearchLocation = indexAfterAmpersand;
+        equalSearchLength = queryLength - indexAfterAmpersand;
+    }
+    
+    return queryDictionary;
+}
+    
+static bool isYouTubeURL(const URL& url)
+{
+    auto hostName = url.host();
+    return equalLettersIgnoringASCIICase(hostName, "m.youtube.com")
+        || equalLettersIgnoringASCIICase(hostName, "youtu.be")
+        || equalLettersIgnoringASCIICase(hostName, "www.youtube.com")
+        || equalLettersIgnoringASCIICase(hostName, "youtube.com")
+        || equalLettersIgnoringASCIICase(hostName, "www.youtube-nocookie.com")
+        || equalLettersIgnoringASCIICase(hostName, "youtube-nocookie.com");
+}
+
+static const String& valueForKey(const YouTubePluginReplacement::KeyValueMap& dictionary, const String& key)
+{
+    const auto& value = dictionary.find(key);
+    if (value == dictionary.end())
+        return emptyString();
+
+    return value->value;
+}
+
+static URL processAndCreateYouTubeURL(const URL& url, bool& isYouTubeShortenedURL, String& outPathAfterFirstAmpersand)
+{
+    if (!url.protocolIsInHTTPFamily())
+        return URL();
+
+    // Bail out early if we aren't even on www.youtube.com or youtube.com.
+    if (!isYouTubeURL(url))
+        return URL();
+
+    auto hostName = url.host();
+    bool isYouTubeMobileWebAppURL = equalLettersIgnoringASCIICase(hostName, "m.youtube.com");
+    isYouTubeShortenedURL = equalLettersIgnoringASCIICase(hostName, "youtu.be");
+
+    // Short URL of the form: http://youtu.be/v1d301D
+    if (isYouTubeShortenedURL) {
+        auto videoID = url.lastPathComponent();
+        if (videoID.isEmpty() || videoID == "/")
+            return URL();
+        return createYouTubeURL(videoID, { });
+    }
+
+    auto path = url.path();
+    auto query = url.query();
+    auto fragment = url.fragmentIdentifier();
+
+    // On the YouTube mobile web app, the path and query string are put into the
+    // fragment so that one web page is only ever loaded (see <rdar://problem/9550639>).
+    if (isYouTubeMobileWebAppURL) {
+        size_t location = fragment.find('?');
+        if (location == notFound) {
+            path = fragment;
+            query = emptyString();
+        } else {
+            path = fragment.substring(0, location);
+            query = fragment.substring(location + 1);
+        }
+        fragment = emptyString();
+    }
+    
+    if (equalLettersIgnoringASCIICase(path, "/watch")) {
+        if (!query.isEmpty()) {
+            const auto& queryDictionary = queryKeysAndValues(query);
+            String videoID = valueForKey(queryDictionary, "v");
+            
+            if (!videoID.isEmpty()) {
+                const auto& fragmentDictionary = queryKeysAndValues(url.fragmentIdentifier());
+                String timeID = valueForKey(fragmentDictionary, "t");
+                return createYouTubeURL(videoID, timeID);
+            }
+        }
+        
+        // May be a new-style link (see <rdar://problem/7733692>).
+        if (fragment.startsWith('!')) {
+            query = fragment.substring(1);
+            
+            if (!query.isEmpty()) {
+                const auto& queryDictionary = queryKeysAndValues(query);
+                String videoID = valueForKey(queryDictionary, "v");
+                
+                if (!videoID.isEmpty()) {
+                    String timeID = valueForKey(queryDictionary, "t");
+                    return createYouTubeURL(videoID, timeID);
+                }
+            }
+        }
+    } else if (startsWithLettersIgnoringASCIICase(path, "/v/") || startsWithLettersIgnoringASCIICase(path, "/e/")) {
+        StringView videoID;
+        StringView pathAfterFirstAmpersand;
+
+        auto lastPathComponent = url.lastPathComponent();
+        size_t ampersandLocation = lastPathComponent.find('&');
+        if (ampersandLocation != notFound) {
+            // Some URLs we care about use & in place of ? for the first query parameter.
+            videoID = lastPathComponent.substring(0, ampersandLocation);
+            pathAfterFirstAmpersand = lastPathComponent.substring(ampersandLocation + 1, lastPathComponent.length() - ampersandLocation);
+        } else
+            videoID = lastPathComponent;
+
+        if (!videoID.isEmpty()) {
+            outPathAfterFirstAmpersand = pathAfterFirstAmpersand.toString();
+            return createYouTubeURL(videoID, emptyString());
+        }
+    }
+
+    return URL();
+}
+
+String YouTubePluginReplacement::youTubeURL(const String& srcString)
+{
+    URL srcURL = m_parentElement->document().completeURL(stripLeadingAndTrailingHTMLSpaces(srcString));
+    return youTubeURLFromAbsoluteURL(srcURL, srcString);
+}
+
+String YouTubePluginReplacement::youTubeURLFromAbsoluteURL(const URL& srcURL, const String& srcString)
+{
+    bool isYouTubeShortenedURL = false;
+    String possiblyMalformedQuery;
+    URL youTubeURL = processAndCreateYouTubeURL(srcURL, isYouTubeShortenedURL, possiblyMalformedQuery);
+    if (srcURL.isEmpty() || youTubeURL.isEmpty())
+        return srcString;
+
+    // Transform the youtubeURL (youtube:VideoID) to iframe embed url which has the format: http://www.youtube.com/embed/VideoID
+    auto srcPath = srcURL.path();
+    const String& videoID = youTubeURL.string().substring(youTubeURL.protocol().length() + 1);
+    size_t locationOfVideoIDInPath = srcPath.find(videoID);
+
+    size_t locationOfPathBeforeVideoID = notFound;
+    if (locationOfVideoIDInPath != notFound) {
+        ASSERT(locationOfVideoIDInPath);
+    
+        // From the original URL, we need to get the part before /path/VideoId.
+        locationOfPathBeforeVideoID = StringView(srcString).find(srcPath.substring(0, locationOfVideoIDInPath));
+    } else if (equalLettersIgnoringASCIICase(srcPath, "/watch")) {
+        // From the original URL, we need to get the part before /watch/#!v=VideoID
+        // FIXME: Shouldn't this be ASCII case-insensitive?
+        locationOfPathBeforeVideoID = srcString.find("/watch");
+    } else
+        return srcString;
+
+    ASSERT(locationOfPathBeforeVideoID != notFound);
+
+    auto srcURLPrefix = StringView(srcString).substring(0, locationOfPathBeforeVideoID);
+    auto query = srcURL.query();
+
+    // If the URL has no query, use the possibly malformed query we found.
+    if (query.isEmpty())
+        query = possiblyMalformedQuery;
+
+    // Append the query string if it is valid.
+    return makeString(
+        isYouTubeShortenedURL ? "http://www.youtube.com" : srcURLPrefix,
+        "/embed/",
+        videoID,
+        query.isEmpty() ? "" : "?",
+        query
+    );
+}
+    
+bool YouTubePluginReplacement::supportsURL(const URL& url)
+{
+    return isYouTubeURL(url);
+}
+
+bool YouTubePluginReplacement::isEnabledBySettings(const Settings& settings)
+{
+    return settings.youTubeFlashPluginReplacementEnabled();
+}
+    
+}

Added: branches/safari-613-branch/Source/WebCore/Modules/plugins/YouTubePluginReplacement.h (0 => 291634)


--- branches/safari-613-branch/Source/WebCore/Modules/plugins/YouTubePluginReplacement.h	                        (rev 0)
+++ branches/safari-613-branch/Source/WebCore/Modules/plugins/YouTubePluginReplacement.h	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * 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. ``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
+ * 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 "PluginReplacement.h"
+#include <wtf/HashMap.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class YouTubeEmbedShadowElement;
+
+class YouTubePluginReplacement final : public PluginReplacement {
+public:
+    static void registerPluginReplacement(PluginReplacementRegistrar);
+
+    typedef HashMap<String, String> KeyValueMap;
+
+    WEBCORE_EXPORT static String youTubeURLFromAbsoluteURL(const URL& srcURL, const String& srcString);
+
+private:
+    YouTubePluginReplacement(HTMLPlugInElement&, const Vector<String>& paramNames, const Vector<String>& paramValues);
+    static Ref<PluginReplacement> create(HTMLPlugInElement&, const Vector<String>& paramNames, const Vector<String>& paramValues);
+    static bool supportsMIMEType(const String&);
+    static bool supportsFileExtension(const String&);
+    static bool supportsURL(const URL&);
+    static bool isEnabledBySettings(const Settings&);
+
+    InstallResult installReplacement(ShadowRoot&) final;
+
+    String youTubeURL(const String& rawURL);
+
+    bool willCreateRenderer() final { return m_embedShadowElement; }
+    RenderPtr<RenderElement> createElementRenderer(HTMLPlugInElement&, RenderStyle&&, const RenderTreePosition&) final;
+
+    WeakPtr<HTMLPlugInElement> m_parentElement;
+    RefPtr<YouTubeEmbedShadowElement> m_embedShadowElement;
+    KeyValueMap m_attributes;
+};
+
+}

Modified: branches/safari-613-branch/Source/WebCore/SourcesCocoa.txt (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/SourcesCocoa.txt	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/SourcesCocoa.txt	2022-03-22 17:54:38 UTC (rev 291634)
@@ -107,6 +107,7 @@
 Modules/model-element/scenekit/SceneKitModelLoaderUSD.mm
 Modules/model-element/scenekit/SceneKitModelPlayer.mm
 Modules/push-api/cocoa/PushCryptoCocoa.cpp
+Modules/plugins/YouTubePluginReplacement.cpp
 Modules/speech/cocoa/SpeechRecognizerCocoa.mm
 Modules/speech/cocoa/WebSpeechRecognizerTask.mm
 Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm
@@ -177,6 +178,7 @@
 editing/mac/TextUndoInsertionMarkupMac.mm
 fileapi/FileCocoa.mm
 history/mac/HistoryItemMac.mm
+html/shadow/YouTubeEmbedShadowElement.cpp
 inspector/mac/PageDebuggerMac.mm
 loader/archive/cf/LegacyWebArchive.cpp
 loader/archive/cf/LegacyWebArchiveMac.mm

Modified: branches/safari-613-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-03-22 17:54:38 UTC (rev 291634)
@@ -109,6 +109,7 @@
 		07277E5517D018CC0015534D /* JSMediaStreamTrackEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 07277E4917D018CC0015534D /* JSMediaStreamTrackEvent.h */; };
 		072880D12010F1F60071B255 /* RealtimeVideoCaptureSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 072880D02010EED70071B255 /* RealtimeVideoCaptureSource.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		072A70401D6E8F6200DF0AFC /* OverconstrainedErrorEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 072A703E1D6E8F6200DF0AFC /* OverconstrainedErrorEvent.h */; };
+		072AE1E5183C0741000A5988 /* PluginReplacement.h in Headers */ = {isa = PBXBuildFile; fileRef = 072AE1DF183C0741000A5988 /* PluginReplacement.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		073794DE19EE2C5200E5A045 /* RTCOfferAnswerOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 073794DC19EE2C5200E5A045 /* RTCOfferAnswerOptions.h */; };
 		073794E619EE2FF200E5A045 /* JSRTCConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 073794E419EE2FF200E5A045 /* JSRTCConfiguration.h */; };
 		073794EC19EE341E00E5A045 /* JSRTCIceServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 073794EA19EE341E00E5A045 /* JSRTCIceServer.h */; };
@@ -2373,6 +2374,7 @@
 		7A45033018DB717200377B34 /* BufferedLineReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A45032E18DB717200377B34 /* BufferedLineReader.h */; };
 		7A54858014E02D51006AE05A /* InspectorHistory.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A54857E14E02D51006AE05A /* InspectorHistory.h */; };
 		7A54881714E432A1006AE05A /* DOMPatchSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A54881514E432A1006AE05A /* DOMPatchSupport.h */; };
+		7A5515F5191830A3009687D2 /* YouTubePluginReplacement.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A5515F3191830A3009687D2 /* YouTubePluginReplacement.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7A5699702086C619000E0433 /* CookieRequestHeaderFieldProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A56996E2086C618000E0433 /* CookieRequestHeaderFieldProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7A674BDC0F9EBF4E006CF099 /* PageGroupLoadDeferrer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A674BDA0F9EBF4E006CF099 /* PageGroupLoadDeferrer.h */; };
 		7A929CA71C598AA9004DF226 /* ResourceLoadStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A929CA21C598378004DF226 /* ResourceLoadStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -3464,6 +3466,7 @@
 		A52B348F1FA3BDA6008B6246 /* ServiceWorkerDebuggable.h in Headers */ = {isa = PBXBuildFile; fileRef = A52B348C1FA3BD79008B6246 /* ServiceWorkerDebuggable.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A52B34961FA3E290008B6246 /* ServiceWorkerInspectorProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = A52B34931FA3E286008B6246 /* ServiceWorkerInspectorProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A52B349E1FA41703008B6246 /* WorkerDebuggerProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = A52B349C1FA416F8008B6246 /* WorkerDebuggerProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		A5416FE618810EF80009FC5F /* YouTubeEmbedShadowElement.h in Headers */ = {isa = PBXBuildFile; fileRef = A5416FE418810EF80009FC5F /* YouTubeEmbedShadowElement.h */; };
 		A54A0C621DB7F8C10017A90B /* WorkerInspectorController.h in Headers */ = {isa = PBXBuildFile; fileRef = A54A0C601DB7F8B70017A90B /* WorkerInspectorController.h */; };
 		A54A0C661DB805360017A90B /* WorkerDebugger.h in Headers */ = {isa = PBXBuildFile; fileRef = A54A0C641DB805320017A90B /* WorkerDebugger.h */; };
 		A54A0C681DB807D90017A90B /* WorkerToPageFrontendChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = A54A0C671DB807D00017A90B /* WorkerToPageFrontendChannel.h */; };
@@ -5994,6 +5997,7 @@
 		072880D02010EED70071B255 /* RealtimeVideoCaptureSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RealtimeVideoCaptureSource.h; sourceTree = "<group>"; };
 		072A703E1D6E8F6200DF0AFC /* OverconstrainedErrorEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OverconstrainedErrorEvent.h; sourceTree = "<group>"; };
 		072A703F1D6E8F6200DF0AFC /* OverconstrainedErrorEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = OverconstrainedErrorEvent.idl; sourceTree = "<group>"; };
+		072AE1DF183C0741000A5988 /* PluginReplacement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginReplacement.h; sourceTree = "<group>"; };
 		072CA86016CB4DC3008AE131 /* CaptionUserPreferences.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CaptionUserPreferences.cpp; sourceTree = "<group>"; };
 		072DBBFB25DB38BC00A1350E /* MediaSessionCoordinator.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = MediaSessionCoordinator.idl; sourceTree = "<group>"; };
 		072DBC0325DC6BD300A1350E /* MediaSessionCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaSessionCoordinator.h; sourceTree = "<group>"; };
@@ -11415,6 +11419,8 @@
 		7A54857E14E02D51006AE05A /* InspectorHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorHistory.h; sourceTree = "<group>"; };
 		7A54881514E432A1006AE05A /* DOMPatchSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMPatchSupport.h; sourceTree = "<group>"; };
 		7A54881614E432A1006AE05A /* DOMPatchSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMPatchSupport.cpp; sourceTree = "<group>"; };
+		7A5515F3191830A3009687D2 /* YouTubePluginReplacement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YouTubePluginReplacement.h; sourceTree = "<group>"; };
+		7A5515F4191830A3009687D2 /* YouTubePluginReplacement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YouTubePluginReplacement.cpp; sourceTree = "<group>"; };
 		7A56996E2086C618000E0433 /* CookieRequestHeaderFieldProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CookieRequestHeaderFieldProxy.h; sourceTree = "<group>"; };
 		7A674BD90F9EBF4E006CF099 /* PageGroupLoadDeferrer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageGroupLoadDeferrer.cpp; sourceTree = "<group>"; };
 		7A674BDA0F9EBF4E006CF099 /* PageGroupLoadDeferrer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageGroupLoadDeferrer.h; sourceTree = "<group>"; };
@@ -13744,6 +13750,8 @@
 		A52B349C1FA416F8008B6246 /* WorkerDebuggerProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WorkerDebuggerProxy.h; sourceTree = "<group>"; };
 		A52D85CA21B0982F0061C1EB /* ServerTimingParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ServerTimingParser.cpp; sourceTree = "<group>"; };
 		A52D85CB21B098300061C1EB /* ServerTimingParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ServerTimingParser.h; sourceTree = "<group>"; };
+		A5416FE318810EF80009FC5F /* YouTubeEmbedShadowElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YouTubeEmbedShadowElement.cpp; sourceTree = "<group>"; };
+		A5416FE418810EF80009FC5F /* YouTubeEmbedShadowElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YouTubeEmbedShadowElement.h; sourceTree = "<group>"; };
 		A54A0C5F1DB7F8B70017A90B /* WorkerInspectorController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerInspectorController.cpp; sourceTree = "<group>"; };
 		A54A0C601DB7F8B70017A90B /* WorkerInspectorController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WorkerInspectorController.h; sourceTree = "<group>"; };
 		A54A0C631DB805320017A90B /* WorkerDebugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerDebugger.cpp; sourceTree = "<group>"; };
@@ -18660,6 +18668,16 @@
 			path = mac;
 			sourceTree = "<group>";
 		};
+		072AE1DE183C0513000A5988 /* plugins */ = {
+			isa = PBXGroup;
+			children = (
+				072AE1DF183C0741000A5988 /* PluginReplacement.h */,
+				7A5515F4191830A3009687D2 /* YouTubePluginReplacement.cpp */,
+				7A5515F3191830A3009687D2 /* YouTubePluginReplacement.h */,
+			);
+			path = plugins;
+			sourceTree = "<group>";
+		};
 		076F0D0812B8192700C26AA4 /* avfoundation */ = {
 			isa = PBXGroup;
 			children = (
@@ -20911,6 +20929,8 @@
 				142B97C813138943008BEF4B /* TextControlInnerElements.h */,
 				CE212154240DBD30006ED443 /* TextPlaceholderElement.cpp */,
 				CE212153240DBD30006ED443 /* TextPlaceholderElement.h */,
+				A5416FE318810EF80009FC5F /* YouTubeEmbedShadowElement.cpp */,
+				A5416FE418810EF80009FC5F /* YouTubeEmbedShadowElement.h */,
 			);
 			path = shadow;
 			sourceTree = "<group>";
@@ -25976,6 +25996,7 @@
 				A1F76B0E1F44C0CF0014C318 /* paymentrequest */,
 				93B0A64226CDC57400AA21E4 /* permissions */,
 				1DEF06A2233C32DB00EE228D /* pictureinpicture */,
+				072AE1DE183C0513000A5988 /* plugins */,
 				418FCBB82706E4BD00F96ECA /* push-api */,
 				CDC312E022FCD0B0001204EC /* remoteplayback */,
 				AA2A5AB716A485A400975A25 /* speech */,
@@ -36516,6 +36537,7 @@
 				A9C6E4F40D745E48006442E9 /* PluginData.h in Headers */,
 				97205ABC1239292700B17380 /* PluginDocument.h in Headers */,
 				1A08FEDD1D592B8B008BA8CB /* PluginInfoProvider.h in Headers */,
+				072AE1E5183C0741000A5988 /* PluginReplacement.h in Headers */,
 				71E2183A17359FB8006E6E4D /* PlugInsResources.h in Headers */,
 				0AFDAC3D10F5448C00E1F3D2 /* PluginViewBase.h in Headers */,
 				BCBB8AB913F1AFB000734DF0 /* PODInterval.h in Headers */,
@@ -38050,6 +38072,8 @@
 				E1F1E8300C3C2BB9006DB391 /* XSLTExtensions.h in Headers */,
 				93F199ED08245E59001E9ABC /* XSLTProcessor.h in Headers */,
 				E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */,
+				A5416FE618810EF80009FC5F /* YouTubeEmbedShadowElement.h in Headers */,
+				7A5515F5191830A3009687D2 /* YouTubePluginReplacement.h in Headers */,
 				FD537353137B651800008DCE /* ZeroPole.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

Modified: branches/safari-613-branch/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp	2022-03-22 17:54:38 UTC (rev 291634)
@@ -78,8 +78,12 @@
 
     // Choke point for script/plugin interaction; notify DOMTimer of the event.
     DOMTimer::scriptDidInteractWithPlugin(pluginElement);
+
+    // First, see if the element has a plug-in replacement with a script.
+    if (auto* scriptObject = pluginElement.scriptObjectForPluginReplacement())
+        return scriptObject;
     
-    // See if we can ask the plug-in view for its script object.
+    // Next, see if we can ask the plug-in view for its script object.
     if (auto* scriptObject = pluginScriptObjectFromPluginViewBase(pluginElement, jsHTMLElement->globalObject()))
         return scriptObject;
 

Modified: branches/safari-613-branch/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2022-03-22 17:54:38 UTC (rev 291634)
@@ -4894,6 +4894,11 @@
         push(@implContent, "    ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n");
         push(@implContent, "    Base::visitChildren(thisObject, visitor);\n");
         push(@implContent, "    thisObject->visitAdditionalChildren(visitor);\n") if $interface->extendedAttributes->{JSCustomMarkFunction};
+        if ($interface->extendedAttributes->{Plugin}) {
+            push(@implContent, "#if PLATFORM(COCOA)\n");
+            push(@implContent, "    thisObject->wrapped().pluginReplacementScriptObject().visit(visitor);\n");
+            push(@implContent, "#endif\n");
+        }
         if ($interface->extendedAttributes->{GenerateAddOpaqueRoot}) {
             AddToImplIncludes("<wtf/GetPtr.h>");
             my $functionName = $interface->extendedAttributes->{GenerateAddOpaqueRoot};

Modified: branches/safari-613-branch/Source/WebCore/bindings/scripts/test/JS/JSTestPluginInterface.cpp (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/bindings/scripts/test/JS/JSTestPluginInterface.cpp	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/bindings/scripts/test/JS/JSTestPluginInterface.cpp	2022-03-22 17:54:38 UTC (rev 291634)
@@ -265,6 +265,9 @@
     auto* thisObject = jsCast<JSTestPluginInterface*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     Base::visitChildren(thisObject, visitor);
+#if PLATFORM(COCOA)
+    thisObject->wrapped().pluginReplacementScriptObject().visit(visitor);
+#endif
 }
 
 DEFINE_VISIT_CHILDREN(JSTestPluginInterface);

Modified: branches/safari-613-branch/Source/WebCore/html/HTMLPlugInElement.cpp (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/html/HTMLPlugInElement.cpp	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/html/HTMLPlugInElement.cpp	2022-03-22 17:54:38 UTC (rev 291634)
@@ -37,6 +37,7 @@
 #include "MIMETypeRegistry.h"
 #include "Page.h"
 #include "PluginData.h"
+#include "PluginReplacement.h"
 #include "PluginViewBase.h"
 #include "RenderEmbeddedObject.h"
 #include "RenderLayer.h"
@@ -49,6 +50,10 @@
 #include "Widget.h"
 #include <wtf/IsoMallocInlines.h>
 
+#if PLATFORM(COCOA)
+#include "YouTubePluginReplacement.h"
+#endif
+
 namespace WebCore {
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLPlugInElement);
@@ -246,8 +251,11 @@
     return !downcast<RenderEmbeddedObject>(*renderer()).isPluginUnavailable();
 }
 
-RenderPtr<RenderElement> HTMLPlugInElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
+RenderPtr<RenderElement> HTMLPlugInElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition& insertionPosition)
 {
+    if (m_pluginReplacement && m_pluginReplacement->willCreateRenderer())
+        return m_pluginReplacement->createElementRenderer(*this, WTFMove(style), insertionPosition);
+
     return createRenderer<RenderEmbeddedObject>(*this, WTFMove(style));
 }
 
@@ -275,15 +283,124 @@
         m_swapRendererTimer.startOneShot(0_s);
 }
 
-void HTMLPlugInElement::didAddUserAgentShadowRoot(ShadowRoot&)
+void HTMLPlugInElement::didAddUserAgentShadowRoot(ShadowRoot& root)
 {
+    if (!m_pluginReplacement || !document().page() || displayState() != PreparingPluginReplacement)
+        return;
+    
+    root.setResetStyleInheritance(true);
+    auto result = m_pluginReplacement->installReplacement(root);
+
+#if PLATFORM(COCOA)
+    RELEASE_ASSERT(result.success || !result.scriptObject);
+    m_pluginReplacementScriptObject.setWeakly(result.scriptObject);
+#endif
+
+    if (result.success) {
+        setDisplayState(DisplayingPluginReplacement);
+        invalidateStyleAndRenderersForSubtree();
+    }
 }
 
-bool HTMLPlugInElement::requestObject(const String&, const String&, const Vector<String>&, const Vector<String>&)
+#if PLATFORM(COCOA)
+static void registrar(const ReplacementPlugin&);
+#endif
+
+static Vector<ReplacementPlugin*>& registeredPluginReplacements()
 {
-    return false;
+    static NeverDestroyed<Vector<ReplacementPlugin*>> registeredReplacements;
+    static bool enginesQueried = false;
+    
+    if (enginesQueried)
+        return registeredReplacements;
+    enginesQueried = true;
+
+#if PLATFORM(COCOA)
+    YouTubePluginReplacement::registerPluginReplacement(registrar);
+#endif
+    
+    return registeredReplacements;
 }
 
+#if PLATFORM(COCOA)
+static void registrar(const ReplacementPlugin& replacement)
+{
+    registeredPluginReplacements().append(new ReplacementPlugin(replacement));
+}
+#endif
+
+static ReplacementPlugin* pluginReplacementForType(const URL& url, const String& mimeType)
+{
+    Vector<ReplacementPlugin*>& replacements = registeredPluginReplacements();
+    if (replacements.isEmpty())
+        return nullptr;
+
+    String extension;
+    auto lastPathComponent = url.lastPathComponent();
+    size_t dotOffset = lastPathComponent.reverseFind('.');
+    if (dotOffset != notFound)
+        extension = lastPathComponent.substring(dotOffset + 1).toString();
+
+    String type = mimeType;
+    if (type.isEmpty() && url.protocolIsData())
+        type = mimeTypeFromDataURL(url.string());
+    
+    if (type.isEmpty() && !extension.isEmpty()) {
+        for (auto* replacement : replacements) {
+            if (replacement->supportsFileExtension(extension) && replacement->supportsURL(url))
+                return replacement;
+        }
+    }
+    
+    if (type.isEmpty()) {
+        if (extension.isEmpty())
+            return nullptr;
+        type = MIMETypeRegistry::mediaMIMETypeForExtension(extension);
+    }
+
+    if (type.isEmpty())
+        return nullptr;
+
+    for (auto* replacement : replacements) {
+        if (replacement->supportsType(type) && replacement->supportsURL(url))
+            return replacement;
+    }
+
+    return nullptr;
+}
+
+bool HTMLPlugInElement::requestObject(const String& relativeURL, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
+{
+    if (m_pluginReplacement)
+        return true;
+
+    URL completedURL;
+    if (!relativeURL.isEmpty())
+        completedURL = document().completeURL(relativeURL);
+
+    ReplacementPlugin* replacement = pluginReplacementForType(completedURL, mimeType);
+    if (!replacement || !replacement->isEnabledBySettings(document().settings()))
+        return false;
+
+    LOG(Plugins, "%p - Found plug-in replacement for %s.", this, completedURL.string().utf8().data());
+
+    m_pluginReplacement = replacement->create(*this, paramNames, paramValues);
+    setDisplayState(PreparingPluginReplacement);
+    return true;
+}
+
+JSC::JSObject* HTMLPlugInElement::scriptObjectForPluginReplacement()
+{
+#if PLATFORM(COCOA)
+    JSC::JSValue value = m_pluginReplacementScriptObject.getValue();
+    if (!value)
+        return nullptr;
+    return value.getObject();
+#else
+    return nullptr;
+#endif
+}
+
 bool HTMLPlugInElement::isBelowSizeThreshold() const
 {
     auto* renderObject = renderer();

Modified: branches/safari-613-branch/Source/WebCore/html/HTMLPlugInElement.h (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/html/HTMLPlugInElement.h	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/html/HTMLPlugInElement.h	2022-03-22 17:54:38 UTC (rev 291634)
@@ -35,6 +35,7 @@
 
 namespace WebCore {
 
+class PluginReplacement;
 class RenderWidget;
 class Widget;
 
@@ -58,6 +59,11 @@
     DisplayState displayState() const { return m_displayState; }
     void setDisplayState(DisplayState);
 
+    JSC::JSObject* scriptObjectForPluginReplacement();
+#if PLATFORM(COCOA)
+    JSValueInWrappedObject& pluginReplacementScriptObject() { return m_pluginReplacementScriptObject; }
+#endif
+
     bool isCapturingMouseEvents() const { return m_isCapturingMouseEvents; }
     void setIsCapturingMouseEvents(bool capturing) { m_isCapturingMouseEvents = capturing; }
 
@@ -113,6 +119,10 @@
 
     RefPtr<JSC::Bindings::Instance> m_instance;
     Timer m_swapRendererTimer;
+    RefPtr<PluginReplacement> m_pluginReplacement;
+#if PLATFORM(COCOA)
+    JSValueInWrappedObject m_pluginReplacementScriptObject;
+#endif
     bool m_isCapturingMouseEvents { false };
     bool m_inBeforeLoadEventHandler { false };
     DisplayState m_displayState { Playing };

Modified: branches/safari-613-branch/Source/WebCore/html/shadow/ShadowPseudoIds.cpp (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/html/shadow/ShadowPseudoIds.cpp	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/html/shadow/ShadowPseudoIds.cpp	2022-03-22 17:54:38 UTC (rev 291634)
@@ -219,6 +219,12 @@
     return webkitMeterEvenLessGoodValue;
 }
 
+const AtomString& webkitPluginReplacement()
+{
+    static MainThreadNeverDestroyed<const AtomString> webkitPluginReplacement("-webkit-plugin-replacement", AtomString::ConstructFromLiteral);
+    return webkitPluginReplacement;
+}
+
 const AtomString& webkitProgressBar()
 {
     static MainThreadNeverDestroyed<const AtomString> webkitProgressBar("-webkit-progress-bar", AtomString::ConstructFromLiteral);

Modified: branches/safari-613-branch/Source/WebCore/html/shadow/ShadowPseudoIds.h (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/html/shadow/ShadowPseudoIds.h	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/html/shadow/ShadowPseudoIds.h	2022-03-22 17:54:38 UTC (rev 291634)
@@ -79,6 +79,8 @@
 const AtomString& webkitMeterSuboptimumValue();
 const AtomString& webkitMeterEvenLessGoodValue();
 
+const AtomString& webkitPluginReplacement();
+
 const AtomString& webkitProgressBar();
 const AtomString& webkitProgressValue();
 const AtomString& webkitProgressInnerElement();

Added: branches/safari-613-branch/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.cpp (0 => 291634)


--- branches/safari-613-branch/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.cpp	                        (rev 0)
+++ branches/safari-613-branch/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.cpp	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012-2016 Apple Inc. All rights reserved.
+ *
+ * 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 "YouTubeEmbedShadowElement.h"
+
+#include "RenderBlockFlow.h"
+#include "ShadowPseudoIds.h"
+#include <wtf/IsoMallocInlines.h>
+
+namespace WebCore {
+
+WTF_MAKE_ISO_ALLOCATED_IMPL(YouTubeEmbedShadowElement);
+
+Ref<YouTubeEmbedShadowElement> YouTubeEmbedShadowElement::create(Document& document)
+{
+    auto element = adoptRef(*new YouTubeEmbedShadowElement(document));
+    element->setPseudo(ShadowPseudoIds::webkitPluginReplacement());
+    return element;
+}
+
+YouTubeEmbedShadowElement::YouTubeEmbedShadowElement(Document& document)
+    : HTMLDivElement(HTMLNames::divTag, document)
+{
+}
+
+RenderPtr<RenderElement> YouTubeEmbedShadowElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
+{
+    return createRenderer<RenderBlockFlow>(*this, WTFMove(style));
+}
+
+}

Added: branches/safari-613-branch/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.h (0 => 291634)


--- branches/safari-613-branch/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.h	                        (rev 0)
+++ branches/safari-613-branch/Source/WebCore/html/shadow/YouTubeEmbedShadowElement.h	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
+ *
+ * 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 "HTMLDivElement.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class YouTubeEmbedShadowElement final : public HTMLDivElement {
+    WTF_MAKE_ISO_ALLOCATED(YouTubeEmbedShadowElement);
+public:
+    static Ref<YouTubeEmbedShadowElement> create(Document&);
+
+    RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final;
+
+private:
+    YouTubeEmbedShadowElement(Document&);
+};
+
+} // namespace WebCore

Modified: branches/safari-613-branch/Source/WebCore/page/Settings.yaml (291633 => 291634)


--- branches/safari-613-branch/Source/WebCore/page/Settings.yaml	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Source/WebCore/page/Settings.yaml	2022-03-22 17:54:38 UTC (rev 291634)
@@ -632,3 +632,10 @@
   defaultValue:
     WebCore:
       default: false
+
+YouTubeFlashPluginReplacementEnabled:
+  type: bool
+  defaultValue:
+    WebCore:
+      PLATFORM(COCOA): true
+      default: false

Modified: branches/safari-613-branch/Tools/ChangeLog (291633 => 291634)


--- branches/safari-613-branch/Tools/ChangeLog	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Tools/ChangeLog	2022-03-22 17:54:38 UTC (rev 291634)
@@ -1,3 +1,86 @@
+2022-03-21  Alan Coon  <alanc...@apple.com>
+
+        Cherry-pick r290519. rdar://problem/89148022
+
+    Re-add YouTubePluginReplacement, removed in r285252
+    https://bugs.webkit.org/show_bug.cgi?id=237182
+    Source/WebCore:
+    
+    <rdar://89148022>
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
+    Reviewed by Chris Dumez.
+    
+    Tests: security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html
+           security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html
+           security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html
+           security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html
+    
+    Its removal broke webpages that work in Chrome and Firefox, so back it comes.
+    
+    * Headers.cmake:
+    * Modules/plugins: Copied from Source/WebCore/Modules/plugins.
+    * SourcesCocoa.txt:
+    * WebCore.xcodeproj/project.pbxproj:
+    * bindings/js/JSPluginElementFunctions.cpp:
+    (WebCore::pluginScriptObject):
+    * bindings/scripts/CodeGeneratorJS.pm:
+    (GenerateImplementation):
+    * bindings/scripts/test/JS/JSTestPluginInterface.cpp:
+    (WebCore::JSTestPluginInterface::visitChildrenImpl):
+    * html/HTMLPlugInElement.cpp:
+    (WebCore::HTMLPlugInElement::createElementRenderer):
+    (WebCore::HTMLPlugInElement::didAddUserAgentShadowRoot):
+    (WebCore::registrar):
+    (WebCore::pluginReplacementForType):
+    (WebCore::HTMLPlugInElement::requestObject):
+    (WebCore::HTMLPlugInElement::scriptObjectForPluginReplacement):
+    * html/HTMLPlugInElement.h:
+    (WebCore::HTMLPlugInElement::pluginReplacementScriptObject):
+    * html/shadow/ShadowPseudoIds.cpp:
+    (WebCore::ShadowPseudoIds::webkitPluginReplacement):
+    * html/shadow/ShadowPseudoIds.h:
+    * html/shadow/YouTubeEmbedShadowElement.cpp:
+    * html/shadow/YouTubeEmbedShadowElement.h:
+    * page/Settings.yaml:
+    
+    Tools:
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
+    Reviewed by Chris Dumez.
+    
+    * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+    * TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp:
+    
+    LayoutTests:
+    
+    Patch by Alex Christensen <achristen...@webkit.org> on 2022-02-25
+    Reviewed by Chris Dumez.
+    
+    * TestExpectations:
+    * platform/ios-wk2/TestExpectations:
+    * platform/win/TestExpectations:
+    * security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement-expected.txt.
+    * security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/object-src-none-blocks-youtube-plugin-replacement.html.
+    * security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement-expected.txt.
+    * security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-allows-youtube-plugin-replacement.html.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-expected.txt.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type-expected.txt.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement-without-mime-type.html.
+    * security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html: Copied from LayoutTests/security/contentSecurityPolicy/plugins-types-blocks-youtube-plugin-replacement.html.
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@290519 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2022-02-25  Alex Christensen  <achristen...@webkit.org>
+
+            Re-add YouTubePluginReplacement, removed in r285252
+            https://bugs.webkit.org/show_bug.cgi?id=237182
+
+            Reviewed by Chris Dumez.
+
+            * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+            * TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp:
+
 2022-03-07  Russell Epstein  <repst...@apple.com>
 
         Cherry-pick r289255. rdar://problem/88490742

Modified: branches/safari-613-branch/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (291633 => 291634)


--- branches/safari-613-branch/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2022-03-22 17:54:28 UTC (rev 291633)
+++ branches/safari-613-branch/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2022-03-22 17:54:38 UTC (rev 291634)
@@ -389,6 +389,7 @@
 		5C2936961D5C00ED00DEAB1E /* CookieMessage.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5C2936941D5BFD1900DEAB1E /* CookieMessage.html */; };
 		5C2C01A82734883600F89D37 /* CrossThreadCopier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 278DE64B22B8D611004E0E7A /* CrossThreadCopier.cpp */; };
 		5C4259462266A68A0039AA7A /* BasicProposedCredentialPlugIn.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C42594422669E9B0039AA7A /* BasicProposedCredentialPlugIn.mm */; };
+		5C581D3227C8A01C006B3BC4 /* YouTubePluginReplacement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C581D3127C8A01C006B3BC4 /* YouTubePluginReplacement.cpp */; };
 		5C6E27A7224EEBEA00128736 /* URLCanonicalization.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C6E27A6224EEBEA00128736 /* URLCanonicalization.mm */; };
 		5C7101C725DD98B600686200 /* test_print.pdf in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5C7101C625DD988700686200 /* test_print.pdf */; };
 		5C75716122124C5200B9E5AC /* BundleRetainPagePlugIn.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C75715F221249BD00B9E5AC /* BundleRetainPagePlugIn.mm */; };
@@ -2220,6 +2221,7 @@
 		5C3B1D2522A74EA400BCF4D0 /* ContextMenus.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContextMenus.mm; sourceTree = "<group>"; };
 		5C42594422669E9B0039AA7A /* BasicProposedCredentialPlugIn.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BasicProposedCredentialPlugIn.mm; sourceTree = "<group>"; };
 		5C4A84941F7EEFD400ACFC54 /* Configuration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Configuration.mm; sourceTree = "<group>"; };
+		5C581D3127C8A01C006B3BC4 /* YouTubePluginReplacement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YouTubePluginReplacement.cpp; sourceTree = "<group>"; };
 		5C5E633D1D0B67940085A025 /* UniqueRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniqueRef.cpp; sourceTree = "<group>"; };
 		5C69BDD41F82A7EB000F4F4B /* _javascript_DuringNavigation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _javascript_DuringNavigation.mm; sourceTree = "<group>"; };
 		5C6E27A6224EEBEA00128736 /* URLCanonicalization.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = URLCanonicalization.mm; sourceTree = "<group>"; };
@@ -3767,6 +3769,7 @@
 				7AD3FE8D1D75FB8D00B169A4 /* TransformationMatrix.cpp */,
 				57D1D75E21DCB7A80093E86A /* U2fCommandConstructorTest.cpp */,
 				E3A1E77E21B25B39008C6007 /* URLParserTextEncoding.cpp */,
+				5C581D3127C8A01C006B3BC4 /* YouTubePluginReplacement.cpp */,
 			);
 			path = WebCore;
 			sourceTree = "<group>";
@@ -5851,6 +5854,7 @@
 				E520A36B25AFB76C00526CB9 /* WKWebViewTitlebarSeparatorTests.mm in Sources */,
 				7C74C8FA22DFBA9600DA2DAB /* WTFStringUtilities.cpp in Sources */,
 				C14D304624B4C3BA00480387 /* XPCEndpoint.mm in Sources */,
+				5C581D3227C8A01C006B3BC4 /* YouTubePluginReplacement.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Added: branches/safari-613-branch/Tools/TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp (0 => 291634)


--- branches/safari-613-branch/Tools/TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp	                        (rev 0)
+++ branches/safari-613-branch/Tools/TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp	2022-03-22 17:54:38 UTC (rev 291634)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * 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 <WebCore/YouTubePluginReplacement.h>
+#include <wtf/MainThread.h>
+#include <wtf/URL.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class YouTubePluginReplacementTest : public testing::Test {
+public:
+    void SetUp() final
+    {
+        WTF::initializeMainThread();
+    }
+};
+
+static bool test(const String& inputURLString, const String& expectedURLString)
+{
+    URL inputURL(URL(), inputURLString);
+    String actualURLString = YouTubePluginReplacement::youTubeURLFromAbsoluteURL(inputURL, inputURLString);
+    return actualURLString.utf8() == expectedURLString.utf8();
+}
+
+TEST_F(YouTubePluginReplacementTest, YouTubeURLFromAbsoluteURL)
+{
+    // YouTube non-video URL, not expected to be transformed.
+    EXPECT_TRUE(test("https://www.youtube.com", "https://www.youtube.com"));
+
+    // Basic YouTube video links, expected to be transformed.
+    EXPECT_TRUE(test("https://www.youtube.com/v/dQw4w9WgXcQ", "https://www.youtube.com/embed/dQw4w9WgXcQ"));
+    EXPECT_TRUE(test("http://www.youtube.com/v/dQw4w9WgXcQ", "http://www.youtube.com/embed/dQw4w9WgXcQ"));
+    EXPECT_TRUE(test("https://youtube.com/v/dQw4w9WgXcQ", "https://youtube.com/embed/dQw4w9WgXcQ"));
+    EXPECT_TRUE(test("http://youtube.com/v/dQw4w9WgXcQ", "http://youtube.com/embed/dQw4w9WgXcQ"));
+
+    // With start time, preserved.
+    EXPECT_TRUE(test("http://www.youtube.com/v/dQw4w9WgXcQ?start=4", "http://www.youtube.com/embed/dQw4w9WgXcQ?start=4"));
+    EXPECT_TRUE(test("http://www.youtube.com/v/dQw4w9WgXcQ?start=4&fs=1", "http://www.youtube.com/embed/dQw4w9WgXcQ?start=4&fs=1"));
+
+    // With an invalid query (see & instead of ?), we preserve and fix the query.
+    EXPECT_TRUE(test("http://www.youtube.com/v/dQw4w9WgXcQ&start=4", "http://www.youtube.com/embed/dQw4w9WgXcQ?start=4"));
+    EXPECT_TRUE(test("http://www.youtube.com/v/dQw4w9WgXcQ&start=4&fs=1", "http://www.youtube.com/embed/dQw4w9WgXcQ?start=4&fs=1"));
+
+    // Non-Flash URL is untouched.
+    EXPECT_TRUE(test("https://www.youtube.com/embed/dQw4w9WgXcQ", "https://www.youtube.com/embed/dQw4w9WgXcQ"));
+    EXPECT_TRUE(test("http://www.youtube.com/embed/dQw4w9WgXcQ", "http://www.youtube.com/embed/dQw4w9WgXcQ"));
+    EXPECT_TRUE(test("https://youtube.com/embed/dQw4w9WgXcQ", "https://youtube.com/embed/dQw4w9WgXcQ"));
+    EXPECT_TRUE(test("http://youtube.com/embed/dQw4w9WgXcQ", "http://youtube.com/embed/dQw4w9WgXcQ"));
+    // Even with extra parameters.
+    EXPECT_TRUE(test("https://www.youtube.com/embed/dQw4w9WgXcQ?start=4", "https://www.youtube.com/embed/dQw4w9WgXcQ?start=4"));
+    EXPECT_TRUE(test("http://www.youtube.com/embed/dQw4w9WgXcQ?enablejsapi=1", "http://www.youtube.com/embed/dQw4w9WgXcQ?enablejsapi=1"));
+    // Even with an invalid "query".
+    EXPECT_TRUE(test("https://www.youtube.com/embed/dQw4w9WgXcQ&start=4", "https://www.youtube.com/embed/dQw4w9WgXcQ&start=4"));
+
+    // Don't transform anything with a non "/v/" path component immediately following the domain.
+    EXPECT_TRUE(test("https://www.youtube.com/something/v/dQw4w9WgXcQ", "https://www.youtube.com/something/v/dQw4w9WgXcQ"));
+
+    // Non-YouTube domain whose path looks like a Flash video shouldn't be transformed.
+    EXPECT_TRUE(test("https://www.notyoutube.com/v/dQw4w9WgXcQ", "https://www.notyoutube.com/v/dQw4w9WgXcQ"));
+}
+
+} // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to