⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 280958 in webkit


Ignore:
Timestamp:
Aug 12, 2021, 2:37:05 AM (5 years ago)
Author:
youenn@apple.com
Message:

Implement SFrameTransform error handling
https://bugs.webkit.org/show_bug.cgi?id=228947

Reviewed by Eric Carlson.

Source/WebCore:

Add support for RTCRtpSFrameTransformErrorEvent.
When RTCRtpSFrameTransformer encounters an issue, dispatch a task to RTCRtpSFrameTransform context and fire a corresponding event.
This follows https://w3c.github.io/webrtc-encoded-transform/#sframe-transform-algorithm, except that:

  • we are not yet exposing some fields in RTCRtpSFrameTransformErrorEvent.
  • we are using errorType instead of type which should be fixed in the spec.

Test: imported/w3c/web-platform-tests/webrtc-encoded-transform/sframe-transform-error.html

  • CMakeLists.txt:
  • DerivedSources-input.xcfilelist:
  • DerivedSources-output.xcfilelist:
  • DerivedSources.make:
  • Modules/mediastream/RTCRtpSFrameTransform.cpp:

(WebCore::RTCRtpSFrameTransform::RTCRtpSFrameTransform):
(WebCore::errorTypeFromInformation):
(WebCore::processFrame):
(WebCore::RTCRtpSFrameTransform::hasKey const):
(WebCore::RTCRtpSFrameTransform::initializeTransformer):
(WebCore::transformFrame):
(WebCore::RTCRtpSFrameTransform::createStreams):
(WebCore::RTCRtpSFrameTransform::writable):
(WebCore::RTCRtpSFrameTransform::virtualHasPendingActivity const):

  • Modules/mediastream/RTCRtpSFrameTransform.h:
  • Modules/mediastream/RTCRtpSFrameTransform.idl:
  • Modules/mediastream/RTCRtpSFrameTransformErrorEvent.cpp: Added.

(WebCore::RTCRtpSFrameTransformErrorEvent::create):
(WebCore::RTCRtpSFrameTransformErrorEvent::RTCRtpSFrameTransformErrorEvent):
(WebCore::RTCRtpSFrameTransformErrorEvent::eventInterface const):

  • Modules/mediastream/RTCRtpSFrameTransformErrorEvent.h: Added.
  • Modules/mediastream/RTCRtpSFrameTransformErrorEvent.idl: Added.
  • Modules/mediastream/RTCRtpSFrameTransformer.cpp:

(WebCore::RTCRtpSFrameTransformer::hasKey const):
(WebCore::RTCRtpSFrameTransformer::decryptFrame):
(WebCore::RTCRtpSFrameTransformer::encryptFrame):
(WebCore::RTCRtpSFrameTransformer::transform):

  • Modules/mediastream/RTCRtpSFrameTransformer.h:
  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • bindings/js/WebCoreBuiltinNames.h:
  • dom/EventNames.in:
  • dom/EventTargetFactory.in:

Tools:

  • TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp:

(TestWebKitAPI::TEST):

LayoutTests:

  • http/wpt/webrtc/sframe-transform-error-worker.js: Added.

(onrtctransform.async event):

  • http/wpt/webrtc/sframe-transform-error.html: Added.
  • http/wpt/webrtc/sframe-transform-error-expected: Added.
Location:
trunk
Files:
4 added
18 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r280954 r280958  
     12021-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
    1132021-08-11  Lauro Moura  <lmoura@igalia.com>
    214
  • trunk/Source/WebCore/CMakeLists.txt

    r280778 r280958  
    413413    Modules/mediastream/RTCRtpRtxParameters.idl
    414414    Modules/mediastream/RTCRtpSFrameTransform.idl
     415    Modules/mediastream/RTCRtpSFrameTransformErrorEvent.idl
    415416    Modules/mediastream/RTCRtpScriptTransform.idl
    416417    Modules/mediastream/RTCRtpScriptTransformProvider.idl
  • trunk/Source/WebCore/ChangeLog

    r280956 r280958  
     12021-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
    1502021-08-11  Alex Christensen  <achristensen@webkit.org>
    251
  • trunk/Source/WebCore/DerivedSources-input.xcfilelist

    r280467 r280958  
    257257$(PROJECT_DIR)/Modules/mediastream/RTCRtpRtxParameters.idl
    258258$(PROJECT_DIR)/Modules/mediastream/RTCRtpSFrameTransform.idl
     259$(PROJECT_DIR)/Modules/mediastream/RTCRtpSFrameTransformErrorEvent.idl
    259260$(PROJECT_DIR)/Modules/mediastream/RTCRtpScriptTransform.idl
    260261$(PROJECT_DIR)/Modules/mediastream/RTCRtpScriptTransformProvider.idl
  • trunk/Source/WebCore/DerivedSources-output.xcfilelist

    r280467 r280958  
    16981698$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSFrameTransform.cpp
    16991699$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSFrameTransform.h
     1700$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSFrameTransformErrorEvent.cpp
     1701$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSFrameTransformErrorEvent.h
    17001702$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpScriptTransform.cpp
    17011703$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpScriptTransform.h
  • trunk/Source/WebCore/DerivedSources.make

    r280467 r280958  
    284284    $(WebCore)/Modules/mediastream/RTCRtpSender+Transform.idl \
    285285    $(WebCore)/Modules/mediastream/RTCRtpSFrameTransform.idl \
     286    $(WebCore)/Modules/mediastream/RTCRtpSFrameTransformErrorEvent.idl \
    286287    $(WebCore)/Modules/mediastream/RTCRtpScriptTransform.idl \
    287288    $(WebCore)/Modules/mediastream/RTCRtpScriptTransformProvider.idl \
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp

    r278523 r280958  
    3636#include "RTCEncodedAudioFrame.h"
    3737#include "RTCEncodedVideoFrame.h"
     38#include "RTCRtpSFrameTransformErrorEvent.h"
    3839#include "RTCRtpSFrameTransformer.h"
    3940#include "RTCRtpTransformBackend.h"
     
    4445#include "WritableStream.h"
    4546#include "WritableStreamSink.h"
     47#include <wtf/IsoMallocInlines.h>
    4648
    4749namespace WebCore {
    4850
     51WTF_MAKE_ISO_ALLOCATED_IMPL(RTCRtpSFrameTransform);
     52
    4953RTCRtpSFrameTransform::RTCRtpSFrameTransform(ScriptExecutionContext& context, Options options)
    50     : ContextDestructionObserver(&context)
     54    : ActiveDOMObject(&context)
    5155    , m_transformer(RTCRtpSFrameTransformer::create(options.compatibilityMode))
    5256{
     57    suspendIfNeeded();
     58
    5359    m_transformer->setIsEncrypting(options.role == Role::Encrypt);
    5460    m_transformer->setAuthenticationSize(options.authenticationSize);
     
    96102}
    97103
     104static 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
     118static 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
     138bool RTCRtpSFrameTransform::hasKey(uint64_t keyID) const
     139{
     140    return m_transformer->hasKey(keyID);
     141}
     142
    98143void RTCRtpSFrameTransform::initializeTransformer(RTCRtpTransformBackend& backend, Side side)
    99144{
    100145    ASSERT(!isAttached());
     146
     147    auto* context = scriptExecutionContext();
     148    if (!context)
     149        return;
    101150
    102151    m_isAttached = true;
     
    109158    m_transformer->setMediaType(backend.mediaType());
    110159
    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) {
    112161        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)
    117163            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() });
    121170
    122171        backend->processTransformedFrame(frame.get());
     
    139188}
    140189
     190static 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
    141197template<typename Frame>
    142 void transformFrame(Frame& frame, JSDOMGlobalObject& globalObject, RTCRtpSFrameTransformer& transformer, SimpleReadableStreamSource& source)
     198void transformFrame(Frame& frame, JSDOMGlobalObject& globalObject, RTCRtpSFrameTransformer& transformer, SimpleReadableStreamSource& source, ScriptExecutionContextIdentifier identifier, const WeakPtr<RTCRtpSFrameTransform>& weakTransform)
    143199{
    144200    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);
    148202    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() };
    153205    frame.rtcFrame().setData(transformedChunk);
    154206    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()));
    164207}
    165208
     
    171214        return;
    172215
    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> {
    174217        if (!context.globalObject())
    175218            return Exception { InvalidStateError };
     
    183226        // We do not want to throw any exception in the transform to make sure we do not error the transform.
    184227        WTF::switchOn(frame, [&](RefPtr<RTCEncodedAudioFrame>& value) {
    185             transformFrame(*value, globalObject, transformer.get(), *readableStreamSource);
     228            transformFrame(*value, globalObject, transformer.get(), *readableStreamSource, context.contextIdentifier(), weakThis);
    186229        }, [&](RefPtr<RTCEncodedVideoFrame>& value) {
    187             transformFrame(*value, globalObject, transformer.get(), *readableStreamSource);
     230            transformFrame(*value, globalObject, transformer.get(), *readableStreamSource, context.contextIdentifier(), weakThis);
    188231        }, [&](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);
    190233        }, [&](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);
    192235        });
    193236        return { };
     
    233276        createStreams(*globalObject);
    234277
     278    m_hasWritable = true;
    235279    return m_writable.copyRef();
    236280}
    237281
     282bool RTCRtpSFrameTransform::virtualHasPendingActivity() const
     283{
     284    return (m_isAttached || m_hasWritable) && hasEventListeners();
     285}
     286
    238287} // namespace WebCore
    239288
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.h

    r278253 r280958  
    2828#if ENABLE(WEB_RTC)
    2929
    30 #include "ContextDestructionObserver.h"
     30#include "ActiveDOMObject.h"
     31#include "EventTarget.h"
    3132#include "JSDOMPromiseDeferred.h"
    3233#include "RTCRtpSFrameTransformer.h"
     34#include <wtf/WeakPtr.h>
    3335
    3436namespace JSC {
     
    4446class WritableStream;
    4547
    46 class RTCRtpSFrameTransform : public RefCounted<RTCRtpSFrameTransform>, private ContextDestructionObserver {
     48class RTCRtpSFrameTransform : public RefCounted<RTCRtpSFrameTransform>, public ActiveDOMObject, public EventTargetWithInlineData {
     49    WTF_MAKE_ISO_ALLOCATED(RTCRtpSFrameTransform);
    4750public:
    4851    enum class Role { Encrypt, Decrypt };
     
    7174    ExceptionOr<RefPtr<WritableStream>> writable();
    7275
     76    bool hasKey(uint64_t) const;
     77
     78    using RefCounted<RTCRtpSFrameTransform>::ref;
     79    using RefCounted<RTCRtpSFrameTransform>::deref;
     80
    7381private:
    7482    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(); }
    7593
    7694    enum class Side { Sender, Receiver };
     
    7997
    8098    bool m_isAttached { false };
     99    bool m_hasWritable { false };
    81100    Ref<RTCRtpSFrameTransformer> m_transformer;
    82101    RefPtr<ReadableStream> m_readable;
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.idl

    r274832 r280958  
    4242
    4343[
     44    ActiveDOMObject,
    4445    Conditional=WEB_RTC,
    4546    EnabledBySetting=WebRTCInsertableStreams,
     
    4849    InterfaceName=SFrameTransform,
    4950    JSGenerateToNativeObject,
    50 ] interface RTCRtpSFrameTransform {
     51] interface RTCRtpSFrameTransform : EventTarget {
    5152    [CallWith=ScriptExecutionContext] constructor(optional RTCRtpSFrameTransformOptions options);
    5253
     
    5859    readonly attribute ReadableStream readable;
    5960    readonly attribute WritableStream writable;
     61
     62    attribute EventHandler onerror;
    6063};
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformErrorEvent.h

    r280957 r280958  
    11/*
    2  * Copyright (C) 2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 enum RTCRtpSFrameTransformRole {
    27     "encrypt",
    28     "decrypt"
     26#pragma once
     27
     28#if ENABLE(WEB_RTC)
     29
     30#include "Event.h"
     31
     32namespace WebCore {
     33
     34class RTCRtpSFrameTransformErrorEvent final : public Event {
     35    WTF_MAKE_ISO_ALLOCATED(RTCRtpSFrameTransformErrorEvent);
     36public:
     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
     52private:
     53    RTCRtpSFrameTransformErrorEvent(const AtomString& type, CanBubble, IsCancelable, Type);
     54
     55    Type m_errorType;
    2956};
    3057
    31 enum RTCRtpSFrameTransformCompatibilityMode {
    32     "none",
    33     "H264",
    34     "VP8"
    35 };
     58} // namespace WebCore
    3659
    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  
    11/*
    2  * Copyright (C) 2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 enum RTCRtpSFrameTransformRole {
    27     "encrypt",
    28     "decrypt"
     26enum RTCRtpSFrameTransformErrorEventType {
     27    "authentication",
     28    "keyID",
     29    "other",
     30    "syntax"
    2931};
    3032
    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";
     33dictionary RTCRtpSFrameTransformErrorEventInit : EventInit {
     34    required RTCRtpSFrameTransformErrorEventType errorType;
    4135};
    4236
     
    4438    Conditional=WEB_RTC,
    4539    EnabledBySetting=WebRTCInsertableStreams,
    46     ExportMacro=WEBCORE_EXPORT,
    4740    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);
    5244
    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;
    6049};
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.cpp

    r278253 r280958  
    3030
    3131#include "SFrameUtils.h"
     32#include <wtf/Algorithms.h>
    3233
    3334namespace WebCore {
     
    161162}
    162163
     164bool 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
    163170ExceptionOr<void> RTCRtpSFrameTransformer::updateEncryptionKey(const Vector<uint8_t>& rawKey, std::optional<uint64_t> keyId, ShouldUpdateKeys shouldUpdateKeys)
    164171{
     
    200207}
    201208
    202 ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::decryptFrame(const uint8_t* frameData, size_t frameSize)
     209RTCRtpSFrameTransformer::TransformResult RTCRtpSFrameTransformer::decryptFrame(const uint8_t* frameData, size_t frameSize)
    203210{
    204211    Vector<uint8_t> buffer;
     
    230237
    231238    if (!header)
    232         return Exception { NotSupportedError };
     239        return makeUnexpected(ErrorInformation {Error::Syntax, "Invalid header"_s, 0 });
    233240
    234241    if (header->counter <= m_counter && m_counter)
    235         return Exception { InvalidStateError };
     242        return makeUnexpected(ErrorInformation {Error::Syntax, "Invalid counter"_s, 0 });
    236243    m_counter = header->counter;
    237244
     
    239246        auto position = m_keys.findMatching([keyId = header->keyId](auto& item) { return item.keyId == keyId; });
    240247        if (position == notFound)
    241             return Exception { DataError, "Key ID is unknown" };
     248            return makeUnexpected(ErrorInformation { Error::KeyID,  "Key ID is unknown"_s, header->keyId });
    242249        auto result = updateEncryptionKey(m_keys[position].keyData, header->keyId, ShouldUpdateKeys::No);
    243250        if (result.hasException())
    244             return result.releaseException();
     251            return makeUnexpected(ErrorInformation {Error::Other, result.exception().message(), 0 });
    245252    }
    246253
    247254    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 });
    249256
    250257    auto iv = computeIV(m_counter, m_saltKey);
     
    256263        if (signature[cptr] != transmittedSignature[cptr]) {
    257264            // FIXME: We should try ratcheting.
    258             return Exception { NotSupportedError };
     265            return makeUnexpected(ErrorInformation { Error::Authentication, "Authentication failed"_s, 0 });
    259266        }
    260267    }
     
    265272
    266273    if (result.hasException())
    267         return result.releaseException();
     274        return makeUnexpected(ErrorInformation { Error::Other, result.exception().message(), 0 });
    268275
    269276    return result.releaseReturnValue();
    270277}
    271278
    272 ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::encryptFrame(const uint8_t* frameData, size_t frameSize)
     279RTCRtpSFrameTransformer::TransformResult RTCRtpSFrameTransformer::encryptFrame(const uint8_t* frameData, size_t frameSize)
    273280{
    274281    static const unsigned MaxHeaderSize = 17;
     
    315322    ASSERT(!encryptedData.hasException());
    316323    if (encryptedData.hasException())
    317         return encryptedData.releaseException();
     324        return makeUnexpected(ErrorInformation { Error::Other, encryptedData.exception().message(), 0 });
    318325
    319326    std::memcpy(newDataPointer + headerSize, encryptedData.returnValue().data(), frameSize);
     
    331338}
    332339
    333 ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::transform(const uint8_t* data, size_t size)
     340RTCRtpSFrameTransformer::TransformResult RTCRtpSFrameTransformer::transform(const uint8_t* data, size_t size)
    334341{
    335342    if (!m_hasKey)
    336         return Exception { InvalidStateError, "Key is not initialized"_s };
     343        return makeUnexpected(ErrorInformation { Error::KeyID,  "Key is not initialized", 0 });
    337344
    338345    return m_isEncrypting ? encryptFrame(data, size) : decryptFrame(data, size);
  • trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.h

    r278253 r280958  
    4949
    5050    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);
    5260
    5361    const Vector<uint8_t>& authenticationKey() const { return m_authenticationKey; }
     
    5967    void setCounter(uint64_t counter) { m_counter = counter; }
    6068
     69    bool hasKey(uint64_t) const;
     70
    6171private:
    6272    WEBCORE_EXPORT explicit RTCRtpSFrameTransformer(CompatibilityMode);
    6373
    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);
    6676
    6777    enum class ShouldUpdateKeys { No, Yes };
     
    7787    void updateAuthenticationSize();
    7888
    79     Lock m_keyLock;
     89    mutable Lock m_keyLock;
    8090    bool m_hasKey { false };
    8191    Vector<uint8_t> m_authenticationKey;
  • trunk/Source/WebCore/Sources.txt

    r280758 r280958  
    172172Modules/mediastream/RTCRtpReceiver.cpp
    173173Modules/mediastream/RTCRtpSFrameTransform.cpp
     174Modules/mediastream/RTCRtpSFrameTransformErrorEvent.cpp
    174175Modules/mediastream/RTCRtpSFrameTransformer.cpp
    175176Modules/mediastream/RTCRtpScriptTransform.cpp
     
    33273328JSRTCRtpRtxParameters.cpp
    33283329JSRTCRtpSFrameTransform.cpp
     3330JSRTCRtpSFrameTransformErrorEvent.cpp
    33293331JSRTCRtpScriptTransform.cpp
    33303332JSRTCRtpScriptTransformer.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r280824 r280958  
    79877987                41B459DA1F4CADB90000F6FD /* ReadableStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReadableStream.h; sourceTree = "<group>"; };
    79887988                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>"; };
    79897992                41B8776023DE1042003638B8 /* RealtimeMediaSourceIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RealtimeMediaSourceIdentifier.h; sourceTree = "<group>"; };
    79907993                41B9137623584D0E0025BFA3 /* MockAudioDestinationCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockAudioDestinationCocoa.h; sourceTree = "<group>"; };
     
    1724217245                                4181C642255B4C2600AEB0FF /* RTCRtpSFrameTransformer.h */,
    1724317246                                4181C63F255B4C2500AEB0FF /* RTCRtpSFrameTransformerCocoa.cpp */,
     17247                                41B6AA5226B995F900AADFA7 /* RTCRtpSFrameTransformErrorEvent.cpp */,
     17248                                41B6AA4F26B995F800AADFA7 /* RTCRtpSFrameTransformErrorEvent.h */,
     17249                                41B6AA5126B995F800AADFA7 /* RTCRtpSFrameTransformErrorEvent.idl */,
    1724417250                                415E1BB62150152A0022DA96 /* RTCRtpSynchronizationSource.h */,
    1724517251                                415E1BB7215015300022DA96 /* RTCRtpSynchronizationSource.idl */,
  • trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h

    r280627 r280958  
    220220    macro(Response) \
    221221    macro(SFrameTransform) \
     222    macro(SFrameTransformErrorEvent) \
    222223    macro(ScreenLuminance) \
    223224    macro(ServiceWorker) \
  • trunk/Source/WebCore/dom/EventNames.in

    r280467 r280958  
    6565RTCDataChannelEvent conditional=WEB_RTC
    6666RTCDTMFToneChangeEvent conditional=WEB_RTC
     67RTCRtpSFrameTransformErrorEvent conditional=WEB_RTC
    6768RTCTrackEvent conditional=WEB_RTC
    6869RTCTransformEvent conditional=WEB_RTC
  • trunk/Source/WebCore/dom/EventTargetFactory.in

    r280467 r280958  
    4141RTCDTMFSender conditional=WEB_RTC
    4242RTCPeerConnection conditional=WEB_RTC
     43RTCRtpSFrameTransform conditional=WEB_RTC
    4344RTCRtpScriptTransform conditional=WEB_RTC
    4445ServiceWorker conditional=SERVICE_WORKER
  • trunk/Tools/ChangeLog

    r280951 r280958  
     12021-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
    1112021-08-11  Peng Liu  <peng.liu6@apple.com>
    212
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp

    r275656 r280958  
    201201
    202202    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());
    206206    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);
    210210}
    211211
     
    221221
    222222    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());
    226226    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);
    230230}
    231231
     
    243243
    244244    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());
    248248    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);
    252252}
    253253
     
    258258    uint8_t frame1[] = { 135, 89, 51, 166, 248, 129, 157, 111, 190, 134, 220 };
    259259    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(
    263263        15,
    264264        198,
     
    300300
    301301    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());
    304304    for (size_t cptr = 0; cptr < 256; ++cptr) {
    305305        result = transformer->transform(frame1, sizeof(frame1));
    306         EXPECT_FALSE(result.hasException());
     306        EXPECT_TRUE(result.has_value());
    307307    }
    308308
    309     checkVectorsAreEqual(result.releaseReturnValue(), Vector<uint8_t>::from(
     309    checkVectorsAreEqual(result.value(), Vector<uint8_t>::from(
    310310        31,
    311311        198,
     
    350350    uint8_t frame1[] = { 0, 33, 244, 24, 236, 156, 127, 8, 48, 88, 220 };
    351351    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(
    355355        47,
    356356        198,
Note: See TracChangeset for help on using the changeset viewer.