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;
};