* Copyright (C) 2012 Google 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.
*/
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_DATA_CHANNEL_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_DATA_CHANNEL_H_
#include "base/gtest_prod_util.h"
#include "base/sequence_checker.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binary_type.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_client.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/platform/heap/collection_support/heap_deque.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/prefinalizer.h"
#include "third_party/blink/renderer/platform/heap/self_keep_alive.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/webrtc/api/data_channel_interface.h"
#include "third_party/webrtc/api/peer_connection_interface.h"
namespace blink {
class Blob;
class DOMArrayBuffer;
class DOMArrayBufferView;
class ExceptionState;
class V8RTCDataChannelState;
class V8RTCPriorityType;
class MODULES_EXPORT RTCDataChannel final
: public EventTarget,
public ActiveScriptWrappable<RTCDataChannel>,
public ExecutionContextLifecycleObserver {
DEFINE_WRAPPERTYPEINFO();
USING_PRE_FINALIZER(RTCDataChannel, Dispose);
public:
static void EnsureThreadWrappersForWorkerThread();
RTCDataChannel(ExecutionContext*,
webrtc::scoped_refptr<webrtc::DataChannelInterface> channel);
~RTCDataChannel() override;
String label() const;
bool reliable() const;
bool ordered() const;
std::optional<uint16_t> maxPacketLifeTime() const;
std::optional<uint16_t> maxRetransmits() const;
String protocol() const;
bool negotiated() const;
std::optional<uint16_t> id() const;
V8RTCDataChannelState readyState() const;
unsigned bufferedAmount() const;
unsigned bufferedAmountLowThreshold() const;
void setBufferedAmountLowThreshold(unsigned);
V8BinaryType binaryType() const;
void setBinaryType(const V8BinaryType&);
V8RTCPriorityType priority() const;
void SetStateToOpenWithoutEvent();
void DispatchOpenEvent();
void send(const String&, ExceptionState&);
void send(DOMArrayBuffer*, ExceptionState&);
void send(NotShared<DOMArrayBufferView>, ExceptionState&);
void send(Blob*, ExceptionState&);
void close();
bool IsTransferable();
webrtc::scoped_refptr<webrtc::DataChannelInterface>
TransferUnderlyingChannel();
DEFINE_ATTRIBUTE_EVENT_LISTENER(open, kOpen)
DEFINE_ATTRIBUTE_EVENT_LISTENER(bufferedamountlow, kBufferedamountlow)
DEFINE_ATTRIBUTE_EVENT_LISTENER(error, kError)
DEFINE_ATTRIBUTE_EVENT_LISTENER(close, kClose)
DEFINE_ATTRIBUTE_EVENT_LISTENER(closing, kClosing)
DEFINE_ATTRIBUTE_EVENT_LISTENER(message, kMessage)
const AtomicString& InterfaceName() const override;
ExecutionContext* GetExecutionContext() const override;
void ContextDestroyed() override;
bool HasPendingActivity() const override;
void Trace(Visitor*) const override;
void ProcessSendQueue();
private:
friend class Observer;
class Observer : public ThreadSafeRefCounted<RTCDataChannel::Observer>,
public webrtc::DataChannelObserver {
public:
Observer(scoped_refptr<base::SingleThreadTaskRunner> main_thread,
RTCDataChannel* blink_channel,
webrtc::scoped_refptr<webrtc::DataChannelInterface> channel);
~Observer() override;
const webrtc::scoped_refptr<webrtc::DataChannelInterface>& channel() const;
bool is_registered() const;
void Unregister();
void OnStateChange() override;
void OnBufferedAmountChange(uint64_t sent_data_size) override;
void OnMessage(const webrtc::DataBuffer& buffer) override;
bool IsOkToCallOnTheNetworkThread() override;
private:
void OnStateChangeImpl(webrtc::DataChannelInterface::DataState state);
void OnBufferedAmountChangeImpl(unsigned sent_data_size);
void OnMessageImpl(webrtc::DataBuffer buffer);
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
WeakPersistent<RTCDataChannel> blink_channel_;
const webrtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel_;
};
void RegisterObserver();
void OnStateChange(webrtc::DataChannelInterface::DataState state);
void OnBufferedAmountChange(unsigned previous_amount);
void OnMessage(webrtc::DataBuffer buffer);
void Dispose();
const webrtc::scoped_refptr<webrtc::DataChannelInterface>& channel() const;
bool ValidateSendLength(uint64_t length, ExceptionState& exception_state);
void SendRawData(const char* data, size_t length);
void SendDataBuffer(webrtc::DataBuffer data_buffer);
void CreateFeatureHandleForScheduler();
webrtc::DataChannelInterface::DataState state_ =
webrtc::DataChannelInterface::kConnecting;
V8BinaryType::Enum binary_type_ = V8BinaryType::Enum::kArraybuffer;
FRIEND_TEST_ALL_PREFIXES(RTCDataChannelTest, Open);
FRIEND_TEST_ALL_PREFIXES(RTCDataChannelTest, Close);
FRIEND_TEST_ALL_PREFIXES(RTCDataChannelTest, Message);
FRIEND_TEST_ALL_PREFIXES(RTCDataChannelTest, BufferedAmountLow);
FrameScheduler::SchedulingAffectingFeatureHandle
feature_handle_for_scheduler_;
mutable std::optional<uint16_t> id_;
unsigned buffered_amount_low_threshold_ = 0u;
unsigned buffered_amount_ = 0u;
bool stopped_ = false;
bool closed_from_owner_ = false;
class PendingMessage;
class BlobReader : public GarbageCollected<BlobReader>,
public ExecutionContextLifecycleObserver,
public FileReaderAccumulator {
public:
static BlobReader* Create(ExecutionContext* context,
RTCDataChannel* data_channel,
PendingMessage* message) {
return MakeGarbageCollected<BlobReader>(context, data_channel, message);
}
BlobReader(ExecutionContext* context,
RTCDataChannel* data_channel,
PendingMessage* message);
~BlobReader() override;
void Start(Blob* blob);
bool HasFinishedLoading() const;
void DidFinishLoading(FileReaderData data) override;
void DidFail(FileErrorCode error) override;
void ContextDestroyed() override;
void Trace(Visitor*) const override;
private:
void Dispose();
Member<FileReaderLoader> loader_;
Member<RTCDataChannel> data_channel_;
Member<PendingMessage> message_;
SelfKeepAlive<BlobReader> keep_alive_;
SEQUENCE_CHECKER(sequence_checker_);
};
class PendingMessage final : public GarbageCollected<PendingMessage> {
public:
enum class Type {
kBufferReady,
kBufferPending,
kCloseEvent,
kBlobFailure,
};
void Trace(Visitor* visitor) const;
Type type_;
std::optional<webrtc::DataBuffer> buffer_;
Member<BlobReader> blob_reader_;
};
HeapDeque<Member<PendingMessage>> pending_messages_;
bool was_transferred_ = false;
bool is_transferable_ = true;
const scoped_refptr<Observer> observer_;
SEQUENCE_CHECKER(sequence_checker_);
};
}
#endif