Changeset 280958 in webkit
- Timestamp:
- Aug 12, 2021, 2:37:05 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 18 edited
- 2 copied
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/http/wpt/webrtc/sframe-transform-error-expected.txt (added)
-
LayoutTests/http/wpt/webrtc/sframe-transform-error-worker.js (added)
-
LayoutTests/http/wpt/webrtc/sframe-transform-error.html (added)
-
Source/WebCore/CMakeLists.txt (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/DerivedSources-input.xcfilelist (modified) (1 diff)
-
Source/WebCore/DerivedSources-output.xcfilelist (modified) (1 diff)
-
Source/WebCore/DerivedSources.make (modified) (1 diff)
-
Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp (modified) (8 diffs)
-
Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.h (modified) (4 diffs)
-
Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.idl (modified) (3 diffs)
-
Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformErrorEvent.cpp (added)
-
Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformErrorEvent.h (copied) (copied from trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.idl ) (2 diffs)
-
Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformErrorEvent.idl (copied) (copied from trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.idl ) (3 diffs)
-
Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.cpp (modified) (9 diffs)
-
Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.h (modified) (3 diffs)
-
Source/WebCore/Sources.txt (modified) (2 diffs)
-
Source/WebCore/WebCore.xcodeproj/project.pbxproj (modified) (2 diffs)
-
Source/WebCore/bindings/js/WebCoreBuiltinNames.h (modified) (1 diff)
-
Source/WebCore/dom/EventNames.in (modified) (1 diff)
-
Source/WebCore/dom/EventTargetFactory.in (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r280954 r280958 1 2021-08-12 Youenn Fablet <youenn@apple.com> 2 3 Implement SFrameTransform error handling 4 https://bugs.webkit.org/show_bug.cgi?id=228947 5 6 Reviewed by Eric Carlson. 7 8 * http/wpt/webrtc/sframe-transform-error-worker.js: Added. 9 (onrtctransform.async event): 10 * http/wpt/webrtc/sframe-transform-error.html: Added. 11 * http/wpt/webrtc/sframe-transform-error-expected: Added. 12 1 13 2021-08-11 Lauro Moura <lmoura@igalia.com> 2 14 -
trunk/Source/WebCore/CMakeLists.txt
r280778 r280958 413 413 Modules/mediastream/RTCRtpRtxParameters.idl 414 414 Modules/mediastream/RTCRtpSFrameTransform.idl 415 Modules/mediastream/RTCRtpSFrameTransformErrorEvent.idl 415 416 Modules/mediastream/RTCRtpScriptTransform.idl 416 417 Modules/mediastream/RTCRtpScriptTransformProvider.idl -
trunk/Source/WebCore/ChangeLog
r280956 r280958 1 2021-08-12 Youenn Fablet <youenn@apple.com> 2 3 Implement SFrameTransform error handling 4 https://bugs.webkit.org/show_bug.cgi?id=228947 5 6 Reviewed by Eric Carlson. 7 8 Add support for RTCRtpSFrameTransformErrorEvent. 9 When RTCRtpSFrameTransformer encounters an issue, dispatch a task to RTCRtpSFrameTransform context and fire a corresponding event. 10 This follows https://w3c.github.io/webrtc-encoded-transform/#sframe-transform-algorithm, except that: 11 - we are not yet exposing some fields in RTCRtpSFrameTransformErrorEvent. 12 - we are using errorType instead of type which should be fixed in the spec. 13 14 Test: imported/w3c/web-platform-tests/webrtc-encoded-transform/sframe-transform-error.html 15 16 * CMakeLists.txt: 17 * DerivedSources-input.xcfilelist: 18 * DerivedSources-output.xcfilelist: 19 * DerivedSources.make: 20 * Modules/mediastream/RTCRtpSFrameTransform.cpp: 21 (WebCore::RTCRtpSFrameTransform::RTCRtpSFrameTransform): 22 (WebCore::errorTypeFromInformation): 23 (WebCore::processFrame): 24 (WebCore::RTCRtpSFrameTransform::hasKey const): 25 (WebCore::RTCRtpSFrameTransform::initializeTransformer): 26 (WebCore::transformFrame): 27 (WebCore::RTCRtpSFrameTransform::createStreams): 28 (WebCore::RTCRtpSFrameTransform::writable): 29 (WebCore::RTCRtpSFrameTransform::virtualHasPendingActivity const): 30 * Modules/mediastream/RTCRtpSFrameTransform.h: 31 * Modules/mediastream/RTCRtpSFrameTransform.idl: 32 * Modules/mediastream/RTCRtpSFrameTransformErrorEvent.cpp: Added. 33 (WebCore::RTCRtpSFrameTransformErrorEvent::create): 34 (WebCore::RTCRtpSFrameTransformErrorEvent::RTCRtpSFrameTransformErrorEvent): 35 (WebCore::RTCRtpSFrameTransformErrorEvent::eventInterface const): 36 * Modules/mediastream/RTCRtpSFrameTransformErrorEvent.h: Added. 37 * Modules/mediastream/RTCRtpSFrameTransformErrorEvent.idl: Added. 38 * Modules/mediastream/RTCRtpSFrameTransformer.cpp: 39 (WebCore::RTCRtpSFrameTransformer::hasKey const): 40 (WebCore::RTCRtpSFrameTransformer::decryptFrame): 41 (WebCore::RTCRtpSFrameTransformer::encryptFrame): 42 (WebCore::RTCRtpSFrameTransformer::transform): 43 * Modules/mediastream/RTCRtpSFrameTransformer.h: 44 * Sources.txt: 45 * WebCore.xcodeproj/project.pbxproj: 46 * bindings/js/WebCoreBuiltinNames.h: 47 * dom/EventNames.in: 48 * dom/EventTargetFactory.in: 49 1 50 2021-08-11 Alex Christensen <achristensen@webkit.org> 2 51 -
trunk/Source/WebCore/DerivedSources-input.xcfilelist
r280467 r280958 257 257 $(PROJECT_DIR)/Modules/mediastream/RTCRtpRtxParameters.idl 258 258 $(PROJECT_DIR)/Modules/mediastream/RTCRtpSFrameTransform.idl 259 $(PROJECT_DIR)/Modules/mediastream/RTCRtpSFrameTransformErrorEvent.idl 259 260 $(PROJECT_DIR)/Modules/mediastream/RTCRtpScriptTransform.idl 260 261 $(PROJECT_DIR)/Modules/mediastream/RTCRtpScriptTransformProvider.idl -
trunk/Source/WebCore/DerivedSources-output.xcfilelist
r280467 r280958 1698 1698 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSFrameTransform.cpp 1699 1699 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSFrameTransform.h 1700 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSFrameTransformErrorEvent.cpp 1701 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSFrameTransformErrorEvent.h 1700 1702 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpScriptTransform.cpp 1701 1703 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpScriptTransform.h -
trunk/Source/WebCore/DerivedSources.make
r280467 r280958 284 284 $(WebCore)/Modules/mediastream/RTCRtpSender+Transform.idl \ 285 285 $(WebCore)/Modules/mediastream/RTCRtpSFrameTransform.idl \ 286 $(WebCore)/Modules/mediastream/RTCRtpSFrameTransformErrorEvent.idl \ 286 287 $(WebCore)/Modules/mediastream/RTCRtpScriptTransform.idl \ 287 288 $(WebCore)/Modules/mediastream/RTCRtpScriptTransformProvider.idl \ -
trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp
r278523 r280958 36 36 #include "RTCEncodedAudioFrame.h" 37 37 #include "RTCEncodedVideoFrame.h" 38 #include "RTCRtpSFrameTransformErrorEvent.h" 38 39 #include "RTCRtpSFrameTransformer.h" 39 40 #include "RTCRtpTransformBackend.h" … … 44 45 #include "WritableStream.h" 45 46 #include "WritableStreamSink.h" 47 #include <wtf/IsoMallocInlines.h> 46 48 47 49 namespace WebCore { 48 50 51 WTF_MAKE_ISO_ALLOCATED_IMPL(RTCRtpSFrameTransform); 52 49 53 RTCRtpSFrameTransform::RTCRtpSFrameTransform(ScriptExecutionContext& context, Options options) 50 : ContextDestructionObserver(&context)54 : ActiveDOMObject(&context) 51 55 , m_transformer(RTCRtpSFrameTransformer::create(options.compatibilityMode)) 52 56 { 57 suspendIfNeeded(); 58 53 59 m_transformer->setIsEncrypting(options.role == Role::Encrypt); 54 60 m_transformer->setAuthenticationSize(options.authenticationSize); … … 96 102 } 97 103 104 static RTCRtpSFrameTransformErrorEvent::Type errorTypeFromInformation(const RTCRtpSFrameTransformer::ErrorInformation& errorInformation) 105 { 106 switch (errorInformation.error) { 107 case RTCRtpSFrameTransformer::Error::KeyID: 108 return RTCRtpSFrameTransformErrorEvent::Type::KeyID; 109 case RTCRtpSFrameTransformer::Error::Authentication: 110 return RTCRtpSFrameTransformErrorEvent::Type::Authentication; 111 case RTCRtpSFrameTransformer::Error::Syntax: 112 return RTCRtpSFrameTransformErrorEvent::Type::Syntax; 113 case RTCRtpSFrameTransformer::Error::Other: 114 return RTCRtpSFrameTransformErrorEvent::Type::Other; 115 } 116 } 117 118 static std::optional<Vector<uint8_t>> processFrame(const uint8_t* data, size_t size, RTCRtpSFrameTransformer& transformer, ScriptExecutionContextIdentifier identifier, const WeakPtr<RTCRtpSFrameTransform>& weakTransform) 119 { 120 auto result = transformer.transform(data, size); 121 if (!result.has_value()) { 122 auto errorInformation = WTFMove(result.error()); 123 errorInformation.message = { }; 124 RELEASE_LOG_ERROR(WebRTC, "RTCRtpSFrameTransform failed transforming a frame with error %d", errorInformation.error); 125 // Call the error event handler. 126 ScriptExecutionContext::postTaskTo(identifier, [errorInformation, weakTransform](auto&&) { 127 if (!weakTransform || weakTransform->isContextStopped()) 128 return; 129 if (errorInformation.error == RTCRtpSFrameTransformer::Error::KeyID && weakTransform->hasKey(errorInformation.keyId)) 130 return; 131 weakTransform->dispatchEvent(RTCRtpSFrameTransformErrorEvent::create(Event::CanBubble::No, Event::IsCancelable::No, errorTypeFromInformation(errorInformation))); 132 }); 133 return { }; 134 } 135 return WTFMove(result.value()); 136 } 137 138 bool RTCRtpSFrameTransform::hasKey(uint64_t keyID) const 139 { 140 return m_transformer->hasKey(keyID); 141 } 142 98 143 void RTCRtpSFrameTransform::initializeTransformer(RTCRtpTransformBackend& backend, Side side) 99 144 { 100 145 ASSERT(!isAttached()); 146 147 auto* context = scriptExecutionContext(); 148 if (!context) 149 return; 101 150 102 151 m_isAttached = true; … … 109 158 m_transformer->setMediaType(backend.mediaType()); 110 159 111 backend.setTransformableFrameCallback([transformer = m_transformer, backend = makeRef(backend)](auto&& frame) {160 backend.setTransformableFrameCallback([transformer = m_transformer, identifier = context->contextIdentifier(), backend = makeRef(backend), weakThis = makeWeakPtr(this)](auto&& frame) { 112 161 auto chunk = frame->data(); 113 auto result = transformer->transform(chunk.data, chunk.size); 114 115 if (result.hasException()) { 116 RELEASE_LOG_ERROR(WebRTC, "RTCRtpSFrameTransform failed transforming a frame"); 162 if (!chunk.data || !chunk.size) 117 163 return; 118 } 119 120 frame->setData({ result.returnValue().data(), result.returnValue().size() }); 164 auto result = processFrame(chunk.data, chunk.size, transformer.get(), identifier, weakThis); 165 166 if (!result) 167 return; 168 169 frame->setData({ result.value().data(), result.value().size() }); 121 170 122 171 backend->processTransformedFrame(frame.get()); … … 139 188 } 140 189 190 static void transformFrame(const uint8_t* data, size_t size, JSDOMGlobalObject& globalObject, RTCRtpSFrameTransformer& transformer, SimpleReadableStreamSource& source, ScriptExecutionContextIdentifier identifier, const WeakPtr<RTCRtpSFrameTransform>& weakTransform) 191 { 192 auto result = processFrame(data, size, transformer, identifier, weakTransform); 193 auto buffer = result ? SharedBuffer::create(WTFMove(*result)) : SharedBuffer::create(); 194 source.enqueue(toJS(&globalObject, &globalObject, buffer->tryCreateArrayBuffer().get())); 195 } 196 141 197 template<typename Frame> 142 void transformFrame(Frame& frame, JSDOMGlobalObject& globalObject, RTCRtpSFrameTransformer& transformer, SimpleReadableStreamSource& source )198 void transformFrame(Frame& frame, JSDOMGlobalObject& globalObject, RTCRtpSFrameTransformer& transformer, SimpleReadableStreamSource& source, ScriptExecutionContextIdentifier identifier, const WeakPtr<RTCRtpSFrameTransform>& weakTransform) 143 199 { 144 200 auto chunk = frame.rtcFrame().data(); 145 auto result = transformer.transform(chunk.data, chunk.size); 146 RELEASE_LOG_ERROR_IF(result.hasException(), WebRTC, "RTCRtpSFrameTransform failed transforming a frame"); 147 201 auto result = processFrame(chunk.data, chunk.size, transformer, identifier, weakTransform); 148 202 RTCRtpTransformableFrame::Data transformedChunk; 149 // In case of error, we just pass along the frame with empty data. 150 if (!result.hasException()) 151 transformedChunk = { result.returnValue().data(), result.returnValue().size() }; 152 203 if (result) 204 transformedChunk = { result->data(), result->size() }; 153 205 frame.rtcFrame().setData(transformedChunk); 154 206 source.enqueue(toJS(&globalObject, &globalObject, frame)); 155 }156 157 static void transformFrame(const uint8_t* data, size_t size, JSDOMGlobalObject& globalObject, RTCRtpSFrameTransformer& transformer, SimpleReadableStreamSource& source)158 {159 auto result = transformer.transform(data, size);160 RELEASE_LOG_ERROR_IF(result.hasException(), WebRTC, "RTCRtpSFrameTransform failed transforming a frame");161 162 auto buffer = result.hasException() ? SharedBuffer::create() : SharedBuffer::create(result.releaseReturnValue());163 source.enqueue(toJS(&globalObject, &globalObject, buffer->tryCreateArrayBuffer().get()));164 207 } 165 208 … … 171 214 return; 172 215 173 auto writable = WritableStream::create(globalObject, SimpleWritableStreamSink::create([transformer = m_transformer, readableStreamSource = m_readableStreamSource ](auto& context, auto value) -> ExceptionOr<void> {216 auto writable = WritableStream::create(globalObject, SimpleWritableStreamSink::create([transformer = m_transformer, readableStreamSource = m_readableStreamSource, weakThis = makeWeakPtr(this)](auto& context, auto value) -> ExceptionOr<void> { 174 217 if (!context.globalObject()) 175 218 return Exception { InvalidStateError }; … … 183 226 // We do not want to throw any exception in the transform to make sure we do not error the transform. 184 227 WTF::switchOn(frame, [&](RefPtr<RTCEncodedAudioFrame>& value) { 185 transformFrame(*value, globalObject, transformer.get(), *readableStreamSource );228 transformFrame(*value, globalObject, transformer.get(), *readableStreamSource, context.contextIdentifier(), weakThis); 186 229 }, [&](RefPtr<RTCEncodedVideoFrame>& value) { 187 transformFrame(*value, globalObject, transformer.get(), *readableStreamSource );230 transformFrame(*value, globalObject, transformer.get(), *readableStreamSource, context.contextIdentifier(), weakThis); 188 231 }, [&](RefPtr<ArrayBuffer>& value) { 189 transformFrame(static_cast<const uint8_t*>(value->data()), value->byteLength(), globalObject, transformer.get(), *readableStreamSource );232 transformFrame(static_cast<const uint8_t*>(value->data()), value->byteLength(), globalObject, transformer.get(), *readableStreamSource, context.contextIdentifier(), weakThis); 190 233 }, [&](RefPtr<ArrayBufferView>& value) { 191 transformFrame(static_cast<const uint8_t*>(value->data()), value->byteLength(), globalObject, transformer.get(), *readableStreamSource );234 transformFrame(static_cast<const uint8_t*>(value->data()), value->byteLength(), globalObject, transformer.get(), *readableStreamSource, context.contextIdentifier(), weakThis); 192 235 }); 193 236 return { }; … … 233 276 createStreams(*globalObject); 234 277 278 m_hasWritable = true; 235 279 return m_writable.copyRef(); 236 280 } 237 281 282 bool RTCRtpSFrameTransform::virtualHasPendingActivity() const 283 { 284 return (m_isAttached || m_hasWritable) && hasEventListeners(); 285 } 286 238 287 } // namespace WebCore 239 288 -
trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.h
r278253 r280958 28 28 #if ENABLE(WEB_RTC) 29 29 30 #include "ContextDestructionObserver.h" 30 #include "ActiveDOMObject.h" 31 #include "EventTarget.h" 31 32 #include "JSDOMPromiseDeferred.h" 32 33 #include "RTCRtpSFrameTransformer.h" 34 #include <wtf/WeakPtr.h> 33 35 34 36 namespace JSC { … … 44 46 class WritableStream; 45 47 46 class RTCRtpSFrameTransform : public RefCounted<RTCRtpSFrameTransform>, private ContextDestructionObserver { 48 class RTCRtpSFrameTransform : public RefCounted<RTCRtpSFrameTransform>, public ActiveDOMObject, public EventTargetWithInlineData { 49 WTF_MAKE_ISO_ALLOCATED(RTCRtpSFrameTransform); 47 50 public: 48 51 enum class Role { Encrypt, Decrypt }; … … 71 74 ExceptionOr<RefPtr<WritableStream>> writable(); 72 75 76 bool hasKey(uint64_t) const; 77 78 using RefCounted<RTCRtpSFrameTransform>::ref; 79 using RefCounted<RTCRtpSFrameTransform>::deref; 80 73 81 private: 74 82 RTCRtpSFrameTransform(ScriptExecutionContext&, Options); 83 84 // ActiveDOMObject 85 const char* activeDOMObjectName() const final { return "RTCRtpSFrameTransform"; } 86 bool virtualHasPendingActivity() const final; 87 88 // EventTargetWithInlineData 89 EventTargetInterface eventTargetInterface() const final { return RTCRtpSFrameTransformEventTargetInterfaceType; } 90 ScriptExecutionContext* scriptExecutionContext() const final { return ContextDestructionObserver::scriptExecutionContext(); } 91 void refEventTarget() final { ref(); } 92 void derefEventTarget() final { deref(); } 75 93 76 94 enum class Side { Sender, Receiver }; … … 79 97 80 98 bool m_isAttached { false }; 99 bool m_hasWritable { false }; 81 100 Ref<RTCRtpSFrameTransformer> m_transformer; 82 101 RefPtr<ReadableStream> m_readable; -
trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.idl
r274832 r280958 42 42 43 43 [ 44 ActiveDOMObject, 44 45 Conditional=WEB_RTC, 45 46 EnabledBySetting=WebRTCInsertableStreams, … … 48 49 InterfaceName=SFrameTransform, 49 50 JSGenerateToNativeObject, 50 ] interface RTCRtpSFrameTransform {51 ] interface RTCRtpSFrameTransform : EventTarget { 51 52 [CallWith=ScriptExecutionContext] constructor(optional RTCRtpSFrameTransformOptions options); 52 53 … … 58 59 readonly attribute ReadableStream readable; 59 60 readonly attribute WritableStream writable; 61 62 attribute EventHandler onerror; 60 63 }; -
trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformErrorEvent.h
r280957 r280958 1 1 /* 2 * Copyright (C) 202 0Apple Inc. All rights reserved.2 * Copyright (C) 2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 enum RTCRtpSFrameTransformRole { 27 "encrypt", 28 "decrypt" 26 #pragma once 27 28 #if ENABLE(WEB_RTC) 29 30 #include "Event.h" 31 32 namespace WebCore { 33 34 class RTCRtpSFrameTransformErrorEvent final : public Event { 35 WTF_MAKE_ISO_ALLOCATED(RTCRtpSFrameTransformErrorEvent); 36 public: 37 virtual ~RTCRtpSFrameTransformErrorEvent(); 38 39 enum Type { Authentication, KeyID, Other, Syntax }; 40 41 struct Init : EventInit { 42 Type errorType; 43 }; 44 45 static Ref<RTCRtpSFrameTransformErrorEvent> create(const AtomString& type, Init&&); 46 static Ref<RTCRtpSFrameTransformErrorEvent> create(CanBubble, IsCancelable, Type); 47 48 Type errorType() const { return m_errorType; } 49 50 virtual EventInterface eventInterface() const; 51 52 private: 53 RTCRtpSFrameTransformErrorEvent(const AtomString& type, CanBubble, IsCancelable, Type); 54 55 Type m_errorType; 29 56 }; 30 57 31 enum RTCRtpSFrameTransformCompatibilityMode { 32 "none", 33 "H264", 34 "VP8" 35 }; 58 } // namespace WebCore 36 59 37 dictionary RTCRtpSFrameTransformOptions { 38 RTCRtpSFrameTransformRole role = "encrypt"; 39 unsigned long authenticationSize = 10; 40 RTCRtpSFrameTransformCompatibilityMode compatibilityMode = "none"; 41 }; 42 43 [ 44 Conditional=WEB_RTC, 45 EnabledBySetting=WebRTCInsertableStreams, 46 ExportMacro=WEBCORE_EXPORT, 47 Exposed=(Window,DedicatedWorker), 48 InterfaceName=SFrameTransform, 49 JSGenerateToNativeObject, 50 ] interface RTCRtpSFrameTransform { 51 [CallWith=ScriptExecutionContext] constructor(optional RTCRtpSFrameTransformOptions options); 52 53 [Custom] Promise<undefined> setEncryptionKey(CryptoKey key, optional any keyID); 54 // FIXME: Add support for missing methods. 55 // Promise<undefined> ratchetEncryptionKey(); 56 // Promise<undefined> setSigningKey(CryptoKey key); 57 58 readonly attribute ReadableStream readable; 59 readonly attribute WritableStream writable; 60 }; 60 #endif // ENABLE(WEB_RTC) -
trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformErrorEvent.idl
r280957 r280958 1 1 /* 2 * Copyright (C) 202 0Apple Inc. All rights reserved.2 * Copyright (C) 2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 enum RTCRtpSFrameTransformRole { 27 "encrypt", 28 "decrypt" 26 enum RTCRtpSFrameTransformErrorEventType { 27 "authentication", 28 "keyID", 29 "other", 30 "syntax" 29 31 }; 30 32 31 enum RTCRtpSFrameTransformCompatibilityMode { 32 "none", 33 "H264", 34 "VP8" 35 }; 36 37 dictionary RTCRtpSFrameTransformOptions { 38 RTCRtpSFrameTransformRole role = "encrypt"; 39 unsigned long authenticationSize = 10; 40 RTCRtpSFrameTransformCompatibilityMode compatibilityMode = "none"; 33 dictionary RTCRtpSFrameTransformErrorEventInit : EventInit { 34 required RTCRtpSFrameTransformErrorEventType errorType; 41 35 }; 42 36 … … 44 38 Conditional=WEB_RTC, 45 39 EnabledBySetting=WebRTCInsertableStreams, 46 ExportMacro=WEBCORE_EXPORT,47 40 Exposed=(Window,DedicatedWorker), 48 InterfaceName=SFrameTransform, 49 JSGenerateToNativeObject, 50 ] interface RTCRtpSFrameTransform { 51 [CallWith=ScriptExecutionContext] constructor(optional RTCRtpSFrameTransformOptions options); 41 InterfaceName=SFrameTransformErrorEvent 42 ] interface RTCRtpSFrameTransformErrorEvent : Event { 43 constructor(DOMString type, RTCRtpSFrameTransformErrorEventInit eventInitDict); 52 44 53 [Custom] Promise<undefined> setEncryptionKey(CryptoKey key, optional any keyID); 54 // FIXME: Add support for missing methods. 55 // Promise<undefined> ratchetEncryptionKey(); 56 // Promise<undefined> setSigningKey(CryptoKey key); 57 58 readonly attribute ReadableStream readable; 59 readonly attribute WritableStream writable; 45 readonly attribute RTCRtpSFrameTransformErrorEventType errorType; 46 // FIXME: Add below fields 47 // readonly attribute CryptoKeyID? keyID; 48 // readonly attribute any frame; 60 49 }; -
trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.cpp
r278253 r280958 30 30 31 31 #include "SFrameUtils.h" 32 #include <wtf/Algorithms.h> 32 33 33 34 namespace WebCore { … … 161 162 } 162 163 164 bool RTCRtpSFrameTransformer::hasKey(uint64_t keyId) const 165 { 166 Locker locker { m_keyLock }; 167 return WTF::anyOf(m_keys, [keyId](auto& key) { return keyId == key.keyId; }); 168 } 169 163 170 ExceptionOr<void> RTCRtpSFrameTransformer::updateEncryptionKey(const Vector<uint8_t>& rawKey, std::optional<uint64_t> keyId, ShouldUpdateKeys shouldUpdateKeys) 164 171 { … … 200 207 } 201 208 202 ExceptionOr<Vector<uint8_t>>RTCRtpSFrameTransformer::decryptFrame(const uint8_t* frameData, size_t frameSize)209 RTCRtpSFrameTransformer::TransformResult RTCRtpSFrameTransformer::decryptFrame(const uint8_t* frameData, size_t frameSize) 203 210 { 204 211 Vector<uint8_t> buffer; … … 230 237 231 238 if (!header) 232 return Exception { NotSupportedError };239 return makeUnexpected(ErrorInformation {Error::Syntax, "Invalid header"_s, 0 }); 233 240 234 241 if (header->counter <= m_counter && m_counter) 235 return Exception { InvalidStateError };242 return makeUnexpected(ErrorInformation {Error::Syntax, "Invalid counter"_s, 0 }); 236 243 m_counter = header->counter; 237 244 … … 239 246 auto position = m_keys.findMatching([keyId = header->keyId](auto& item) { return item.keyId == keyId; }); 240 247 if (position == notFound) 241 return Exception { DataError, "Key ID is unknown" };248 return makeUnexpected(ErrorInformation { Error::KeyID, "Key ID is unknown"_s, header->keyId }); 242 249 auto result = updateEncryptionKey(m_keys[position].keyData, header->keyId, ShouldUpdateKeys::No); 243 250 if (result.hasException()) 244 return result.releaseException();251 return makeUnexpected(ErrorInformation {Error::Other, result.exception().message(), 0 }); 245 252 } 246 253 247 254 if (frameSize < (header->size + m_authenticationSize)) 248 return Exception { DataError, "Chunk is too small for authentication size" };255 return makeUnexpected(ErrorInformation { Error::Syntax, "Chunk is too small for authentication size"_s, 0 }); 249 256 250 257 auto iv = computeIV(m_counter, m_saltKey); … … 256 263 if (signature[cptr] != transmittedSignature[cptr]) { 257 264 // FIXME: We should try ratcheting. 258 return Exception { NotSupportedError };265 return makeUnexpected(ErrorInformation { Error::Authentication, "Authentication failed"_s, 0 }); 259 266 } 260 267 } … … 265 272 266 273 if (result.hasException()) 267 return result.releaseException();274 return makeUnexpected(ErrorInformation { Error::Other, result.exception().message(), 0 }); 268 275 269 276 return result.releaseReturnValue(); 270 277 } 271 278 272 ExceptionOr<Vector<uint8_t>>RTCRtpSFrameTransformer::encryptFrame(const uint8_t* frameData, size_t frameSize)279 RTCRtpSFrameTransformer::TransformResult RTCRtpSFrameTransformer::encryptFrame(const uint8_t* frameData, size_t frameSize) 273 280 { 274 281 static const unsigned MaxHeaderSize = 17; … … 315 322 ASSERT(!encryptedData.hasException()); 316 323 if (encryptedData.hasException()) 317 return encryptedData.releaseException();324 return makeUnexpected(ErrorInformation { Error::Other, encryptedData.exception().message(), 0 }); 318 325 319 326 std::memcpy(newDataPointer + headerSize, encryptedData.returnValue().data(), frameSize); … … 331 338 } 332 339 333 ExceptionOr<Vector<uint8_t>>RTCRtpSFrameTransformer::transform(const uint8_t* data, size_t size)340 RTCRtpSFrameTransformer::TransformResult RTCRtpSFrameTransformer::transform(const uint8_t* data, size_t size) 334 341 { 335 342 if (!m_hasKey) 336 return Exception { InvalidStateError, "Key is not initialized"_s };343 return makeUnexpected(ErrorInformation { Error::KeyID, "Key is not initialized", 0 }); 337 344 338 345 return m_isEncrypting ? encryptFrame(data, size) : decryptFrame(data, size); -
trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.h
r278253 r280958 49 49 50 50 WEBCORE_EXPORT ExceptionOr<void> setEncryptionKey(const Vector<uint8_t>& rawKey, std::optional<uint64_t>); 51 WEBCORE_EXPORT ExceptionOr<Vector<uint8_t>> transform(const uint8_t*, size_t); 51 52 enum class Error { KeyID, Authentication, Syntax, Other }; 53 struct ErrorInformation { 54 Error error; 55 String message; 56 uint64_t keyId { 0 }; 57 }; 58 using TransformResult = Expected<Vector<uint8_t>, ErrorInformation>; 59 WEBCORE_EXPORT TransformResult transform(const uint8_t*, size_t); 52 60 53 61 const Vector<uint8_t>& authenticationKey() const { return m_authenticationKey; } … … 59 67 void setCounter(uint64_t counter) { m_counter = counter; } 60 68 69 bool hasKey(uint64_t) const; 70 61 71 private: 62 72 WEBCORE_EXPORT explicit RTCRtpSFrameTransformer(CompatibilityMode); 63 73 64 ExceptionOr<Vector<uint8_t>>decryptFrame(const uint8_t*, size_t);65 ExceptionOr<Vector<uint8_t>>encryptFrame(const uint8_t*, size_t);74 TransformResult decryptFrame(const uint8_t*, size_t); 75 TransformResult encryptFrame(const uint8_t*, size_t); 66 76 67 77 enum class ShouldUpdateKeys { No, Yes }; … … 77 87 void updateAuthenticationSize(); 78 88 79 Lock m_keyLock;89 mutable Lock m_keyLock; 80 90 bool m_hasKey { false }; 81 91 Vector<uint8_t> m_authenticationKey; -
trunk/Source/WebCore/Sources.txt
r280758 r280958 172 172 Modules/mediastream/RTCRtpReceiver.cpp 173 173 Modules/mediastream/RTCRtpSFrameTransform.cpp 174 Modules/mediastream/RTCRtpSFrameTransformErrorEvent.cpp 174 175 Modules/mediastream/RTCRtpSFrameTransformer.cpp 175 176 Modules/mediastream/RTCRtpScriptTransform.cpp … … 3327 3328 JSRTCRtpRtxParameters.cpp 3328 3329 JSRTCRtpSFrameTransform.cpp 3330 JSRTCRtpSFrameTransformErrorEvent.cpp 3329 3331 JSRTCRtpScriptTransform.cpp 3330 3332 JSRTCRtpScriptTransformer.cpp -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r280824 r280958 7987 7987 41B459DA1F4CADB90000F6FD /* ReadableStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReadableStream.h; sourceTree = "<group>"; }; 7988 7988 41B459ED1F55EBC70000F6FD /* ReadableStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReadableStream.cpp; sourceTree = "<group>"; }; 7989 41B6AA4F26B995F800AADFA7 /* RTCRtpSFrameTransformErrorEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCRtpSFrameTransformErrorEvent.h; sourceTree = "<group>"; }; 7990 41B6AA5126B995F800AADFA7 /* RTCRtpSFrameTransformErrorEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCRtpSFrameTransformErrorEvent.idl; sourceTree = "<group>"; }; 7991 41B6AA5226B995F900AADFA7 /* RTCRtpSFrameTransformErrorEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTCRtpSFrameTransformErrorEvent.cpp; sourceTree = "<group>"; }; 7989 7992 41B8776023DE1042003638B8 /* RealtimeMediaSourceIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RealtimeMediaSourceIdentifier.h; sourceTree = "<group>"; }; 7990 7993 41B9137623584D0E0025BFA3 /* MockAudioDestinationCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockAudioDestinationCocoa.h; sourceTree = "<group>"; }; … … 17242 17245 4181C642255B4C2600AEB0FF /* RTCRtpSFrameTransformer.h */, 17243 17246 4181C63F255B4C2500AEB0FF /* RTCRtpSFrameTransformerCocoa.cpp */, 17247 41B6AA5226B995F900AADFA7 /* RTCRtpSFrameTransformErrorEvent.cpp */, 17248 41B6AA4F26B995F800AADFA7 /* RTCRtpSFrameTransformErrorEvent.h */, 17249 41B6AA5126B995F800AADFA7 /* RTCRtpSFrameTransformErrorEvent.idl */, 17244 17250 415E1BB62150152A0022DA96 /* RTCRtpSynchronizationSource.h */, 17245 17251 415E1BB7215015300022DA96 /* RTCRtpSynchronizationSource.idl */, -
trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h
r280627 r280958 220 220 macro(Response) \ 221 221 macro(SFrameTransform) \ 222 macro(SFrameTransformErrorEvent) \ 222 223 macro(ScreenLuminance) \ 223 224 macro(ServiceWorker) \ -
trunk/Source/WebCore/dom/EventNames.in
r280467 r280958 65 65 RTCDataChannelEvent conditional=WEB_RTC 66 66 RTCDTMFToneChangeEvent conditional=WEB_RTC 67 RTCRtpSFrameTransformErrorEvent conditional=WEB_RTC 67 68 RTCTrackEvent conditional=WEB_RTC 68 69 RTCTransformEvent conditional=WEB_RTC -
trunk/Source/WebCore/dom/EventTargetFactory.in
r280467 r280958 41 41 RTCDTMFSender conditional=WEB_RTC 42 42 RTCPeerConnection conditional=WEB_RTC 43 RTCRtpSFrameTransform conditional=WEB_RTC 43 44 RTCRtpScriptTransform conditional=WEB_RTC 44 45 ServiceWorker conditional=SERVICE_WORKER -
trunk/Tools/ChangeLog
r280951 r280958 1 2021-08-12 Youenn Fablet <youenn@apple.com> 2 3 Implement SFrameTransform error handling 4 https://bugs.webkit.org/show_bug.cgi?id=228947 5 6 Reviewed by Eric Carlson. 7 8 * TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp: 9 (TestWebKitAPI::TEST): 10 1 11 2021-08-11 Peng Liu <peng.liu6@apple.com> 2 12 -
trunk/Tools/TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp
r275656 r280958 201 201 202 202 auto encryptedResult = encryptor->transform(frame.data(), frame.size()); 203 EXPECT_ FALSE(encryptedResult.hasException());204 205 auto encrypted = encryptedResult.releaseReturnValue();203 EXPECT_TRUE(encryptedResult.has_value()); 204 205 auto encrypted = WTFMove(encryptedResult.value()); 206 206 auto decryptedResult = decryptor->transform(encrypted.data(), encrypted.size()); 207 EXPECT_ FALSE(decryptedResult.hasException());208 209 checkVectorsAreEqual(decryptedResult. returnValue(), frame);207 EXPECT_TRUE(decryptedResult.has_value()); 208 209 checkVectorsAreEqual(decryptedResult.value(), frame); 210 210 } 211 211 … … 221 221 222 222 auto encryptedResult = encryptor->transform(frame.data(), frame.size()); 223 EXPECT_ FALSE(encryptedResult.hasException());224 225 auto encrypted = encryptedResult.releaseReturnValue();223 EXPECT_TRUE(encryptedResult.has_value()); 224 225 auto encrypted = WTFMove(encryptedResult.value()); 226 226 auto decryptedResult = decryptor->transform(encrypted.data(), encrypted.size()); 227 EXPECT_ FALSE(decryptedResult.hasException());228 229 checkVectorsAreEqual(decryptedResult. returnValue(), frame);227 EXPECT_TRUE(decryptedResult.has_value()); 228 229 checkVectorsAreEqual(decryptedResult.value(), frame); 230 230 } 231 231 … … 243 243 244 244 auto encryptedResult = encryptor->transform(frame.data(), frame.size()); 245 EXPECT_ FALSE(encryptedResult.hasException());246 247 auto encrypted = encryptedResult.releaseReturnValue();245 EXPECT_TRUE(encryptedResult.has_value()); 246 247 auto encrypted = WTFMove(encryptedResult.value()); 248 248 auto decryptedResult = decryptor->transform(encrypted.data(), encrypted.size()); 249 EXPECT_ FALSE(decryptedResult.hasException());250 251 checkVectorsAreEqual(decryptedResult. returnValue(), frame);249 EXPECT_TRUE(decryptedResult.has_value()); 250 251 checkVectorsAreEqual(decryptedResult.value(), frame); 252 252 } 253 253 … … 258 258 uint8_t frame1[] = { 135, 89, 51, 166, 248, 129, 157, 111, 190, 134, 220 }; 259 259 auto result = transformer->transform(frame1, sizeof(frame1)); 260 EXPECT_ FALSE(result.hasException());261 262 checkVectorsAreEqual(result. releaseReturnValue(), Vector<uint8_t>::from(260 EXPECT_TRUE(result.has_value()); 261 262 checkVectorsAreEqual(result.value(), Vector<uint8_t>::from( 263 263 15, 264 264 198, … … 300 300 301 301 uint8_t frame1[] = { 8, 164, 189, 18, 61, 117, 132, 43, 117, 169, 42 }; 302 WebCore::ExceptionOr<Vector<uint8_t>> result = Vector<uint8_t>();303 result = transformer->transform(frame1, sizeof(frame1));302 auto result = transformer->transform(frame1, sizeof(frame1)); 303 EXPECT_TRUE(result.has_value()); 304 304 for (size_t cptr = 0; cptr < 256; ++cptr) { 305 305 result = transformer->transform(frame1, sizeof(frame1)); 306 EXPECT_ FALSE(result.hasException());306 EXPECT_TRUE(result.has_value()); 307 307 } 308 308 309 checkVectorsAreEqual(result. releaseReturnValue(), Vector<uint8_t>::from(309 checkVectorsAreEqual(result.value(), Vector<uint8_t>::from( 310 310 31, 311 311 198, … … 350 350 uint8_t frame1[] = { 0, 33, 244, 24, 236, 156, 127, 8, 48, 88, 220 }; 351 351 auto result = transformer->transform(frame1, sizeof(frame1)); 352 EXPECT_ FALSE(result.hasException());353 354 checkVectorsAreEqual(result. releaseReturnValue(), Vector<uint8_t>::from(352 EXPECT_TRUE(result.has_value()); 353 354 checkVectorsAreEqual(result.value(), Vector<uint8_t>::from( 355 355 47, 356 356 198,
Note:
See TracChangeset
for help on using the changeset viewer.