Changeset 282366 in webkit
- Timestamp:
- Sep 13, 2021 3:18:26 PM (10 months ago)
- Location:
- trunk
- Files:
-
- 4 added
- 10 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/http/tests/messaging/broadcastchannel-partitioning-with-storage-access-expected.txt (added)
-
LayoutTests/http/tests/messaging/broadcastchannel-partitioning-with-storage-access.html (added)
-
LayoutTests/http/tests/messaging/resources/broadcastchannel-partitioning-with-storage-access-iframe.html (added)
-
LayoutTests/http/tests/messaging/resources/broadcastchannel-partitioning-with-storage-access-popup.html (added)
-
LayoutTests/platform/mac-wk1/TestExpectations (modified) (1 diff)
-
LayoutTests/platform/win/TestExpectations (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/dom/BroadcastChannel.cpp (modified) (6 diffs)
-
Source/WebCore/dom/BroadcastChannel.h (modified) (2 diffs)
-
Source/WebCore/page/ChromeClient.h (modified) (1 diff)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp (modified) (1 diff)
-
Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r282363 r282366 1 2021-09-13 Chris Dumez <cdumez@apple.com> 2 3 Relax BroadcastChannel origin partitioning if iframe has storage access 4 https://bugs.webkit.org/show_bug.cgi?id=230164 5 6 Reviewed by Alex Christensen. 7 8 Add layout test coverage. 9 10 * http/tests/messaging/broadcastchannel-partitioning-with-storage-access-expected.txt: Added. 11 * http/tests/messaging/broadcastchannel-partitioning-with-storage-access.html: Added. 12 * http/tests/messaging/resources/broadcastchannel-partitioning-with-storage-access-iframe.html: Added. 13 * http/tests/messaging/resources/broadcastchannel-partitioning-with-storage-access-popup.html: Added. 14 1 15 2021-09-13 Arcady Goldmints-Orlov <agoldmints@igalia.com> 2 16 -
trunk/LayoutTests/platform/mac-wk1/TestExpectations
r282358 r282366 79 79 editing/async-clipboard/clipboard-read-text-same-origin.html [ Skip ] 80 80 editing/async-clipboard/sanitize-when-reading-markup.html [ Skip ] 81 82 # No requestStorageAccess() support for WK1. 83 http/tests/messaging/broadcastchannel-partitioning-with-storage-access.html [ Skip ] 81 84 82 85 imported/w3c/web-platform-tests/websockets/Close-1000-reason.any.html [ Pass Failure ] -
trunk/LayoutTests/platform/win/TestExpectations
r282357 r282366 4637 4637 fast/html/broadcast-channel-between-different-sessions.html [ Skip ] 4638 4638 http/tests/messaging/broadcastchannel-partitioning.html [ Skip ] 4639 http/tests/messaging/broadcastchannel-partitioning-with-storage-access.html [ Skip ] 4639 4640 4640 4641 # This test is skipped because the necessary feature flag functionality specific to the Windows WebKit legacy port is -
trunk/Source/WebCore/ChangeLog
r282362 r282366 1 2021-09-13 Chris Dumez <cdumez@apple.com> 2 3 Relax BroadcastChannel origin partitioning if iframe has storage access 4 https://bugs.webkit.org/show_bug.cgi?id=230164 5 6 Reviewed by Alex Christensen. 7 8 In r282105, we started partitioning origins for BroadcastChannel using topOrigin/frameOrigin. 9 This prevents a topFrame of origin A to message a subframe of origin A if that subframe if under 10 another domain B. However, the `document.requestStorageAccess()` API exists to relax storage 11 partitioning and Gecko relies on this to relax BroadcastChannel origin partitioning as well. 12 This patch aligns WebKit's behavior with Gecko. 13 14 Test: http/tests/messaging/broadcastchannel-partitioning-with-storage-access.html 15 16 * dom/BroadcastChannel.cpp: 17 (WebCore::shouldPartitionOrigin): 18 (WebCore::BroadcastChannel::MainThreadBridge::create): 19 (WebCore::BroadcastChannel::MainThreadBridge::name const): 20 (WebCore::BroadcastChannel::MainThreadBridge::identifier const): 21 (WebCore::BroadcastChannel::MainThreadBridge::MainThreadBridge): 22 (WebCore::BroadcastChannel::MainThreadBridge::ensureOnMainThread): 23 (WebCore::BroadcastChannel::MainThreadBridge::registerChannel): 24 (WebCore::BroadcastChannel::MainThreadBridge::unregisterChannel): 25 (WebCore::BroadcastChannel::MainThreadBridge::postMessage): 26 (WebCore::BroadcastChannel::BroadcastChannel): 27 (WebCore::BroadcastChannel::~BroadcastChannel): 28 (WebCore::BroadcastChannel::identifier const): 29 (WebCore::BroadcastChannel::name const): 30 (WebCore::BroadcastChannel::postMessage): 31 (WebCore::BroadcastChannel::close): 32 (WebCore::BroadcastChannel::dispatchMessage): 33 * dom/BroadcastChannel.h: 34 * page/ChromeClient.h: 35 (WebCore::ChromeClient::hasPageLevelStorageAccess const): 36 1 37 2021-09-13 Youenn Fablet <youenn@apple.com> 2 38 -
trunk/Source/WebCore/dom/BroadcastChannel.cpp
r282105 r282366 28 28 29 29 #include "BroadcastChannelRegistry.h" 30 #include "Chrome.h" 31 #include "ChromeClient.h" 30 32 #include "EventNames.h" 31 33 #include "MessageEvent.h" … … 58 60 } 59 61 62 static bool shouldPartitionOrigin(Document& document) 63 { 64 if (!document.settings().broadcastChannelOriginPartitioningEnabled()) 65 return false; 66 67 #if ENABLE(RESOURCE_LOAD_STATISTICS) 68 if (!document.settings().storageAccessAPIEnabled()) 69 return true; 70 71 auto* page = document.page(); 72 if (!page) 73 return true; 74 75 return !page->chrome().client().hasPageLevelStorageAccess(RegistrableDomain::uncheckedCreateFromHost(document.topDocument().securityOrigin().host()), RegistrableDomain::uncheckedCreateFromHost(document.securityOrigin().host())); 76 #else 77 return true; 78 #endif 79 } 80 81 class BroadcastChannel::MainThreadBridge : public ThreadSafeRefCounted<MainThreadBridge, WTF::DestructionThread::Main> { 82 public: 83 static Ref<MainThreadBridge> create(BroadcastChannel& channel, const String& name) 84 { 85 return adoptRef(*new MainThreadBridge(channel, name)); 86 } 87 88 void registerChannel(); 89 void unregisterChannel(); 90 void postMessage(Ref<SerializedScriptValue>&&); 91 92 String name() const { return m_name.isolatedCopy(); } 93 BroadcastChannelIdentifier identifier() const { return m_identifier; } 94 95 private: 96 MainThreadBridge(BroadcastChannel&, const String& name); 97 98 void ensureOnMainThread(Function<void(Document&)>&&); 99 100 WeakPtr<BroadcastChannel> m_broadcastChannel; 101 const BroadcastChannelIdentifier m_identifier; 102 const String m_name; // Main thread only. 103 ClientOrigin m_origin; // Main thread only. 104 }; 105 106 BroadcastChannel::MainThreadBridge::MainThreadBridge(BroadcastChannel& channel, const String& name) 107 : m_broadcastChannel(makeWeakPtr(channel)) 108 , m_identifier(BroadcastChannelIdentifier::generateThreadSafe()) 109 , m_name(name.isolatedCopy()) 110 { 111 } 112 113 void BroadcastChannel::MainThreadBridge::ensureOnMainThread(Function<void(Document&)>&& task) 114 { 115 ASSERT(m_broadcastChannel); 116 if (!m_broadcastChannel) 117 return; 118 119 auto* context = m_broadcastChannel->scriptExecutionContext(); 120 if (!context) 121 return; 122 ASSERT(context->isContextThread()); 123 124 Ref protectedThis { *this }; 125 if (is<Document>(*context)) 126 task(downcast<Document>(*context)); 127 else { 128 downcast<WorkerGlobalScope>(*context).thread().workerLoaderProxy().postTaskToLoader([protectedThis = WTFMove(protectedThis), task = WTFMove(task)](auto& context) { 129 task(downcast<Document>(context)); 130 }); 131 } 132 } 133 134 void BroadcastChannel::MainThreadBridge::registerChannel() 135 { 136 ensureOnMainThread([this, contextIdentifier = m_broadcastChannel->scriptExecutionContext()->contextIdentifier()](auto& document) { 137 m_origin = { shouldPartitionOrigin(document) ? document.topOrigin().data() : document.securityOrigin().data(), document.securityOrigin().data() }; 138 if (auto* page = document.page()) 139 page->broadcastChannelRegistry().registerChannel(m_origin, m_name, m_identifier); 140 channelToContextIdentifier().add(m_identifier, contextIdentifier); 141 }); 142 } 143 144 void BroadcastChannel::MainThreadBridge::unregisterChannel() 145 { 146 ensureOnMainThread([this](auto& document) { 147 if (auto* page = document.page()) 148 page->broadcastChannelRegistry().unregisterChannel(m_origin, m_name, m_identifier); 149 channelToContextIdentifier().remove(m_identifier); 150 }); 151 } 152 153 void BroadcastChannel::MainThreadBridge::postMessage(Ref<SerializedScriptValue>&& message) 154 { 155 ensureOnMainThread([this, message = WTFMove(message)](auto& document) mutable { 156 auto* page = document.page(); 157 if (!page) 158 return; 159 160 auto blobHandles = message->blobHandles(); 161 page->broadcastChannelRegistry().postMessage(m_origin, m_name, m_identifier, WTFMove(message), [blobHandles = WTFMove(blobHandles)] { 162 // Keeps Blob data inside messageData alive until the message has been delivered. 163 }); 164 }); 165 } 166 60 167 BroadcastChannel::BroadcastChannel(ScriptExecutionContext& context, const String& name) 61 168 : ActiveDOMObject(&context) 62 , m_name(name) 63 , m_origin { context.settingsValues().broadcastChannelOriginPartitioningEnabled ? context.topOrigin().data() : context.securityOrigin()->data(), context.securityOrigin()->data() } 64 , m_identifier(BroadcastChannelIdentifier::generateThreadSafe()) 169 , m_mainThreadBridge(MainThreadBridge::create(*this, name)) 65 170 { 66 171 { 67 172 Locker locker { allBroadcastChannelsLock }; 68 allBroadcastChannels().add(m_identifier, this); 69 } 70 71 ensureOnMainThread([origin = crossThreadCopy(m_origin), name = crossThreadCopy(m_name), contextIdentifier = context.contextIdentifier(), channelIdentifier = m_identifier](auto& document) { 72 if (auto* page = document.page()) 73 page->broadcastChannelRegistry().registerChannel(origin, name, channelIdentifier); 74 channelToContextIdentifier().add(channelIdentifier, contextIdentifier); 75 }); 173 allBroadcastChannels().add(m_mainThreadBridge->identifier(), this); 174 } 175 m_mainThreadBridge->registerChannel(); 76 176 } 77 177 … … 81 181 { 82 182 Locker locker { allBroadcastChannelsLock }; 83 allBroadcastChannels().remove(m_identifier); 84 } 183 allBroadcastChannels().remove(m_mainThreadBridge->identifier()); 184 } 185 } 186 187 BroadcastChannelIdentifier BroadcastChannel::identifier() const 188 { 189 return m_mainThreadBridge->identifier(); 190 } 191 192 String BroadcastChannel::name() const 193 { 194 return m_mainThreadBridge->name(); 85 195 } 86 196 … … 96 206 ASSERT(ports.isEmpty()); 97 207 98 ensureOnMainThread([origin = crossThreadCopy(m_origin), name = crossThreadCopy(m_name), identifier = m_identifier, messageData = messageData.releaseReturnValue()](auto& document) mutable { 99 auto* page = document.page(); 100 if (!page) 101 return; 102 103 auto blobHandles = messageData->blobHandles(); 104 page->broadcastChannelRegistry().postMessage(origin, name, identifier, WTFMove(messageData), [blobHandles = WTFMove(blobHandles)] { 105 // Keeps Blob data inside messageData alive until the message has been delivered. 106 }); 107 }); 108 208 m_mainThreadBridge->postMessage(messageData.releaseReturnValue()); 109 209 return { }; 110 210 } … … 116 216 117 217 m_isClosed = true; 118 ensureOnMainThread([origin = crossThreadCopy(m_origin), name = crossThreadCopy(m_name), channelIdentifier = m_identifier](auto& document) { 119 if (auto* page = document.page()) 120 page->broadcastChannelRegistry().unregisterChannel(origin, name, channelIdentifier); 121 channelToContextIdentifier().remove(channelIdentifier); 122 }); 218 m_mainThreadBridge->unregisterChannel(); 123 219 } 124 220 … … 150 246 151 247 queueTaskKeepingObjectAlive(*this, TaskSource::PostedMessageQueue, [this, message = WTFMove(message)]() mutable { 152 if (!m_isClosed) 153 dispatchEvent(MessageEvent::create({ }, WTFMove(message), m_origin.clientOrigin.toString())); 154 }); 155 } 156 157 void BroadcastChannel::ensureOnMainThread(Function<void(Document&)>&& task) 158 { 159 auto* context = scriptExecutionContext(); 160 if (!context) 161 return; 162 163 if (is<Document>(*context)) 164 task(downcast<Document>(*context)); 165 else { 166 downcast<WorkerGlobalScope>(*context).thread().workerLoaderProxy().postTaskToLoader([task = WTFMove(task)](auto& context) { 167 task(downcast<Document>(context)); 168 }); 169 } 248 if (!m_isClosed && scriptExecutionContext()) 249 dispatchEvent(MessageEvent::create({ }, WTFMove(message), scriptExecutionContext()->securityOrigin()->toString())); 250 }); 170 251 } 171 252 -
trunk/Source/WebCore/dom/BroadcastChannel.h
r282105 r282366 57 57 using RefCounted<BroadcastChannel>::deref; 58 58 59 BroadcastChannelIdentifier identifier() const { return m_identifier; }60 const String& name() const { return m_name; }59 BroadcastChannelIdentifier identifier() const; 60 String name() const; 61 61 62 62 ExceptionOr<void> postMessage(JSC::JSGlobalObject&, JSC::JSValue message); … … 83 83 void stop() final { close(); } 84 84 85 const String m_name; 86 const ClientOrigin m_origin; 87 const BroadcastChannelIdentifier m_identifier; 85 class MainThreadBridge; 86 Ref<MainThreadBridge> m_mainThreadBridge; 88 87 bool m_isClosed { false }; 89 88 bool m_hasRelevantEventListener { false }; -
trunk/Source/WebCore/page/ChromeClient.h
r281980 r282366 555 555 virtual void hasStorageAccess(RegistrableDomain&& /*subFrameDomain*/, RegistrableDomain&& /*topFrameDomain*/, Frame&, WTF::CompletionHandler<void(bool)>&& completionHandler) { completionHandler(false); } 556 556 virtual void requestStorageAccess(RegistrableDomain&& subFrameDomain, RegistrableDomain&& topFrameDomain, Frame&, StorageAccessScope scope, WTF::CompletionHandler<void(RequestStorageAccessResult)>&& completionHandler) { completionHandler({ StorageAccessWasGranted::No, StorageAccessPromptWasShown::No, scope, WTFMove(topFrameDomain), WTFMove(subFrameDomain) }); } 557 virtual bool hasPageLevelStorageAccess(const RegistrableDomain& /*topLevelDomain*/, const RegistrableDomain& /*resourceDomain*/) const { return false; } 557 558 #endif 558 559 -
trunk/Source/WebKit/ChangeLog
r282365 r282366 1 2021-09-13 Chris Dumez <cdumez@apple.com> 2 3 Relax BroadcastChannel origin partitioning if iframe has storage access 4 https://bugs.webkit.org/show_bug.cgi?id=230164 5 6 Reviewed by Alex Christensen. 7 8 * WebProcess/WebCoreSupport/WebChromeClient.cpp: 9 (WebKit::WebChromeClient::hasPageLevelStorageAccess const): 10 * WebProcess/WebCoreSupport/WebChromeClient.h: 11 1 12 2021-09-13 Chris Dumez <cdumez@apple.com> 2 13 -
trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
r281980 r282366 1442 1442 m_page.requestStorageAccess(WTFMove(subFrameDomain), WTFMove(topFrameDomain), *webFrame, scope, WTFMove(completionHandler)); 1443 1443 } 1444 1445 bool WebChromeClient::hasPageLevelStorageAccess(const WebCore::RegistrableDomain& topLevelDomain, const WebCore::RegistrableDomain& resourceDomain) const 1446 { 1447 return m_page.hasPageLevelStorageAccess(topLevelDomain, resourceDomain); 1448 } 1444 1449 #endif 1445 1450 -
trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h
r281980 r282366 411 411 void hasStorageAccess(WebCore::RegistrableDomain&& subFrameDomain, WebCore::RegistrableDomain&& topFrameDomain, WebCore::Frame&, WTF::CompletionHandler<void(bool)>&&) final; 412 412 void requestStorageAccess(WebCore::RegistrableDomain&& subFrameDomain, WebCore::RegistrableDomain&& topFrameDomain, WebCore::Frame&, WebCore::StorageAccessScope, WTF::CompletionHandler<void(WebCore::RequestStorageAccessResult)>&&) final; 413 bool hasPageLevelStorageAccess(const WebCore::RegistrableDomain& topLevelDomain, const WebCore::RegistrableDomain& resourceDomain) const final; 413 414 #endif 414 415
Note: See TracChangeset
for help on using the changeset viewer.