blob: 1872065b83584bf99e3ea320e2786cdb7283597e [file] [log] [blame]
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
* Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
* Copyright (C) 2015 Ericsson AB. All rights reserved.
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Google Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#if ENABLE(WEB_RTC)
#include "ActiveDOMObject.h"
#include "EventTarget.h"
#include "MediaEndpointConfiguration.h"
#include "MediaStream.h"
#include "RTCConfiguration.h"
#include "RTCDataChannel.h"
#include "RTCIceConnectionState.h"
#include "RTCIceGatheringState.h"
#include "RTCPeerConnectionState.h"
#include "RTCRtpTransceiver.h"
#include "RTCSignalingState.h"
#include <JavaScriptCore/Uint8Array.h>
#include <wtf/LoggerHelper.h>
namespace WebCore {
class MediaStream;
class MediaStreamTrack;
class PeerConnectionBackend;
class RTCController;
class RTCIceCandidate;
class RTCPeerConnectionErrorCallback;
class RTCSessionDescription;
class RTCStatsCallback;
struct RTCAnswerOptions;
struct RTCOfferOptions;
struct RTCRtpParameters;
struct RTCRtpTransceiverInit {
RTCRtpTransceiverDirection direction { RTCRtpTransceiverDirection::Sendrecv };
Vector<RefPtr<MediaStream>> streams;
};
class RTCPeerConnection final
: public RefCounted<RTCPeerConnection>
, public EventTargetWithInlineData
, public ActiveDOMObject
#if !RELEASE_LOG_DISABLED
, private LoggerHelper
#endif
{
WTF_MAKE_ISO_ALLOCATED(RTCPeerConnection);
public:
static Ref<RTCPeerConnection> create(ScriptExecutionContext&);
virtual ~RTCPeerConnection();
using DataChannelInit = RTCDataChannelInit;
ExceptionOr<void> initializeWith(Document&, RTCConfiguration&&);
struct CertificateParameters {
String name;
String hash;
String namedCurve;
Optional<uint32_t> modulusLength;
RefPtr<Uint8Array> publicExponent;
Optional<double> expires;
};
using AlgorithmIdentifier = Variant<JSC::Strong<JSC::JSObject>, String>;
static void generateCertificate(JSC::ExecState&, AlgorithmIdentifier&&, DOMPromiseDeferred<IDLInterface<RTCCertificate>>&&);
// 4.3.2 RTCPeerConnection Interface
void queuedCreateOffer(RTCOfferOptions&&, PeerConnection::SessionDescriptionPromise&&);
void queuedCreateAnswer(RTCAnswerOptions&&, PeerConnection::SessionDescriptionPromise&&);
void queuedSetLocalDescription(RTCSessionDescription&, DOMPromiseDeferred<void>&&);
RefPtr<RTCSessionDescription> localDescription() const;
RefPtr<RTCSessionDescription> currentLocalDescription() const;
RefPtr<RTCSessionDescription> pendingLocalDescription() const;
void queuedSetRemoteDescription(RTCSessionDescription&, DOMPromiseDeferred<void>&&);
RefPtr<RTCSessionDescription> remoteDescription() const;
RefPtr<RTCSessionDescription> currentRemoteDescription() const;
RefPtr<RTCSessionDescription> pendingRemoteDescription() const;
void queuedAddIceCandidate(RTCIceCandidate*, DOMPromiseDeferred<void>&&);
RTCSignalingState signalingState() const { return m_signalingState; }
RTCIceGatheringState iceGatheringState() const { return m_iceGatheringState; }
RTCIceConnectionState iceConnectionState() const { return m_iceConnectionState; }
RTCPeerConnectionState connectionState() const { return m_connectionState; }
const RTCConfiguration& getConfiguration() const { return m_configuration; }
ExceptionOr<void> setConfiguration(RTCConfiguration&&);
void close();
bool isClosed() const { return m_connectionState == RTCPeerConnectionState::Closed; }
bool isStopped() const { return m_isStopped; }
void addInternalTransceiver(Ref<RTCRtpTransceiver>&& transceiver) { m_transceiverSet->append(WTFMove(transceiver)); }
// 5.1 RTCPeerConnection extensions
Vector<std::reference_wrapper<RTCRtpSender>> getSenders() const;
Vector<std::reference_wrapper<RTCRtpReceiver>> getReceivers() const;
const Vector<RefPtr<RTCRtpTransceiver>>& getTransceivers() const;
const Vector<RefPtr<RTCRtpTransceiver>>& currentTransceivers() const { return m_transceiverSet->list(); }
ExceptionOr<Ref<RTCRtpSender>> addTrack(Ref<MediaStreamTrack>&&, const Vector<std::reference_wrapper<MediaStream>>&);
ExceptionOr<void> removeTrack(RTCRtpSender&);
using AddTransceiverTrackOrKind = Variant<RefPtr<MediaStreamTrack>, String>;
ExceptionOr<Ref<RTCRtpTransceiver>> addTransceiver(AddTransceiverTrackOrKind&&, const RTCRtpTransceiverInit&);
// 6.1 Peer-to-peer data API
ExceptionOr<Ref<RTCDataChannel>> createDataChannel(String&&, RTCDataChannelInit&&);
// 8.2 Statistics API
void getStats(MediaStreamTrack*, Ref<DeferredPromise>&&);
// EventTarget
EventTargetInterface eventTargetInterface() const final { return RTCPeerConnectionEventTargetInterfaceType; }
ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
using RefCounted::ref;
using RefCounted::deref;
// Used for testing with a mock
WEBCORE_EXPORT void emulatePlatformEvent(const String& action);
// API used by PeerConnectionBackend and relatives
void addTransceiver(Ref<RTCRtpTransceiver>&&);
void setSignalingState(RTCSignalingState);
void updateIceGatheringState(RTCIceGatheringState);
void updateIceConnectionState(RTCIceConnectionState);
void scheduleNegotiationNeededEvent();
void dispatchEventWhenFeasible(Ref<Event>&&);
void disableICECandidateFiltering() { m_backend->disableICECandidateFiltering(); }
void enableICECandidateFiltering() { m_backend->enableICECandidateFiltering(); }
void clearController() { m_controller = nullptr; }
// ActiveDOMObject.
bool hasPendingActivity() const final;
Document* document();
void doTask(Function<void()>&&);
#if !RELEASE_LOG_DISABLED
const Logger& logger() const final { return m_logger.get(); }
const void* logIdentifier() const final { return m_logIdentifier; }
const char* logClassName() const final { return "RTCPeerConnection"; }
WTFLogChannel& logChannel() const final;
#endif
private:
template<typename PromiseType> void addPendingPromise(PromiseType& promise)
{
promise.whenSettled([pendingActivity = makePendingActivity(*this)] { });
}
RTCPeerConnection(Document&);
ExceptionOr<void> initializeConfiguration(RTCConfiguration&&);
Ref<RTCRtpTransceiver> completeAddTransceiver(Ref<RTCRtpSender>&&, const RTCRtpTransceiverInit&, const String& trackId, const String& trackKind);
void registerToController(RTCController&);
void unregisterFromController();
friend class Internals;
void applyRotationForOutgoingVideoSources() { m_backend->applyRotationForOutgoingVideoSources(); }
// EventTarget implementation.
void refEventTarget() final { ref(); }
void derefEventTarget() final { deref(); }
void dispatchEvent(Event&) final;
// ActiveDOMObject
WEBCORE_EXPORT void stop() final;
const char* activeDOMObjectName() const final;
bool shouldPreventEnteringBackForwardCache_DEPRECATED() const final;
void suspend(ReasonForSuspension) final;
void resume() final;
void updateConnectionState();
bool doClose();
void doStop();
ExceptionOr<Vector<MediaEndpointConfiguration::CertificatePEM>> certificatesFromConfiguration(const RTCConfiguration&);
bool m_isStopped { false };
RTCSignalingState m_signalingState { RTCSignalingState::Stable };
RTCIceGatheringState m_iceGatheringState { RTCIceGatheringState::New };
RTCIceConnectionState m_iceConnectionState { RTCIceConnectionState::New };
RTCPeerConnectionState m_connectionState { RTCPeerConnectionState::New };
#if !RELEASE_LOG_DISABLED
Ref<const Logger> m_logger;
const void* m_logIdentifier;
#endif
std::unique_ptr<RtpTransceiverSet> m_transceiverSet { std::unique_ptr<RtpTransceiverSet>(new RtpTransceiverSet()) };
std::unique_ptr<PeerConnectionBackend> m_backend;
RTCConfiguration m_configuration;
RTCController* m_controller { nullptr };
Vector<RefPtr<RTCCertificate>> m_certificates;
bool m_shouldDelayTasks { false };
Vector<Function<void()>> m_pendingTasks;
};
} // namespace WebCore
#endif // ENABLE(WEB_RTC)