Title: [293261] branches/safari-613.2.7.1-branch
Revision
293261
Author
repst...@apple.com
Date
2022-04-22 16:02:57 -0700 (Fri, 22 Apr 2022)

Log Message

Cherry-pick r291589. rdar://problem/90511155

    LayoutTests/imported/w3c:
    BroadcastChannel instances in distinct opaque origins can communicate
    https://bugs.webkit.org/show_bug.cgi?id=238090
    <rdar://problem/90511155>

    Reviewed by Alex Christensen.

    Import web-platform-tests test coverage.

    * web-platform-tests/webmessaging/broadcastchannel/opaque-origin-expected.txt: Added.
    * web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html: Added.
    * web-platform-tests/webmessaging/broadcastchannel/w3c-import.log:

    Source/WebCore:
    BroadcastChannel instances in distinct opaque origins can communicate
    https://bugs.webkit.org/show_bug.cgi?id=238090
    <rdar://problem/90511155>

    Reviewed by Alex Christensen.

    The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
    which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
    SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
    unique SecurityOrigins, they would compare as equal.

    To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
    to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
    objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
    would not be equal but the same unique SecurityOrigin would be. I then used this new
    PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
    ClientOrigin. This allows communication between several BroadcastChannels from the same
    unique origin, while preventing communication between distinct opaque origins.

    When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
    the Network Process at all since the destination can only be in the same WebProcess.

    Test: imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html

    * Headers.cmake:
    * WebCore.xcodeproj/project.pbxproj:
    * dom/BroadcastChannel.cpp:
    (WebCore::shouldPartitionOrigin):
    (WebCore::BroadcastChannel::MainThreadBridge::registerChannel):
    (WebCore::BroadcastChannel::MainThreadBridge::unregisterChannel):
    (WebCore::BroadcastChannel::MainThreadBridge::postMessage):
    * dom/BroadcastChannelRegistry.h:
    * loader/EmptyClients.cpp:
    * page/PartitionedSecurityOrigin.h: Added.
    (WebCore::PartitionedSecurityOrigin::PartitionedSecurityOrigin):
    (WebCore::PartitionedSecurityOrigin::isHashTableDeletedValue const):
    (WebCore::PartitionedSecurityOrigin::isHashTableEmptyValue const):
    (WebCore::operator==):
    (WTF::add):
    (WTF::PartitionedSecurityOriginHash::hash):
    (WTF::PartitionedSecurityOriginHash::equal):
    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::emptyValue):
    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::constructEmptyValue):
    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::isEmptyValue):
    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::peek):
    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::take):

    Source/WebKit:
    BroadcastChannel instances in distinct opaque origins can communicate
    https://bugs.webkit.org/show_bug.cgi?id=238090
    <rdar://problem/90511155>

    Reviewed by Alex Christensen.

    The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
    which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
    SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
    unique SecurityOrigins, they would compare as equal.

    To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
    to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
    objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
    would not be equal but the same unique SecurityOrigin would be. I then used this new
    PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
    ClientOrigin. This allows communication between several BroadcastChannels from the same
    unique origin, while preventing communication between distinct opaque origins.

    When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
    the Network Process at all since the destination can only be in the same WebProcess.

    * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp:
    (WebKit::toClientOrigin):
    (WebKit::WebBroadcastChannelRegistry::registerChannel):
    (WebKit::WebBroadcastChannelRegistry::unregisterChannel):
    (WebKit::WebBroadcastChannelRegistry::postMessage):
    (WebKit::WebBroadcastChannelRegistry::postMessageLocally):
    (WebKit::WebBroadcastChannelRegistry::postMessageToRemote):
    (WebKit::WebBroadcastChannelRegistry::networkProcessCrashed):
    * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h:

    Source/WebKitLegacy:
    Dust off Mac CMake build
    https://bugs.webkit.org/show_bug.cgi?id=238121

    Reviewed by Yusuke Suzuki.

    * PlatformMac.cmake:

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

Modified Paths

Added Paths

Diff

Modified: branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/ChangeLog (293260 => 293261)


--- branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/ChangeLog	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/ChangeLog	2022-04-22 23:02:57 UTC (rev 293261)
@@ -1,3 +1,125 @@
+2022-04-22  Russell Epstein  <repst...@apple.com>
+
+        Cherry-pick r291589. rdar://problem/90511155
+
+    LayoutTests/imported/w3c:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
+    
+    Reviewed by Alex Christensen.
+    
+    Import web-platform-tests test coverage.
+    
+    * web-platform-tests/webmessaging/broadcastchannel/opaque-origin-expected.txt: Added.
+    * web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html: Added.
+    * web-platform-tests/webmessaging/broadcastchannel/w3c-import.log:
+    
+    Source/WebCore:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
+    
+    Reviewed by Alex Christensen.
+    
+    The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
+    which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
+    SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
+    unique SecurityOrigins, they would compare as equal.
+    
+    To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
+    to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
+    objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
+    would not be equal but the same unique SecurityOrigin would be. I then used this new
+    PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
+    ClientOrigin. This allows communication between several BroadcastChannels from the same
+    unique origin, while preventing communication between distinct opaque origins.
+    
+    When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
+    the Network Process at all since the destination can only be in the same WebProcess.
+    
+    Test: imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html
+    
+    * Headers.cmake:
+    * WebCore.xcodeproj/project.pbxproj:
+    * dom/BroadcastChannel.cpp:
+    (WebCore::shouldPartitionOrigin):
+    (WebCore::BroadcastChannel::MainThreadBridge::registerChannel):
+    (WebCore::BroadcastChannel::MainThreadBridge::unregisterChannel):
+    (WebCore::BroadcastChannel::MainThreadBridge::postMessage):
+    * dom/BroadcastChannelRegistry.h:
+    * loader/EmptyClients.cpp:
+    * page/PartitionedSecurityOrigin.h: Added.
+    (WebCore::PartitionedSecurityOrigin::PartitionedSecurityOrigin):
+    (WebCore::PartitionedSecurityOrigin::isHashTableDeletedValue const):
+    (WebCore::PartitionedSecurityOrigin::isHashTableEmptyValue const):
+    (WebCore::operator==):
+    (WTF::add):
+    (WTF::PartitionedSecurityOriginHash::hash):
+    (WTF::PartitionedSecurityOriginHash::equal):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::emptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::constructEmptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::isEmptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::peek):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::take):
+    
+    Source/WebKit:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
+    
+    Reviewed by Alex Christensen.
+    
+    The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
+    which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
+    SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
+    unique SecurityOrigins, they would compare as equal.
+    
+    To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
+    to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
+    objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
+    would not be equal but the same unique SecurityOrigin would be. I then used this new
+    PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
+    ClientOrigin. This allows communication between several BroadcastChannels from the same
+    unique origin, while preventing communication between distinct opaque origins.
+    
+    When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
+    the Network Process at all since the destination can only be in the same WebProcess.
+    
+    * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp:
+    (WebKit::toClientOrigin):
+    (WebKit::WebBroadcastChannelRegistry::registerChannel):
+    (WebKit::WebBroadcastChannelRegistry::unregisterChannel):
+    (WebKit::WebBroadcastChannelRegistry::postMessage):
+    (WebKit::WebBroadcastChannelRegistry::postMessageLocally):
+    (WebKit::WebBroadcastChannelRegistry::postMessageToRemote):
+    (WebKit::WebBroadcastChannelRegistry::networkProcessCrashed):
+    * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h:
+    
+    Source/WebKitLegacy:
+    Dust off Mac CMake build
+    https://bugs.webkit.org/show_bug.cgi?id=238121
+    
+    Reviewed by Yusuke Suzuki.
+    
+    * PlatformMac.cmake:
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@291589 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2022-03-21  Chris Dumez  <cdu...@apple.com>
+
+            BroadcastChannel instances in distinct opaque origins can communicate
+            https://bugs.webkit.org/show_bug.cgi?id=238090
+            <rdar://problem/90511155>
+
+            Reviewed by Alex Christensen.
+
+            Import web-platform-tests test coverage.
+
+            * web-platform-tests/webmessaging/broadcastchannel/opaque-origin-expected.txt: Added.
+            * web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html: Added.
+            * web-platform-tests/webmessaging/broadcastchannel/w3c-import.log:
+
 2022-04-18  Kocsen Chung  <kocsen_ch...@apple.com>
 
         Cherry-pick r292400. rdar://problem/89382543

Added: branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin-expected.txt (0 => 293261)


--- branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin-expected.txt	                        (rev 0)
+++ branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin-expected.txt	2022-04-22 23:02:57 UTC (rev 293261)
@@ -0,0 +1,4 @@
+
+PASS Opaque origin should be serialized to "null"
+PASS BroadcastChannel messages from opaque origins should be self-contained
+

Added: branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html (0 => 293261)


--- branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html	                        (rev 0)
+++ branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html	2022-04-22 23:02:57 UTC (rev 293261)
@@ -0,0 +1,85 @@
+<!doctype html>
+<html>
+<head>
+<meta charset=utf-8>
+<title></title>
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+<!--
+promise_test(t => {
+  return new Promise((resolve) => {
+    let ifr = document.createElement("iframe");
+    ifr.src =
+      "data:text/html,<script> let bc = new BroadcastChannel(\"test\");" +
+      "bc._onmessage_ = (e) => {" +
+      "  if (e.data == \"ping\") bc.postMessage('pong');"+
+      "  else parent.postMessage({workerMessageOrigin: e.data, messageOrigin: e.origin}, \"*\"); };" +
+      "new Worker(URL.createObjectURL(new Blob([\"" +
+      "let bc2 = new BroadcastChannel('test'); bc2.postMessage('ping'); " +
+      "bc2._onmessage_ = e => bc2.postMessage(e.origin);" +
+      "\"], {type: 'text/_javascript_'}))); </script>";
+    window.addEventListener("message", t.step_func(e => {
+        assert_equals(e.data.workerMessageOrigin, "null");
+        assert_equals(e.data.messageOrigin, "null");
+        resolve();
+      }), {once: true});
+    t.add_cleanup(() => { document.body.removeChild(ifr) });
+    document.body.appendChild(ifr);
+    });
+}, "Opaque origin should be serialized to \"null\"");
+
+
+const iframe_src = (channel_name, iframe_name) => `data:text/html,<script>
+let bc2 = new BroadcastChannel("${channel_name}");
+bc2._onmessage_ = (e) => {
+  if (e.data == "from-${iframe_name}") {
+    parent.postMessage("${iframe_name}-done", "*");
+  } else {
+    parent.postMessage("fail", "*");
+  }
+};
+let bc3 = new BroadcastChannel("${channel_name}");
+bc3.postMessage("from-${iframe_name}");
+</script>`;
+
+promise_test(t => {
+  return new Promise((resolve, reject) => {
+    const channel_name = "opaque-origin-test-2";
+    const bc1 = new BroadcastChannel(channel_name);
+    bc1._onmessage_ = t.unreached_func("Received message from an opaque origin");
+
+    // We'll create an iframe and have it send a BroadcastChannel message
+    // between two instances. Once the message is received, it will postMessage
+    // back and we'll repeat this with another iframe. If the first
+    // BroadcastChannel message is received by `bc1`, or if the second
+    // BroadcastChannel message is received by `bc1` or `bc2` in the first
+    // iframe, then the test should fail.
+
+    window.addEventListener("message", e => {
+      if(e.data == "iframe1-done") {
+        let iframe2 = document.createElement("iframe");
+        iframe2.src = "" "iframe2");
+        t.add_cleanup(() => { document.body.removeChild(iframe2) });
+        document.body.appendChild(iframe2);
+      } else if(e.data == "iframe2-done") {
+        resolve();
+      } else if(e.data == "fail") {
+        reject("One opaque origin received a message from the other");
+      } else {
+        reject("An unexpected error occurred");
+      }
+    });
+
+    let iframe1 = document.createElement("iframe");
+    iframe1.src = "" "iframe1");
+    t.add_cleanup(() => { document.body.removeChild(iframe1) });
+    document.body.appendChild(iframe1);
+    });
+}, "BroadcastChannel messages from opaque origins should be self-contained");
+//-->
+</script>
+</body>
+</html>

Modified: branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/w3c-import.log (293260 => 293261)


--- branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/w3c-import.log	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/w3c-import.log	2022-04-22 23:02:57 UTC (rev 293261)
@@ -19,6 +19,7 @@
 /LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/cross-origin.html
 /LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/detached-iframe.html
 /LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/interface.any.js
+/LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html
 /LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/ordering.html
 /LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/origin.window.js
 /LayoutTests/imported/w3c/web-platform-tests/webmessaging/broadcastchannel/sandbox.html

Added: branches/safari-613.2.7.1-branch/Source/_javascript_Core/runtime/InternalFunction.cpp.orig (0 => 293261)


--- branches/safari-613.2.7.1-branch/Source/_javascript_Core/runtime/InternalFunction.cpp.orig	                        (rev 0)
+++ branches/safari-613.2.7.1-branch/Source/_javascript_Core/runtime/InternalFunction.cpp.orig	2022-04-22 23:02:57 UTC (rev 293261)
@@ -0,0 +1,208 @@
+/*
+ *  Copyright (C) 1999-2002 Harri Porten (por...@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (p...@post.com)
+ *  Copyright (C) 2004-2021 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "InternalFunction.h"
+
+#include "JSBoundFunction.h"
+#include "JSCInlines.h"
+#include "ProxyObject.h"
+
+namespace JSC {
+
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(InternalFunction);
+
+const ClassInfo InternalFunction::s_info = { "Function", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(InternalFunction) };
+
+InternalFunction::InternalFunction(VM& vm, Structure* structure, NativeFunction functionForCall, NativeFunction functionForConstruct)
+    : Base(vm, structure)
+    , m_functionForCall(functionForCall)
+    , m_functionForConstruct(functionForConstruct ? functionForConstruct : callHostFunctionAsConstructor)
+    , m_globalObject(vm, this, structure->globalObject())
+{
+    ASSERT_WITH_MESSAGE(m_functionForCall, "[[Call]] must be implemented");
+    ASSERT(m_functionForConstruct);
+
+    ASSERT(jsDynamicCast<InternalFunction*>(vm, this));
+    // JSCell::{getCallData,getConstructData} relies on the following conditions.
+    ASSERT(methodTable(vm)->getCallData == InternalFunction::info()->methodTable.getCallData);
+    ASSERT(methodTable(vm)->getConstructData == InternalFunction::info()->methodTable.getConstructData);
+    ASSERT(type() == InternalFunctionType || type() == NullSetterFunctionType);
+}
+
+void InternalFunction::finishCreation(VM& vm, unsigned length, const String& name, PropertyAdditionMode nameAdditionMode)
+{
+    Base::finishCreation(vm);
+
+    JSString* nameString = jsString(vm, name);
+    m_originalName.set(vm, this, nameString);
+    // The enumeration order is length followed by name. So, we make sure to add the properties in that order.
+    if (nameAdditionMode == PropertyAdditionMode::WithStructureTransition) {
+        putDirect(vm, vm.propertyNames->length, jsNumber(length), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
+        putDirect(vm, vm.propertyNames->name, nameString, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
+    } else {
+        putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(length), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
+        putDirectWithoutTransition(vm, vm.propertyNames->name, nameString, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
+    }
+}
+
+void InternalFunction::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+}
+
+template<typename Visitor>
+void InternalFunction::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+    InternalFunction* thisObject = jsCast<InternalFunction*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    Base::visitChildren(thisObject, visitor);
+    
+    visitor.append(thisObject->m_originalName);
+}
+
+DEFINE_VISIT_CHILDREN_WITH_MODIFIER(JS_EXPORT_PRIVATE, InternalFunction);
+
+String InternalFunction::name()
+{
+    const String& name = m_originalName->tryGetValue();
+    ASSERT(name); // m_originalName was built from a String, and hence, there is no rope to resolve.
+    return name;
+}
+
+String InternalFunction::displayName(VM& vm)
+{
+    JSValue displayName = getDirect(vm, vm.propertyNames->displayName);
+    
+    if (displayName && isJSString(displayName))
+        return asString(displayName)->tryGetValue();
+    
+    return String();
+}
+
+CallData InternalFunction::getCallData(JSCell* cell)
+{
+    // Keep this function OK for invocation from concurrent compilers.
+    auto* function = jsCast<InternalFunction*>(cell);
+    ASSERT(function->m_functionForCall);
+
+    CallData callData;
+    callData.type = CallData::Type::Native;
+    callData.native.function = function->m_functionForCall;
+    return callData;
+}
+
+CallData InternalFunction::getConstructData(JSCell* cell)
+{
+    // Keep this function OK for invocation from concurrent compilers.
+    CallData constructData;
+    auto* function = jsCast<InternalFunction*>(cell);
+    if (function->m_functionForConstruct != callHostFunctionAsConstructor) {
+        constructData.type = CallData::Type::Native;
+        constructData.native.function = function->m_functionForConstruct;
+    }
+    return constructData;
+}
+
+String InternalFunction::calculatedDisplayName(VM& vm)
+{
+    String explicitName = displayName(vm);
+    
+    if (!explicitName.isEmpty())
+        return explicitName;
+    
+    return name();
+}
+
+Structure* InternalFunction::createSubclassStructure(JSGlobalObject* globalObject, JSObject* newTarget, Structure* baseClass)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    ASSERT(baseClass->hasMonoProto());
+
+    // newTarget may be an InternalFunction if we were called from Reflect.construct.
+    JSFunction* targetFunction = jsDynamicCast<JSFunction*>(vm, newTarget);
+
+    if (LIKELY(targetFunction)) {
+        FunctionRareData* rareData = targetFunction->ensureRareData(vm);
+        Structure* structure = rareData->internalFunctionAllocationStructure();
+        if (LIKELY(structure && structure->classInfo() == baseClass->classInfo() && structure->globalObject() == baseClass->globalObject()))
+            return structure;
+
+        // Note, Reflect.construct might cause the profile to churn but we don't care.
+        JSValue prototypeValue = targetFunction->get(globalObject, vm.propertyNames->prototype);
+        RETURN_IF_EXCEPTION(scope, nullptr);
+        if (JSObject* prototype = jsDynamicCast<JSObject*>(vm, prototypeValue))
+            return rareData->createInternalFunctionAllocationStructureFromBase(vm, prototype->globalObject(vm), prototype, baseClass);
+    } else {
+        JSValue prototypeValue = newTarget->get(globalObject, vm.propertyNames->prototype);
+        RETURN_IF_EXCEPTION(scope, nullptr);
+        if (JSObject* prototype = jsDynamicCast<JSObject*>(vm, prototypeValue)) {
+            // This only happens if someone Reflect.constructs our builtin constructor with another builtin constructor as the new.target.
+            // Thus, we don't care about the cost of looking up the structure from our hash table every time.
+            return vm.structureCache.emptyStructureForPrototypeFromBaseStructure(prototype->globalObject(vm), prototype, baseClass);
+        }
+    }
+    
+    return baseClass;
+}
+
+InternalFunction* InternalFunction::createFunctionThatMasqueradesAsUndefined(VM& vm, JSGlobalObject* globalObject, unsigned length, const String& name, NativeFunction nativeFunction)
+{
+    Structure* structure = Structure::create(vm, globalObject, globalObject->objectPrototype(), TypeInfo(InternalFunctionType, InternalFunction::StructureFlags | MasqueradesAsUndefined), InternalFunction::info());
+    globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(globalObject->vm(), "Allocated masquerading object");
+    InternalFunction* function = new (NotNull, allocateCell<InternalFunction>(vm)) InternalFunction(vm, structure, nativeFunction);
+    function->finishCreation(vm, length, name, PropertyAdditionMode::WithoutStructureTransition);
+    return function;
+}
+
+// https://tc39.es/ecma262/#sec-getfunctionrealm
+JSGlobalObject* getFunctionRealm(JSGlobalObject* globalObject, JSObject* object)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    ASSERT(object->isCallable(vm));
+
+    while (true) {
+        if (object->inherits<JSBoundFunction>(vm)) {
+            object = jsCast<JSBoundFunction*>(object)->targetFunction();
+            continue;
+        }
+
+        if (object->type() == ProxyObjectType) {
+            auto* proxy = jsCast<ProxyObject*>(object);
+            if (proxy->isRevoked()) {
+                throwTypeError(globalObject, scope, "Cannot get function realm from revoked Proxy"_s);
+                return nullptr;
+            }
+            object = proxy->target();
+            continue;
+        }
+
+        return object->globalObject(vm);
+    }
+}
+
+
+} // namespace JSC

Modified: branches/safari-613.2.7.1-branch/Source/WebCore/ChangeLog (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebCore/ChangeLog	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebCore/ChangeLog	2022-04-22 23:02:57 UTC (rev 293261)
@@ -1,5 +1,162 @@
 2022-04-22  Russell Epstein  <repst...@apple.com>
 
+        Cherry-pick r291589. rdar://problem/90511155
+
+    LayoutTests/imported/w3c:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
+    
+    Reviewed by Alex Christensen.
+    
+    Import web-platform-tests test coverage.
+    
+    * web-platform-tests/webmessaging/broadcastchannel/opaque-origin-expected.txt: Added.
+    * web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html: Added.
+    * web-platform-tests/webmessaging/broadcastchannel/w3c-import.log:
+    
+    Source/WebCore:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
+    
+    Reviewed by Alex Christensen.
+    
+    The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
+    which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
+    SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
+    unique SecurityOrigins, they would compare as equal.
+    
+    To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
+    to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
+    objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
+    would not be equal but the same unique SecurityOrigin would be. I then used this new
+    PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
+    ClientOrigin. This allows communication between several BroadcastChannels from the same
+    unique origin, while preventing communication between distinct opaque origins.
+    
+    When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
+    the Network Process at all since the destination can only be in the same WebProcess.
+    
+    Test: imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html
+    
+    * Headers.cmake:
+    * WebCore.xcodeproj/project.pbxproj:
+    * dom/BroadcastChannel.cpp:
+    (WebCore::shouldPartitionOrigin):
+    (WebCore::BroadcastChannel::MainThreadBridge::registerChannel):
+    (WebCore::BroadcastChannel::MainThreadBridge::unregisterChannel):
+    (WebCore::BroadcastChannel::MainThreadBridge::postMessage):
+    * dom/BroadcastChannelRegistry.h:
+    * loader/EmptyClients.cpp:
+    * page/PartitionedSecurityOrigin.h: Added.
+    (WebCore::PartitionedSecurityOrigin::PartitionedSecurityOrigin):
+    (WebCore::PartitionedSecurityOrigin::isHashTableDeletedValue const):
+    (WebCore::PartitionedSecurityOrigin::isHashTableEmptyValue const):
+    (WebCore::operator==):
+    (WTF::add):
+    (WTF::PartitionedSecurityOriginHash::hash):
+    (WTF::PartitionedSecurityOriginHash::equal):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::emptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::constructEmptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::isEmptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::peek):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::take):
+    
+    Source/WebKit:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
+    
+    Reviewed by Alex Christensen.
+    
+    The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
+    which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
+    SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
+    unique SecurityOrigins, they would compare as equal.
+    
+    To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
+    to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
+    objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
+    would not be equal but the same unique SecurityOrigin would be. I then used this new
+    PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
+    ClientOrigin. This allows communication between several BroadcastChannels from the same
+    unique origin, while preventing communication between distinct opaque origins.
+    
+    When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
+    the Network Process at all since the destination can only be in the same WebProcess.
+    
+    * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp:
+    (WebKit::toClientOrigin):
+    (WebKit::WebBroadcastChannelRegistry::registerChannel):
+    (WebKit::WebBroadcastChannelRegistry::unregisterChannel):
+    (WebKit::WebBroadcastChannelRegistry::postMessage):
+    (WebKit::WebBroadcastChannelRegistry::postMessageLocally):
+    (WebKit::WebBroadcastChannelRegistry::postMessageToRemote):
+    (WebKit::WebBroadcastChannelRegistry::networkProcessCrashed):
+    * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h:
+    
+    Source/WebKitLegacy:
+    Dust off Mac CMake build
+    https://bugs.webkit.org/show_bug.cgi?id=238121
+    
+    Reviewed by Yusuke Suzuki.
+    
+    * PlatformMac.cmake:
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@291589 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2022-03-21  Chris Dumez  <cdu...@apple.com>
+
+            BroadcastChannel instances in distinct opaque origins can communicate
+            https://bugs.webkit.org/show_bug.cgi?id=238090
+            <rdar://problem/90511155>
+
+            Reviewed by Alex Christensen.
+
+            The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
+            which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
+            SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
+            unique SecurityOrigins, they would compare as equal.
+
+            To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
+            to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
+            objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
+            would not be equal but the same unique SecurityOrigin would be. I then used this new
+            PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
+            ClientOrigin. This allows communication between several BroadcastChannels from the same
+            unique origin, while preventing communication between distinct opaque origins.
+
+            When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
+            the Network Process at all since the destination can only be in the same WebProcess.
+
+            Test: imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html
+
+            * Headers.cmake:
+            * WebCore.xcodeproj/project.pbxproj:
+            * dom/BroadcastChannel.cpp:
+            (WebCore::shouldPartitionOrigin):
+            (WebCore::BroadcastChannel::MainThreadBridge::registerChannel):
+            (WebCore::BroadcastChannel::MainThreadBridge::unregisterChannel):
+            (WebCore::BroadcastChannel::MainThreadBridge::postMessage):
+            * dom/BroadcastChannelRegistry.h:
+            * loader/EmptyClients.cpp:
+            * page/PartitionedSecurityOrigin.h: Added.
+            (WebCore::PartitionedSecurityOrigin::PartitionedSecurityOrigin):
+            (WebCore::PartitionedSecurityOrigin::isHashTableDeletedValue const):
+            (WebCore::PartitionedSecurityOrigin::isHashTableEmptyValue const):
+            (WebCore::operator==):
+            (WTF::add):
+            (WTF::PartitionedSecurityOriginHash::hash):
+            (WTF::PartitionedSecurityOriginHash::equal):
+            (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::emptyValue):
+            (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::constructEmptyValue):
+            (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::isEmptyValue):
+            (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::peek):
+            (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::take):
+
+2022-04-22  Russell Epstein  <repst...@apple.com>
+
         Cherry-pick r292878. rdar://problem/90248865
 
     ScriptDisallowedScope::isEventAllowedInMainThread assert failure when activating AudioSession

Modified: branches/safari-613.2.7.1-branch/Source/WebCore/Headers.cmake (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebCore/Headers.cmake	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebCore/Headers.cmake	2022-04-22 23:02:57 UTC (rev 293261)
@@ -1125,6 +1125,7 @@
     page/PageOverlay.h
     page/PageOverlayController.h
     page/PagePasteboardContext.h
+    page/PartitionedSecurityOrigin.h
     page/PerformanceLogging.h
     page/PerformanceLoggingClient.h
     page/PointerCaptureController.h

Modified: branches/safari-613.2.7.1-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-04-22 23:02:57 UTC (rev 293261)
@@ -1346,6 +1346,7 @@
 		4682D2001F79783000C863DB /* StoredCredentialsPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4682D1FF1F79782300C863DB /* StoredCredentialsPolicy.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		468344E01EDDFAAA00B7795B /* DOMRectList.h in Headers */ = {isa = PBXBuildFile; fileRef = 468344DE1EDDFA5F00B7795B /* DOMRectList.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		4688EE3C26DD2610002AF5C4 /* CrossOriginMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4688EE3A26DD260C002AF5C4 /* CrossOriginMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		46893B8427E8D74C002CC13D /* PartitionedSecurityOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 46893B8327E8D716002CC13D /* PartitionedSecurityOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		469CCCFE269D021C006E0314 /* BroadcastChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 469CCCFC269D0202006E0314 /* BroadcastChannel.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		469D77B82701625100142FA6 /* NavigationRequester.h in Headers */ = {isa = PBXBuildFile; fileRef = 469D77B62701625000142FA6 /* NavigationRequester.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		46AAAA3D25D3632000BAF42F /* AudioFileReaderCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 46AAAA3A25D3631400BAF42F /* AudioFileReaderCocoa.h */; };
@@ -9215,6 +9216,7 @@
 		468344DD1EDDFA5F00B7795B /* DOMRectList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DOMRectList.cpp; sourceTree = "<group>"; };
 		468344DE1EDDFA5F00B7795B /* DOMRectList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DOMRectList.h; sourceTree = "<group>"; };
 		4688EE3A26DD260C002AF5C4 /* CrossOriginMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CrossOriginMode.h; sourceTree = "<group>"; };
+		46893B8327E8D716002CC13D /* PartitionedSecurityOrigin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PartitionedSecurityOrigin.h; sourceTree = "<group>"; };
 		468B8BDE25CC849300F67822 /* JSBaseAudioContextCustom.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSBaseAudioContextCustom.cpp; sourceTree = "<group>"; };
 		469CCCFA269D0202006E0314 /* BroadcastChannel.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BroadcastChannel.cpp; sourceTree = "<group>"; };
 		469CCCFC269D0202006E0314 /* BroadcastChannel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BroadcastChannel.h; sourceTree = "<group>"; };
@@ -24084,6 +24086,7 @@
 				F40DAAEE25D9F3BF0011B4FA /* PagePasteboardContext.h */,
 				371E65CD13661EED00BEEDB0 /* PageSerializer.cpp */,
 				371E65CB13661EDC00BEEDB0 /* PageSerializer.h */,
+				46893B8327E8D716002CC13D /* PartitionedSecurityOrigin.h */,
 				BC4A53282560563B0028C592 /* PDFImageCachingPolicy.h */,
 				7C72471E2516758800C363CD /* Performance+NavigationTiming.idl */,
 				7C72471C251674CE00C363CD /* Performance+PerformanceTimeline.idl */,
@@ -36372,6 +36375,7 @@
 				447958041643B49A001E0A7F /* ParsedContentType.h in Headers */,
 				5C4A0FDA25C3449A00D9EE97 /* ParsedRequestRange.h in Headers */,
 				536D5A23193E8E0C00CE4CAB /* ParsingUtilities.h in Headers */,
+				46893B8427E8D74C002CC13D /* PartitionedSecurityOrigin.h in Headers */,
 				F55B3DCA1251F12D003EF269 /* PasswordInputType.h in Headers */,
 				4B2708C70AF19EE40065127F /* Pasteboard.h in Headers */,
 				F40DAAEC25D9F25E0011B4FA /* PasteboardContext.h in Headers */,

Modified: branches/safari-613.2.7.1-branch/Source/WebCore/dom/BroadcastChannel.cpp (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebCore/dom/BroadcastChannel.cpp	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebCore/dom/BroadcastChannel.cpp	2022-04-22 23:02:57 UTC (rev 293261)
@@ -30,6 +30,7 @@
 #include "EventNames.h"
 #include "MessageEvent.h"
 #include "Page.h"
+#include "PartitionedSecurityOrigin.h"
 #include "SecurityOrigin.h"
 #include "SerializedScriptValue.h"
 #include "WorkerGlobalScope.h"
@@ -86,7 +87,7 @@
     WeakPtr<BroadcastChannel> m_broadcastChannel;
     const BroadcastChannelIdentifier m_identifier;
     const String m_name; // Main thread only.
-    ClientOrigin m_origin; // Main thread only.
+    std::optional<PartitionedSecurityOrigin> m_origin; // Main thread only.
 };
 
 BroadcastChannel::MainThreadBridge::MainThreadBridge(BroadcastChannel& channel, const String& name)
@@ -120,9 +121,9 @@
 void BroadcastChannel::MainThreadBridge::registerChannel()
 {
     ensureOnMainThread([this, contextIdentifier = m_broadcastChannel->scriptExecutionContext()->identifier()](auto& document) {
-        m_origin = { shouldPartitionOrigin(document) ? document.topOrigin().data() : document.securityOrigin().data(), document.securityOrigin().data() };
+        m_origin = PartitionedSecurityOrigin { shouldPartitionOrigin(document) ? document.topOrigin() : document.securityOrigin(), document.securityOrigin() };
         if (auto* page = document.page())
-            page->broadcastChannelRegistry().registerChannel(m_origin, m_name, m_identifier);
+            page->broadcastChannelRegistry().registerChannel(*m_origin, m_name, m_identifier);
         channelToContextIdentifier().add(m_identifier, contextIdentifier);
     });
 }
@@ -131,7 +132,7 @@
 {
     ensureOnMainThread([this](auto& document) {
         if (auto* page = document.page())
-            page->broadcastChannelRegistry().unregisterChannel(m_origin, m_name, m_identifier);
+            page->broadcastChannelRegistry().unregisterChannel(*m_origin, m_name, m_identifier);
         channelToContextIdentifier().remove(m_identifier);
     });
 }
@@ -144,7 +145,7 @@
             return;
 
         auto blobHandles = message->blobHandles();
-        page->broadcastChannelRegistry().postMessage(m_origin, m_name, m_identifier, WTFMove(message), [blobHandles = WTFMove(blobHandles)] {
+        page->broadcastChannelRegistry().postMessage(*m_origin, m_name, m_identifier, WTFMove(message), [blobHandles = WTFMove(blobHandles)] {
             // Keeps Blob data inside messageData alive until the message has been delivered.
         });
     });

Modified: branches/safari-613.2.7.1-branch/Source/WebCore/dom/BroadcastChannelRegistry.h (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebCore/dom/BroadcastChannelRegistry.h	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebCore/dom/BroadcastChannelRegistry.h	2022-04-22 23:02:57 UTC (rev 293261)
@@ -31,15 +31,15 @@
 
 namespace WebCore {
 
+struct PartitionedSecurityOrigin;
 class SerializedScriptValue;
-struct ClientOrigin;
 
 class BroadcastChannelRegistry : public RefCounted<BroadcastChannelRegistry> {
 public:
     virtual ~BroadcastChannelRegistry() { }
-    virtual void registerChannel(const ClientOrigin&, const String& name, BroadcastChannelIdentifier) = 0;
-    virtual void unregisterChannel(const ClientOrigin&, const String& name, BroadcastChannelIdentifier) = 0;
-    virtual void postMessage(const ClientOrigin&, const String& name, BroadcastChannelIdentifier source, Ref<SerializedScriptValue>&&, CompletionHandler<void()>&&) = 0;
+    virtual void registerChannel(const PartitionedSecurityOrigin&, const String& name, BroadcastChannelIdentifier) = 0;
+    virtual void unregisterChannel(const PartitionedSecurityOrigin&, const String& name, BroadcastChannelIdentifier) = 0;
+    virtual void postMessage(const PartitionedSecurityOrigin&, const String& name, BroadcastChannelIdentifier source, Ref<SerializedScriptValue>&&, CompletionHandler<void()>&&) = 0;
 };
 
 } // namespace WebCore

Modified: branches/safari-613.2.7.1-branch/Source/WebCore/loader/EmptyClients.cpp (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebCore/loader/EmptyClients.cpp	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebCore/loader/EmptyClients.cpp	2022-04-22 23:02:57 UTC (rev 293261)
@@ -1183,9 +1183,9 @@
 private:
     EmptyBroadcastChannelRegistry() = default;
 
-    void registerChannel(const ClientOrigin&, const String&, BroadcastChannelIdentifier) final { }
-    void unregisterChannel(const ClientOrigin&, const String&, BroadcastChannelIdentifier) final { }
-    void postMessage(const ClientOrigin&, const String&, BroadcastChannelIdentifier, Ref<SerializedScriptValue>&&, CompletionHandler<void()>&&) final { }
+    void registerChannel(const PartitionedSecurityOrigin&, const String&, BroadcastChannelIdentifier) final { }
+    void unregisterChannel(const PartitionedSecurityOrigin&, const String&, BroadcastChannelIdentifier) final { }
+    void postMessage(const PartitionedSecurityOrigin&, const String&, BroadcastChannelIdentifier, Ref<SerializedScriptValue>&&, CompletionHandler<void()>&&) final { }
 };
 
 class EmptyWebLockRegistry final : public WebLockRegistry {

Added: branches/safari-613.2.7.1-branch/Source/WebCore/page/PartitionedSecurityOrigin.h (0 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebCore/page/PartitionedSecurityOrigin.h	                        (rev 0)
+++ branches/safari-613.2.7.1-branch/Source/WebCore/page/PartitionedSecurityOrigin.h	2022-04-22 23:02:57 UTC (rev 293261)
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 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 "SecurityOrigin.h"
+#include <wtf/HashTraits.h>
+#include <wtf/Hasher.h>
+#include <wtf/Ref.h>
+
+namespace WebCore {
+
+struct PartitionedSecurityOrigin {
+    PartitionedSecurityOrigin(Ref<SecurityOrigin>&& topOrigin, Ref<SecurityOrigin>&& clientOrigin)
+        : topOrigin(WTFMove(topOrigin))
+        , clientOrigin(WTFMove(clientOrigin))
+    { }
+
+    PartitionedSecurityOrigin(WTF::HashTableDeletedValueType)
+        : topOrigin(WTF::HashTableDeletedValue)
+        , clientOrigin(WTF::HashTableDeletedValue)
+    { }
+
+    PartitionedSecurityOrigin(WTF::HashTableEmptyValueType)
+        : topOrigin(WTF::HashTableEmptyValue)
+        , clientOrigin(WTF::HashTableEmptyValue)
+    { }
+
+    bool isHashTableDeletedValue() const { return topOrigin.isHashTableDeletedValue(); }
+    bool isHashTableEmptyValue() const { return topOrigin.isHashTableEmptyValue(); }
+
+    Ref<SecurityOrigin> topOrigin;
+    Ref<SecurityOrigin> clientOrigin;
+};
+
+inline bool operator==(const PartitionedSecurityOrigin& a, const PartitionedSecurityOrigin& b)
+{
+    return a.topOrigin->isSameOriginAs(b.topOrigin) && a.clientOrigin->isSameOriginAs(b.clientOrigin);
+}
+
+} // namespace WebCore
+
+namespace WTF {
+
+inline void add(Hasher& hasher, const WebCore::PartitionedSecurityOrigin& origin)
+{
+    add(hasher, origin.topOrigin.get(), origin.clientOrigin.get());
+}
+
+struct PartitionedSecurityOriginHash {
+    static unsigned hash(const WebCore::PartitionedSecurityOrigin& origin) { return computeHash(origin); }
+    static bool equal(const WebCore::PartitionedSecurityOrigin& a, const WebCore::PartitionedSecurityOrigin& b) { return a == b; }
+    static constexpr bool safeToCompareToEmptyOrDeleted = false;
+};
+
+template<> struct DefaultHash<WebCore::PartitionedSecurityOrigin> : PartitionedSecurityOriginHash { };
+
+template<> struct HashTraits<WebCore::PartitionedSecurityOrigin> : SimpleClassHashTraits<WebCore::PartitionedSecurityOrigin> {
+    static constexpr bool emptyValueIsZero = true;
+    static WebCore::PartitionedSecurityOrigin emptyValue() { return HashTableEmptyValue; }
+
+    template <typename>
+    static void constructEmptyValue(WebCore::PartitionedSecurityOrigin& slot)
+    {
+        new (NotNull, std::addressof(slot)) WebCore::PartitionedSecurityOrigin(HashTableEmptyValue);
+    }
+
+    static constexpr bool hasIsEmptyValueFunction = true;
+    static bool isEmptyValue(const WebCore::PartitionedSecurityOrigin& value) { return value.isHashTableEmptyValue(); }
+
+    using PeekType = std::optional<WebCore::PartitionedSecurityOrigin>;
+    static PeekType peek(const WebCore::PartitionedSecurityOrigin& value) { return isEmptyValue(value) ? std::nullopt : std::optional { value }; }
+
+    using TakeType = std::optional<WebCore::PartitionedSecurityOrigin>;
+    static TakeType take(WebCore::PartitionedSecurityOrigin&& value) { return isEmptyValue(value) ? std::nullopt : std::optional { WTFMove(value) }; }
+};
+
+} // namespace WTF

Modified: branches/safari-613.2.7.1-branch/Source/WebCore/page/SecurityOrigin.h (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebCore/page/SecurityOrigin.h	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebCore/page/SecurityOrigin.h	2022-04-22 23:02:57 UTC (rev 293261)
@@ -306,4 +306,9 @@
     return origin;
 }
 
+inline void add(Hasher& hasher, const SecurityOrigin& origin)
+{
+    add(hasher, origin.protocol(), origin.host(), origin.port());
+}
+
 } // namespace WebCore

Modified: branches/safari-613.2.7.1-branch/Source/WebKit/ChangeLog (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKit/ChangeLog	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKit/ChangeLog	2022-04-22 23:02:57 UTC (rev 293261)
@@ -1,5 +1,147 @@
 2022-04-22  Russell Epstein  <repst...@apple.com>
 
+        Cherry-pick r291589. rdar://problem/90511155
+
+    LayoutTests/imported/w3c:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
+    
+    Reviewed by Alex Christensen.
+    
+    Import web-platform-tests test coverage.
+    
+    * web-platform-tests/webmessaging/broadcastchannel/opaque-origin-expected.txt: Added.
+    * web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html: Added.
+    * web-platform-tests/webmessaging/broadcastchannel/w3c-import.log:
+    
+    Source/WebCore:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
+    
+    Reviewed by Alex Christensen.
+    
+    The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
+    which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
+    SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
+    unique SecurityOrigins, they would compare as equal.
+    
+    To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
+    to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
+    objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
+    would not be equal but the same unique SecurityOrigin would be. I then used this new
+    PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
+    ClientOrigin. This allows communication between several BroadcastChannels from the same
+    unique origin, while preventing communication between distinct opaque origins.
+    
+    When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
+    the Network Process at all since the destination can only be in the same WebProcess.
+    
+    Test: imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html
+    
+    * Headers.cmake:
+    * WebCore.xcodeproj/project.pbxproj:
+    * dom/BroadcastChannel.cpp:
+    (WebCore::shouldPartitionOrigin):
+    (WebCore::BroadcastChannel::MainThreadBridge::registerChannel):
+    (WebCore::BroadcastChannel::MainThreadBridge::unregisterChannel):
+    (WebCore::BroadcastChannel::MainThreadBridge::postMessage):
+    * dom/BroadcastChannelRegistry.h:
+    * loader/EmptyClients.cpp:
+    * page/PartitionedSecurityOrigin.h: Added.
+    (WebCore::PartitionedSecurityOrigin::PartitionedSecurityOrigin):
+    (WebCore::PartitionedSecurityOrigin::isHashTableDeletedValue const):
+    (WebCore::PartitionedSecurityOrigin::isHashTableEmptyValue const):
+    (WebCore::operator==):
+    (WTF::add):
+    (WTF::PartitionedSecurityOriginHash::hash):
+    (WTF::PartitionedSecurityOriginHash::equal):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::emptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::constructEmptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::isEmptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::peek):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::take):
+    
+    Source/WebKit:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
+    
+    Reviewed by Alex Christensen.
+    
+    The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
+    which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
+    SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
+    unique SecurityOrigins, they would compare as equal.
+    
+    To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
+    to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
+    objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
+    would not be equal but the same unique SecurityOrigin would be. I then used this new
+    PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
+    ClientOrigin. This allows communication between several BroadcastChannels from the same
+    unique origin, while preventing communication between distinct opaque origins.
+    
+    When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
+    the Network Process at all since the destination can only be in the same WebProcess.
+    
+    * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp:
+    (WebKit::toClientOrigin):
+    (WebKit::WebBroadcastChannelRegistry::registerChannel):
+    (WebKit::WebBroadcastChannelRegistry::unregisterChannel):
+    (WebKit::WebBroadcastChannelRegistry::postMessage):
+    (WebKit::WebBroadcastChannelRegistry::postMessageLocally):
+    (WebKit::WebBroadcastChannelRegistry::postMessageToRemote):
+    (WebKit::WebBroadcastChannelRegistry::networkProcessCrashed):
+    * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h:
+    
+    Source/WebKitLegacy:
+    Dust off Mac CMake build
+    https://bugs.webkit.org/show_bug.cgi?id=238121
+    
+    Reviewed by Yusuke Suzuki.
+    
+    * PlatformMac.cmake:
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@291589 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2022-03-21  Chris Dumez  <cdu...@apple.com>
+
+            BroadcastChannel instances in distinct opaque origins can communicate
+            https://bugs.webkit.org/show_bug.cgi?id=238090
+            <rdar://problem/90511155>
+
+            Reviewed by Alex Christensen.
+
+            The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
+            which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
+            SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
+            unique SecurityOrigins, they would compare as equal.
+
+            To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
+            to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
+            objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
+            would not be equal but the same unique SecurityOrigin would be. I then used this new
+            PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
+            ClientOrigin. This allows communication between several BroadcastChannels from the same
+            unique origin, while preventing communication between distinct opaque origins.
+
+            When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
+            the Network Process at all since the destination can only be in the same WebProcess.
+
+            * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp:
+            (WebKit::toClientOrigin):
+            (WebKit::WebBroadcastChannelRegistry::registerChannel):
+            (WebKit::WebBroadcastChannelRegistry::unregisterChannel):
+            (WebKit::WebBroadcastChannelRegistry::postMessage):
+            (WebKit::WebBroadcastChannelRegistry::postMessageLocally):
+            (WebKit::WebBroadcastChannelRegistry::postMessageToRemote):
+            (WebKit::WebBroadcastChannelRegistry::networkProcessCrashed):
+            * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h:
+
+2022-04-22  Russell Epstein  <repst...@apple.com>
+
         Apply patch. rdar://problem/91446317
 
     2022-04-21  Youenn Fablet  <you...@apple.com>

Modified: branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkBroadcastChannelRegistry.cpp (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkBroadcastChannelRegistry.cpp	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkBroadcastChannelRegistry.cpp	2022-04-22 23:02:57 UTC (rev 293261)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "NetworkBroadcastChannelRegistry.h"
 
+#include "NetworkProcessProxyMessages.h"
 #include "WebBroadcastChannelRegistryMessages.h"
 #include <WebCore/MessageWithMessagePorts.h>
 #include <wtf/CallbackAggregator.h>
@@ -32,10 +33,31 @@
 
 namespace WebKit {
 
-NetworkBroadcastChannelRegistry::NetworkBroadcastChannelRegistry() = default;
+#define REGISTRY_MESSAGE_CHECK(assertion) REGISTRY_MESSAGE_CHECK_COMPLETION(assertion, (void)0)
+#define REGISTRY_MESSAGE_CHECK_COMPLETION(assertion, completion) do { \
+    ASSERT(assertion); \
+    if (UNLIKELY(!(assertion))) { \
+        if (auto webProcessIdentifier = m_networkProcess->webProcessIdentifierForConnection(connection)) \
+            m_networkProcess->parentProcessConnection()->send(Messages::NetworkProcessProxy::TerminateWebProcess(webProcessIdentifier), 0); \
+        { completion; } \
+        return; \
+    } \
+} while (0)
 
+static bool isValidClientOrigin(const WebCore::ClientOrigin& clientOrigin)
+{
+    return !clientOrigin.topOrigin.isEmpty() && !clientOrigin.clientOrigin.isEmpty();
+}
+
+NetworkBroadcastChannelRegistry::NetworkBroadcastChannelRegistry(NetworkProcess& networkProcess)
+    : m_networkProcess(networkProcess)
+{
+}
+
 void NetworkBroadcastChannelRegistry::registerChannel(IPC::Connection& connection, const WebCore::ClientOrigin& origin, const String& name)
 {
+    REGISTRY_MESSAGE_CHECK(isValidClientOrigin(origin));
+
     auto& channelsForOrigin = m_broadcastChannels.ensure(origin, [] { return NameToConnectionIdentifiersMap { }; }).iterator->value;
     auto& connectionIdentifiersForName = channelsForOrigin.ensure(name, [] { return Vector<IPC::Connection::UniqueID> { }; }).iterator->value;
     ASSERT(!connectionIdentifiersForName.contains(connection.uniqueID()));
@@ -44,6 +66,8 @@
 
 void NetworkBroadcastChannelRegistry::unregisterChannel(IPC::Connection& connection, const WebCore::ClientOrigin& origin, const String& name)
 {
+    REGISTRY_MESSAGE_CHECK(isValidClientOrigin(origin));
+
     auto channelsForOriginIterator = m_broadcastChannels.find(origin);
     ASSERT(channelsForOriginIterator != m_broadcastChannels.end());
     if (channelsForOriginIterator == m_broadcastChannels.end())
@@ -59,6 +83,8 @@
 
 void NetworkBroadcastChannelRegistry::postMessage(IPC::Connection& connection, const WebCore::ClientOrigin& origin, const String& name, WebCore::MessageWithMessagePorts&& message, CompletionHandler<void()>&& completionHandler)
 {
+    REGISTRY_MESSAGE_CHECK_COMPLETION(isValidClientOrigin(origin), completionHandler());
+
     auto channelsForOriginIterator = m_broadcastChannels.find(origin);
     ASSERT(channelsForOriginIterator != m_broadcastChannels.end());
     if (channelsForOriginIterator == m_broadcastChannels.end())
@@ -101,4 +127,7 @@
         m_broadcastChannels.remove(originToRemove);
 }
 
+#undef REGISTRY_MESSAGE_CHECK
+#undef REGISTRY_MESSAGE_CHECK_COMPLETION
+
 } // namespace WebKit

Modified: branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkBroadcastChannelRegistry.h (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkBroadcastChannelRegistry.h	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkBroadcastChannelRegistry.h	2022-04-22 23:02:57 UTC (rev 293261)
@@ -36,10 +36,12 @@
 
 namespace WebKit {
 
+class NetworkProcess;
+
 class NetworkBroadcastChannelRegistry {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    NetworkBroadcastChannelRegistry();
+    explicit NetworkBroadcastChannelRegistry(NetworkProcess&);
 
     void removeConnection(IPC::Connection&);
 
@@ -50,6 +52,7 @@
     void postMessage(IPC::Connection&, const WebCore::ClientOrigin&, const String& name, WebCore::MessageWithMessagePorts&&, CompletionHandler<void()>&&);
 
 private:
+    Ref<NetworkProcess> m_networkProcess;
     using NameToConnectionIdentifiersMap = HashMap<String, Vector<IPC::Connection::UniqueID>>;
     HashMap<WebCore::ClientOrigin, NameToConnectionIdentifiersMap> m_broadcastChannels;
 };

Modified: branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkProcess.cpp (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2022-04-22 23:02:57 UTC (rev 293261)
@@ -2605,6 +2605,15 @@
     }
 }
 
+WebCore::ProcessIdentifier NetworkProcess::webProcessIdentifierForConnection(IPC::Connection& connection) const
+{
+    for (auto& [processIdentifier, webConnection] : m_webProcessConnections) {
+        if (&webConnection->connection() == &connection)
+            return processIdentifier;
+    }
+    return { };
+}
+
 NetworkConnectionToWebProcess* NetworkProcess::webProcessConnection(ProcessIdentifier identifier) const
 {
     return m_webProcessConnections.get(identifier);

Modified: branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkProcess.h (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkProcess.h	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkProcess.h	2022-04-22 23:02:57 UTC (rev 293261)
@@ -335,6 +335,7 @@
     const OptionSet<NetworkCache::CacheOption>& cacheOptions() const { return m_cacheOptions; }
 
     NetworkConnectionToWebProcess* webProcessConnection(WebCore::ProcessIdentifier) const;
+    WebCore::ProcessIdentifier webProcessIdentifierForConnection(IPC::Connection&) const;
     WebCore::MessagePortChannelRegistry& messagePortChannelRegistry() { return m_messagePortChannelRegistry; }
 
     void setServiceWorkerFetchTimeoutForTesting(Seconds, CompletionHandler<void()>&&);

Modified: branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkSession.cpp (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkSession.cpp	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKit/NetworkProcess/NetworkSession.cpp	2022-04-22 23:02:57 UTC (rev 293261)
@@ -125,7 +125,7 @@
 #endif
     , m_privateClickMeasurement(managerOrProxy(*this, networkProcess, parameters))
     , m_privateClickMeasurementDebugModeEnabled(parameters.enablePrivateClickMeasurementDebugMode)
-    , m_broadcastChannelRegistry(makeUniqueRef<NetworkBroadcastChannelRegistry>())
+    , m_broadcastChannelRegistry(makeUniqueRef<NetworkBroadcastChannelRegistry>(networkProcess))
     , m_testSpeedMultiplier(parameters.testSpeedMultiplier)
     , m_allowsServerPreconnect(parameters.allowsServerPreconnect)
     , m_shouldRunServiceWorkersOnMainThreadForTesting(parameters.shouldRunServiceWorkersOnMainThreadForTesting)

Modified: branches/safari-613.2.7.1-branch/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp	2022-04-22 23:02:57 UTC (rev 293261)
@@ -40,17 +40,30 @@
     return WebProcess::singleton().ensureNetworkProcessConnection().connection();
 }
 
-void WebBroadcastChannelRegistry::registerChannel(const WebCore::ClientOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier identifier)
+// Unique origins are only stored in process in m_channelsPerOrigin and never sent to the NetworkProcess as a ClientOrigin.
+// The identity of unique origins wouldn't be preserved when serializing them as a SecurityOriginData (via ClientOrigin).
+// Since BroadcastChannels from a unique origin can only communicate with other BroadcastChannels from the same unique origin,
+// the destination channels have to be within the same WebProcess anyway.
+static std::optional<WebCore::ClientOrigin> toClientOrigin(const WebCore::PartitionedSecurityOrigin& origin)
 {
+    if (origin.topOrigin->isUnique() || origin.clientOrigin->isUnique())
+        return std::nullopt;
+    return WebCore::ClientOrigin { origin.topOrigin->data(), origin.clientOrigin->data() };
+}
+
+void WebBroadcastChannelRegistry::registerChannel(const WebCore::PartitionedSecurityOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier identifier)
+{
     auto& channelsForOrigin = m_channelsPerOrigin.ensure(origin, [] { return HashMap<String, Vector<WebCore::BroadcastChannelIdentifier>> { }; }).iterator->value;
     auto& channelsForName = channelsForOrigin.ensure(name, [] { return Vector<WebCore::BroadcastChannelIdentifier> { }; }).iterator->value;
     channelsForName.append(identifier);
 
-    if (channelsForName.size() == 1)
-        networkProcessConnection().send(Messages::NetworkBroadcastChannelRegistry::RegisterChannel { origin, name }, 0);
+    if (channelsForName.size() == 1) {
+        if (auto clientOrigin = toClientOrigin(origin))
+            networkProcessConnection().send(Messages::NetworkBroadcastChannelRegistry::RegisterChannel { *clientOrigin, name }, 0);
+    }
 }
 
-void WebBroadcastChannelRegistry::unregisterChannel(const WebCore::ClientOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier identifier)
+void WebBroadcastChannelRegistry::unregisterChannel(const WebCore::PartitionedSecurityOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier identifier)
 {
     auto channelsPerOriginIterator = m_channelsPerOrigin.find(origin);
     if (channelsPerOriginIterator == m_channelsPerOrigin.end())
@@ -68,20 +81,22 @@
         return;
 
     channelsForOrigin.remove(channelsForOriginIterator);
-    networkProcessConnection().send(Messages::NetworkBroadcastChannelRegistry::UnregisterChannel { origin, name }, 0);
+    if (auto clientOrigin = toClientOrigin(origin))
+        networkProcessConnection().send(Messages::NetworkBroadcastChannelRegistry::UnregisterChannel { *clientOrigin, name }, 0);
 
     if (channelsForOrigin.isEmpty())
         m_channelsPerOrigin.remove(channelsPerOriginIterator);
 }
 
-void WebBroadcastChannelRegistry::postMessage(const WebCore::ClientOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&& message, CompletionHandler<void()>&& completionHandler)
+void WebBroadcastChannelRegistry::postMessage(const WebCore::PartitionedSecurityOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&& message, CompletionHandler<void()>&& completionHandler)
 {
     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
     postMessageLocally(origin, name, source, message.copyRef(), callbackAggregator.copyRef());
-    networkProcessConnection().sendWithAsyncReply(Messages::NetworkBroadcastChannelRegistry::PostMessage { origin, name, WebCore::MessageWithMessagePorts { WTFMove(message), { } } }, [callbackAggregator] { }, 0);
+    if (auto clientOrigin = toClientOrigin(origin))
+        networkProcessConnection().sendWithAsyncReply(Messages::NetworkBroadcastChannelRegistry::PostMessage { *clientOrigin, name, WebCore::MessageWithMessagePorts { WTFMove(message), { } } }, [callbackAggregator] { }, 0);
 }
 
-void WebBroadcastChannelRegistry::postMessageLocally(const WebCore::ClientOrigin& origin, const String& name, std::optional<WebCore::BroadcastChannelIdentifier> sourceInProcess, Ref<WebCore::SerializedScriptValue>&& message, Ref<WTF::CallbackAggregator>&& callbackAggregator)
+void WebBroadcastChannelRegistry::postMessageLocally(const WebCore::PartitionedSecurityOrigin& origin, const String& name, std::optional<WebCore::BroadcastChannelIdentifier> sourceInProcess, Ref<WebCore::SerializedScriptValue>&& message, Ref<WTF::CallbackAggregator>&& callbackAggregator)
 {
     auto channelsPerOriginIterator = m_channelsPerOrigin.find(origin);
     if (channelsPerOriginIterator == m_channelsPerOrigin.end())
@@ -100,9 +115,10 @@
     }
 }
 
-void WebBroadcastChannelRegistry::postMessageToRemote(const WebCore::ClientOrigin& origin, const String& name, WebCore::MessageWithMessagePorts&& message, CompletionHandler<void()>&& completionHandler)
+void WebBroadcastChannelRegistry::postMessageToRemote(const WebCore::ClientOrigin& clientOrigin, const String& name, WebCore::MessageWithMessagePorts&& message, CompletionHandler<void()>&& completionHandler)
 {
     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
+    WebCore::PartitionedSecurityOrigin origin { clientOrigin.topOrigin.securityOrigin(), clientOrigin.clientOrigin.securityOrigin() };
     postMessageLocally(origin, name, std::nullopt, *message.message, callbackAggregator.copyRef());
 }
 
@@ -109,8 +125,11 @@
 void WebBroadcastChannelRegistry::networkProcessCrashed()
 {
     for (auto& [origin, channelsForOrigin] : m_channelsPerOrigin) {
+        auto clientOrigin = toClientOrigin(origin);
+        if (!clientOrigin)
+            continue;
         for (auto& name : channelsForOrigin.keys())
-            networkProcessConnection().send(Messages::NetworkBroadcastChannelRegistry::RegisterChannel { origin, name }, 0);
+            networkProcessConnection().send(Messages::NetworkBroadcastChannelRegistry::RegisterChannel { *clientOrigin, name }, 0);
     }
 }
 

Modified: branches/safari-613.2.7.1-branch/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h	2022-04-22 23:02:57 UTC (rev 293261)
@@ -28,6 +28,8 @@
 #include "Connection.h"
 #include <WebCore/BroadcastChannelRegistry.h>
 #include <WebCore/ClientOrigin.h>
+#include <WebCore/PartitionedSecurityOrigin.h>
+#include <WebCore/SecurityOrigin.h>
 #include <wtf/HashMap.h>
 #include <wtf/Vector.h>
 
@@ -48,9 +50,9 @@
         return adoptRef(*new WebBroadcastChannelRegistry);
     }
 
-    void registerChannel(const WebCore::ClientOrigin&, const String& name, WebCore::BroadcastChannelIdentifier) final;
-    void unregisterChannel(const WebCore::ClientOrigin&, const String& name, WebCore::BroadcastChannelIdentifier) final;
-    void postMessage(const WebCore::ClientOrigin&, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&&, CompletionHandler<void()>&&) final;
+    void registerChannel(const WebCore::PartitionedSecurityOrigin&, const String& name, WebCore::BroadcastChannelIdentifier) final;
+    void unregisterChannel(const WebCore::PartitionedSecurityOrigin&, const String& name, WebCore::BroadcastChannelIdentifier) final;
+    void postMessage(const WebCore::PartitionedSecurityOrigin&, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&&, CompletionHandler<void()>&&) final;
 
     void networkProcessCrashed();
 
@@ -60,9 +62,9 @@
     WebBroadcastChannelRegistry() = default;
 
     void postMessageToRemote(const WebCore::ClientOrigin&, const String& name, WebCore::MessageWithMessagePorts&&, CompletionHandler<void()>&&);
-    void postMessageLocally(const WebCore::ClientOrigin&, const String& name, std::optional<WebCore::BroadcastChannelIdentifier> sourceInProcess, Ref<WebCore::SerializedScriptValue>&&, Ref<WTF::CallbackAggregator>&&);
+    void postMessageLocally(const WebCore::PartitionedSecurityOrigin&, const String& name, std::optional<WebCore::BroadcastChannelIdentifier> sourceInProcess, Ref<WebCore::SerializedScriptValue>&&, Ref<WTF::CallbackAggregator>&&);
 
-    HashMap<WebCore::ClientOrigin, HashMap<String, Vector<WebCore::BroadcastChannelIdentifier>>> m_channelsPerOrigin;
+    HashMap<WebCore::PartitionedSecurityOrigin, HashMap<String, Vector<WebCore::BroadcastChannelIdentifier>>> m_channelsPerOrigin;
 };
 
 } // namespace WebKit

Modified: branches/safari-613.2.7.1-branch/Source/WebKitLegacy/ChangeLog (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKitLegacy/ChangeLog	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKitLegacy/ChangeLog	2022-04-22 23:02:57 UTC (rev 293261)
@@ -1,15 +1,137 @@
-2022-01-24  Alan Coon  <alanc...@apple.com>
+2022-04-22  Russell Epstein  <repst...@apple.com>
 
-        Cherry-pick r288389. rdar://problem/85405320
+        Cherry-pick r291589. rdar://problem/90511155
 
-    Disable CFURLCache in WebKit2
-    https://bugs.webkit.org/show_bug.cgi?id=234988
-    <rdar://problem/87619196>
+    LayoutTests/imported/w3c:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
     
-    Reviewed by Geoffrey Garen.
+    Reviewed by Alex Christensen.
     
+    Import web-platform-tests test coverage.
+    
+    * web-platform-tests/webmessaging/broadcastchannel/opaque-origin-expected.txt: Added.
+    * web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html: Added.
+    * web-platform-tests/webmessaging/broadcastchannel/w3c-import.log:
+    
     Source/WebCore:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
     
+    Reviewed by Alex Christensen.
+    
+    The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
+    which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
+    SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
+    unique SecurityOrigins, they would compare as equal.
+    
+    To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
+    to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
+    objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
+    would not be equal but the same unique SecurityOrigin would be. I then used this new
+    PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
+    ClientOrigin. This allows communication between several BroadcastChannels from the same
+    unique origin, while preventing communication between distinct opaque origins.
+    
+    When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
+    the Network Process at all since the destination can only be in the same WebProcess.
+    
+    Test: imported/w3c/web-platform-tests/webmessaging/broadcastchannel/opaque-origin.html
+    
+    * Headers.cmake:
+    * WebCore.xcodeproj/project.pbxproj:
+    * dom/BroadcastChannel.cpp:
+    (WebCore::shouldPartitionOrigin):
+    (WebCore::BroadcastChannel::MainThreadBridge::registerChannel):
+    (WebCore::BroadcastChannel::MainThreadBridge::unregisterChannel):
+    (WebCore::BroadcastChannel::MainThreadBridge::postMessage):
+    * dom/BroadcastChannelRegistry.h:
+    * loader/EmptyClients.cpp:
+    * page/PartitionedSecurityOrigin.h: Added.
+    (WebCore::PartitionedSecurityOrigin::PartitionedSecurityOrigin):
+    (WebCore::PartitionedSecurityOrigin::isHashTableDeletedValue const):
+    (WebCore::PartitionedSecurityOrigin::isHashTableEmptyValue const):
+    (WebCore::operator==):
+    (WTF::add):
+    (WTF::PartitionedSecurityOriginHash::hash):
+    (WTF::PartitionedSecurityOriginHash::equal):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::emptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::constructEmptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::isEmptyValue):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::peek):
+    (WTF::HashTraits<WebCore::PartitionedSecurityOrigin>::take):
+    
+    Source/WebKit:
+    BroadcastChannel instances in distinct opaque origins can communicate
+    https://bugs.webkit.org/show_bug.cgi?id=238090
+    <rdar://problem/90511155>
+    
+    Reviewed by Alex Christensen.
+    
+    The issue is that we would use a ClientOrigin to distinguish origins for BroadcastChannel,
+    which relies on SecurityOriginData internally. A unique/opaque SecurityOrigin becomes an empty
+    SecurityOriginData upon conversion. As a result, when comparing ClientOrigin objects from
+    unique SecurityOrigins, they would compare as equal.
+    
+    To address the issue, I introduced a new PartitionedSecurityOrigin type which is similar
+    to ClientOrigin but stores SecurityOrigin objects internally, instead of SecurityOriginData
+    objects. PartitionedSecurityOrigin's operator==() is such that different SecurityOrigins
+    would not be equal but the same unique SecurityOrigin would be. I then used this new
+    PartitionedSecurityOrigin type as key in our HashMap on the WebProcess side instead of
+    ClientOrigin. This allows communication between several BroadcastChannels from the same
+    unique origin, while preventing communication between distinct opaque origins.
+    
+    When the PartitionedSecurityOrigin contains an opaque security origin, we don't involve
+    the Network Process at all since the destination can only be in the same WebProcess.
+    
+    * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp:
+    (WebKit::toClientOrigin):
+    (WebKit::WebBroadcastChannelRegistry::registerChannel):
+    (WebKit::WebBroadcastChannelRegistry::unregisterChannel):
+    (WebKit::WebBroadcastChannelRegistry::postMessage):
+    (WebKit::WebBroadcastChannelRegistry::postMessageLocally):
+    (WebKit::WebBroadcastChannelRegistry::postMessageToRemote):
+    (WebKit::WebBroadcastChannelRegistry::networkProcessCrashed):
+    * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h:
+    
+    Source/WebKitLegacy:
+    Dust off Mac CMake build
+    https://bugs.webkit.org/show_bug.cgi?id=238121
+    
+    Reviewed by Yusuke Suzuki.
+    
+    * PlatformMac.cmake:
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@291589 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2022-01-24  Alan Coon  <alanc...@apple.com>
+
+            Cherry-pick r288389. rdar://problem/85405320
+
+        Disable CFURLCache in WebKit2
+        https://bugs.webkit.org/show_bug.cgi?id=234988
+        <rdar://problem/87619196>
+
+        Reviewed by Geoffrey Garen.
+2022-03-21  Chris Dumez  <cdu...@apple.com>
+
+        BroadcastChannel instances in distinct opaque origins can communicate
+        https://bugs.webkit.org/show_bug.cgi?id=238090
+        <rdar://problem/90511155>
+
+        Reviewed by Alex Christensen.
+
+        * WebCoreSupport/WebBroadcastChannelRegistry.cpp:
+        (WebBroadcastChannelRegistry::registerChannel):
+        (WebBroadcastChannelRegistry::unregisterChannel):
+        (WebBroadcastChannelRegistry::postMessage):
+        * WebCoreSupport/WebBroadcastChannelRegistry.h:
+
+    
+    Source/WebCore:
+    
     _CFURLStorageSessionCopyCache can be slow (see rdar://85418732) and UI process may kill network process for
     being unresponsive. Since WebKit does not use CFURLCache, we should disable it to avoid the hang.
     

Modified: branches/safari-613.2.7.1-branch/Source/WebKitLegacy/WebCoreSupport/WebBroadcastChannelRegistry.cpp (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKitLegacy/WebCoreSupport/WebBroadcastChannelRegistry.cpp	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKitLegacy/WebCoreSupport/WebBroadcastChannelRegistry.cpp	2022-04-22 23:02:57 UTC (rev 293261)
@@ -44,7 +44,7 @@
     return registry;
 }
 
-void WebBroadcastChannelRegistry::registerChannel(const WebCore::ClientOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier identifier)
+void WebBroadcastChannelRegistry::registerChannel(const WebCore::PartitionedSecurityOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier identifier)
 {
     ASSERT(isMainThread());
     auto& channelsForOrigin = m_channels.ensure(origin, [] { return NameToChannelIdentifiersMap { }; }).iterator->value;
@@ -53,7 +53,7 @@
     channelsForName.append(identifier);
 }
 
-void WebBroadcastChannelRegistry::unregisterChannel(const WebCore::ClientOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier identifier)
+void WebBroadcastChannelRegistry::unregisterChannel(const WebCore::PartitionedSecurityOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier identifier)
 {
     ASSERT(isMainThread());
     auto channelsForOriginIterator = m_channels.find(origin);
@@ -66,7 +66,7 @@
     channelsForNameIterator->value.removeFirst(identifier);
 }
 
-void WebBroadcastChannelRegistry::postMessage(const WebCore::ClientOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&& message, CompletionHandler<void()>&& completionHandler)
+void WebBroadcastChannelRegistry::postMessage(const WebCore::PartitionedSecurityOrigin& origin, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&& message, CompletionHandler<void()>&& completionHandler)
 {
     ASSERT(isMainThread());
     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));

Modified: branches/safari-613.2.7.1-branch/Source/WebKitLegacy/WebCoreSupport/WebBroadcastChannelRegistry.h (293260 => 293261)


--- branches/safari-613.2.7.1-branch/Source/WebKitLegacy/WebCoreSupport/WebBroadcastChannelRegistry.h	2022-04-22 22:52:23 UTC (rev 293260)
+++ branches/safari-613.2.7.1-branch/Source/WebKitLegacy/WebCoreSupport/WebBroadcastChannelRegistry.h	2022-04-22 23:02:57 UTC (rev 293261)
@@ -24,7 +24,7 @@
  */
 
 #include <WebCore/BroadcastChannelRegistry.h>
-#include <WebCore/ClientOrigin.h>
+#include <WebCore/PartitionedSecurityOrigin.h>
 #include <wtf/Forward.h>
 #include <wtf/WeakPtr.h>
 
@@ -34,13 +34,13 @@
 public:
     static Ref<WebBroadcastChannelRegistry> getOrCreate(bool privateSession);
 
-    void registerChannel(const WebCore::ClientOrigin&, const String& name, WebCore::BroadcastChannelIdentifier) final;
-    void unregisterChannel(const WebCore::ClientOrigin&, const String& name, WebCore::BroadcastChannelIdentifier) final;
-    void postMessage(const WebCore::ClientOrigin&, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&&, CompletionHandler<void()>&&) final;
+    void registerChannel(const WebCore::PartitionedSecurityOrigin&, const String& name, WebCore::BroadcastChannelIdentifier) final;
+    void unregisterChannel(const WebCore::PartitionedSecurityOrigin&, const String& name, WebCore::BroadcastChannelIdentifier) final;
+    void postMessage(const WebCore::PartitionedSecurityOrigin&, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&&, CompletionHandler<void()>&&) final;
 
 private:
     WebBroadcastChannelRegistry() = default;
 
     using NameToChannelIdentifiersMap = HashMap<String, Vector<WebCore::BroadcastChannelIdentifier>>;
-    HashMap<WebCore::ClientOrigin, NameToChannelIdentifiersMap> m_channels;
+    HashMap<WebCore::PartitionedSecurityOrigin, NameToChannelIdentifiersMap> m_channels;
 };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to