| Index: components/devtools_bridge/session_dependency_factory.cc
|
| diff --git a/components/devtools_bridge/session_dependency_factory.cc b/components/devtools_bridge/session_dependency_factory.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ec8233020395b2b4383d6346875a92c0ea9101af
|
| --- /dev/null
|
| +++ b/components/devtools_bridge/session_dependency_factory.cc
|
| @@ -0,0 +1,429 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "components/devtools_bridge/session_dependency_factory.h"
|
| +
|
| +#include "components/devtools_bridge/abstract_data_channel.h"
|
| +#include "components/devtools_bridge/abstract_peer_connection.h"
|
| +#include "components/devtools_bridge/rtc_configuration.h"
|
| +#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
|
| +#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
|
| +#include "third_party/webrtc/base/bind.h"
|
| +#include "third_party/webrtc/base/ssladapter.h"
|
| +#include "third_party/webrtc/base/thread.h"
|
| +
|
| +namespace devtools_bridge {
|
| +
|
| +class RTCConfiguration::Impl
|
| + : public RTCConfiguration,
|
| + public webrtc::PeerConnectionInterface::RTCConfiguration {
|
| + public:
|
| +
|
| + virtual void AddIceServer(
|
| + const std::string& uri,
|
| + const std::string& username,
|
| + const std::string& credential) override {
|
| + webrtc::PeerConnectionInterface::IceServer server;
|
| + server.uri = uri;
|
| + server.username = username;
|
| + server.password = credential;
|
| + servers.push_back(server);
|
| + }
|
| +
|
| + const Impl& impl() const override {
|
| + return *this;
|
| + }
|
| +
|
| + private:
|
| + webrtc::PeerConnectionInterface::RTCConfiguration base_;
|
| +};
|
| +
|
| +namespace {
|
| +
|
| +template <typename T>
|
| +void CheckedRelease(rtc::scoped_refptr<T>* ptr) {
|
| + CHECK_EQ(0, ptr->release()->Release());
|
| +}
|
| +
|
| +class MediaConstraints
|
| + : public webrtc::MediaConstraintsInterface {
|
| + public:
|
| + virtual ~MediaConstraints() {}
|
| +
|
| + virtual const Constraints& GetMandatory() const override {
|
| + return mandatory_;
|
| + }
|
| +
|
| + virtual const Constraints& GetOptional() const override {
|
| + return optional_;
|
| + }
|
| +
|
| + void AddMandatory(const std::string& key, const std::string& value) {
|
| + mandatory_.push_back(Constraint(key, value));
|
| + }
|
| +
|
| + private:
|
| + Constraints mandatory_;
|
| + Constraints optional_;
|
| +};
|
| +
|
| +class DataChannelImpl : public AbstractDataChannel {
|
| + public:
|
| + explicit DataChannelImpl(
|
| + rtc::scoped_refptr<webrtc::DataChannelInterface> impl) : impl_(impl) {
|
| + }
|
| +
|
| + // TODO(serya): Implement.
|
| +
|
| + private:
|
| + const rtc::scoped_refptr<webrtc::DataChannelInterface> impl_;
|
| +};
|
| +
|
| +class PeerConnectionObserverImpl
|
| + : public webrtc::PeerConnectionObserver {
|
| + public:
|
| + PeerConnectionObserverImpl(AbstractPeerConnection::Delegate* delegate)
|
| + : delegate_(delegate),
|
| + connected_(false) {
|
| + }
|
| +
|
| + virtual void OnAddStream(webrtc::MediaStreamInterface* stream) override {}
|
| +
|
| + virtual void OnRemoveStream(webrtc::MediaStreamInterface* stream) override {}
|
| +
|
| + virtual void OnDataChannel(webrtc::DataChannelInterface* data_channel)
|
| + override {}
|
| +
|
| + virtual void OnRenegotiationNeeded() override {}
|
| +
|
| + virtual void OnSignalingChange(
|
| + webrtc::PeerConnectionInterface::SignalingState new_state) override {
|
| + }
|
| +
|
| + virtual void OnIceConnectionChange(
|
| + webrtc::PeerConnectionInterface::IceConnectionState new_state) override {
|
| + bool connected =
|
| + new_state == webrtc::PeerConnectionInterface::kIceConnectionConnected ||
|
| + new_state == webrtc::PeerConnectionInterface::kIceConnectionCompleted;
|
| +
|
| + if (connected != connected_) {
|
| + connected_ = connected;
|
| + delegate_->OnIceConnectionChange(connected_);
|
| + }
|
| + }
|
| +
|
| + virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate)
|
| + override {
|
| + std::string sdp;
|
| + candidate->ToString(&sdp);
|
| +
|
| + delegate_->OnIceCandidate(
|
| + candidate->sdp_mid(), candidate->sdp_mline_index(), sdp);
|
| + }
|
| +
|
| + private:
|
| + AbstractPeerConnection::Delegate* const delegate_;
|
| + bool connected_;
|
| +};
|
| +
|
| +/**
|
| + * Helper object which may outlive PeerConnectionImpl. Provides access
|
| + * to the connection and the delegate to operaion callback objects
|
| + * in a safe way. Always accessible on the signaling thread.
|
| + */
|
| +class PeerConnectionHolder : public rtc::RefCountInterface {
|
| + public:
|
| + PeerConnectionHolder(
|
| + rtc::Thread* signaling_thread,
|
| + webrtc::PeerConnectionInterface* connection,
|
| + AbstractPeerConnection::Delegate* delegate)
|
| + : signaling_thread_(signaling_thread),
|
| + connection_(connection),
|
| + delegate_(delegate),
|
| + disposed_(false) {
|
| + }
|
| +
|
| + virtual ~PeerConnectionHolder() {
|
| + DCHECK(disposed_);
|
| + }
|
| +
|
| + void Dispose() {
|
| + DCHECK(!IsDisposed());
|
| + disposed_ = true;
|
| + }
|
| +
|
| + webrtc::PeerConnectionInterface* connection() {
|
| + DCHECK(!IsDisposed());
|
| + return connection_;
|
| + }
|
| +
|
| + AbstractPeerConnection::Delegate* delegate() {
|
| + DCHECK(!IsDisposed());
|
| + return delegate_;
|
| + }
|
| +
|
| + bool IsDisposed() {
|
| + DCHECK(signaling_thread_->IsCurrent());
|
| + return disposed_;
|
| + }
|
| +
|
| + private:
|
| + rtc::Thread* const signaling_thread_;
|
| + webrtc::PeerConnectionInterface* const connection_;
|
| + AbstractPeerConnection::Delegate* const delegate_;
|
| + bool disposed_;
|
| +};
|
| +
|
| +class CreateAndSetHandler
|
| + : public webrtc::CreateSessionDescriptionObserver,
|
| + public webrtc::SetSessionDescriptionObserver {
|
| + public:
|
| + explicit CreateAndSetHandler(
|
| + rtc::scoped_refptr<PeerConnectionHolder> holder)
|
| + : holder_(holder) {
|
| + }
|
| +
|
| + virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
|
| + if (holder_->IsDisposed()) return;
|
| +
|
| + type_ = desc->type();
|
| + if (desc->ToString(&description_)) {
|
| + holder_->connection()->SetLocalDescription(this, desc);
|
| + } else {
|
| + OnFailure("Can't serialize session description");
|
| + }
|
| + }
|
| +
|
| + virtual void OnSuccess() override {
|
| + if (holder_->IsDisposed()) return;
|
| +
|
| + if (type_ == webrtc::SessionDescriptionInterface::kOffer) {
|
| + holder_->delegate()->OnLocalOfferCreatedAndSetSet(description_);
|
| + } else {
|
| + DCHECK_EQ(webrtc::SessionDescriptionInterface::kAnswer, type_);
|
| +
|
| + holder_->delegate()->OnLocalAnswerCreatedAndSetSet(description_);
|
| + }
|
| + }
|
| +
|
| + virtual void OnFailure(const std::string& error) override {
|
| + if (holder_->IsDisposed()) return;
|
| +
|
| + holder_->delegate()->OnFailure(error);
|
| + }
|
| +
|
| + private:
|
| + const rtc::scoped_refptr<PeerConnectionHolder> holder_;
|
| + std::string type_;
|
| + std::string description_;
|
| +};
|
| +
|
| +class SetRemoteDescriptionHandler
|
| + : public webrtc::SetSessionDescriptionObserver {
|
| + public:
|
| + SetRemoteDescriptionHandler(
|
| + rtc::scoped_refptr<PeerConnectionHolder> holder)
|
| + : holder_(holder) {
|
| + }
|
| +
|
| + virtual void OnSuccess() override {
|
| + if (holder_->IsDisposed()) return;
|
| +
|
| + holder_->delegate()->OnRemoteDescriptionSet();
|
| + }
|
| +
|
| + virtual void OnFailure(const std::string& error) override {
|
| + if (holder_->IsDisposed()) return;
|
| +
|
| + holder_->delegate()->OnFailure(error);
|
| + }
|
| +
|
| + private:
|
| + const rtc::scoped_refptr<PeerConnectionHolder> holder_;
|
| +};
|
| +
|
| +class PeerConnectionImpl : public AbstractPeerConnection {
|
| + public:
|
| + PeerConnectionImpl(
|
| + rtc::Thread* signaling_thread,
|
| + rtc::scoped_refptr<webrtc::PeerConnectionInterface> connection,
|
| + scoped_ptr<PeerConnectionObserverImpl> observer,
|
| + scoped_ptr<AbstractPeerConnection::Delegate> delegate)
|
| + : holder_(new rtc::RefCountedObject<PeerConnectionHolder>(
|
| + signaling_thread, connection.get(), delegate.get())),
|
| + signaling_thread_(signaling_thread),
|
| + connection_(connection),
|
| + observer_(observer.Pass()),
|
| + delegate_(delegate.Pass()) {
|
| + }
|
| +
|
| + virtual ~PeerConnectionImpl() {
|
| + signaling_thread_->Invoke<void>(rtc::Bind(
|
| + &PeerConnectionImpl::DisposeOnSignalingThread, this));
|
| + }
|
| +
|
| + virtual void CreateAndSetLocalOffer() override {
|
| + connection_->CreateOffer(MakeCreateAndSetHandler(), NULL);
|
| + }
|
| +
|
| + virtual void CreateAndSetLocalAnswer() override {
|
| + connection_->CreateAnswer(MakeCreateAndSetHandler(), NULL);
|
| + }
|
| +
|
| + virtual void SetRemoteOffer(const std::string& description) override {
|
| + SetRemoteDescription(
|
| + webrtc::SessionDescriptionInterface::kOffer, description);
|
| + }
|
| +
|
| + virtual void SetRemoteAnswer(const std::string& description) override {
|
| + SetRemoteDescription(
|
| + webrtc::SessionDescriptionInterface::kAnswer, description);
|
| + }
|
| +
|
| + void SetRemoteDescription(
|
| + const std::string& type, const std::string& description) {
|
| + webrtc::SdpParseError error;
|
| + scoped_ptr<webrtc::SessionDescriptionInterface> value(
|
| + webrtc::CreateSessionDescription(type, description, &error));
|
| + if (value == NULL) {
|
| + OnParseError(error);
|
| + return;
|
| + }
|
| + // Takes ownership on |value|.
|
| + connection_->SetRemoteDescription(
|
| + new rtc::RefCountedObject<SetRemoteDescriptionHandler>(holder_),
|
| + value.release());
|
| + }
|
| +
|
| + virtual void AddIceCandidate(
|
| + const std::string& sdp_mid,
|
| + int sdp_mline_index,
|
| + const std::string& sdp) override {
|
| + webrtc::SdpParseError error;
|
| + auto candidate = webrtc::CreateIceCandidate(
|
| + sdp_mid, sdp_mline_index, sdp, &error);
|
| + if (candidate == NULL) {
|
| + OnParseError(error);
|
| + return;
|
| + }
|
| + // Doesn't takes ownership.
|
| + connection_->AddIceCandidate(candidate);
|
| + delete candidate;
|
| + }
|
| +
|
| + virtual scoped_ptr<AbstractDataChannel> CreateDataChannel(
|
| + int channelId) override {
|
| + webrtc::DataChannelInit init;
|
| + init.reliable = true;
|
| + init.ordered = true;
|
| + init.negotiated = true;
|
| + init.id = channelId;
|
| +
|
| + return make_scoped_ptr(new DataChannelImpl(
|
| + connection_->CreateDataChannel("", &init)));
|
| + }
|
| +
|
| + private:
|
| + webrtc::CreateSessionDescriptionObserver* MakeCreateAndSetHandler() {
|
| + return new rtc::RefCountedObject<CreateAndSetHandler>(holder_);
|
| + }
|
| +
|
| + void DisposeOnSignalingThread() {
|
| + DCHECK(signaling_thread_->IsCurrent());
|
| +
|
| + CheckedRelease(&connection_);
|
| + holder_->Dispose();
|
| + }
|
| +
|
| + void OnParseError(const webrtc::SdpParseError& error) {
|
| + // TODO(serya): Send on signaling thread.
|
| + }
|
| +
|
| + const rtc::scoped_refptr<PeerConnectionHolder> holder_;
|
| + rtc::Thread* const signaling_thread_;
|
| + rtc::scoped_refptr<webrtc::PeerConnectionInterface> connection_;
|
| + const scoped_ptr<PeerConnectionObserverImpl> observer_;
|
| + const scoped_ptr<AbstractPeerConnection::Delegate> delegate_;
|
| +};
|
| +
|
| +class SessionDependencyFactoryImpl : public SessionDependencyFactory {
|
| + public:
|
| + SessionDependencyFactoryImpl(
|
| + const base::Closure& cleanup_on_signaling_thread)
|
| + : cleanup_on_signaling_thread_(cleanup_on_signaling_thread) {
|
| + signaling_thread_.SetName("signaling_thread", NULL);
|
| + signaling_thread_.Start();
|
| + worker_thread_.SetName("worker_thread", NULL);
|
| + worker_thread_.Start();
|
| +
|
| + factory_ = webrtc::CreatePeerConnectionFactory(
|
| + &worker_thread_, &signaling_thread_, NULL, NULL, NULL);
|
| + }
|
| +
|
| + virtual ~SessionDependencyFactoryImpl() {
|
| + signaling_thread_.Invoke<void>(rtc::Bind(
|
| + &SessionDependencyFactoryImpl::DisposeOnSignalingThread, this));
|
| + }
|
| +
|
| + virtual scoped_ptr<AbstractPeerConnection> CreatePeerConnection(
|
| + scoped_ptr<RTCConfiguration> config,
|
| + scoped_ptr<AbstractPeerConnection::Delegate> delegate) override {
|
| + auto observer = make_scoped_ptr(
|
| + new PeerConnectionObserverImpl(delegate.get()));
|
| +
|
| + MediaConstraints constraints;
|
| + constraints.AddMandatory(
|
| + MediaConstraints::kEnableDtlsSrtp, MediaConstraints::kValueTrue);
|
| +
|
| + auto connection = factory_->CreatePeerConnection(
|
| + config->impl(), &constraints, NULL, NULL, observer.get());
|
| +
|
| + return make_scoped_ptr(new PeerConnectionImpl(
|
| + &signaling_thread_, connection, observer.Pass(), delegate.Pass()));
|
| + }
|
| +
|
| + private:
|
| + void DisposeOnSignalingThread() {
|
| + DCHECK(signaling_thread_.IsCurrent());
|
| + CheckedRelease(&factory_);
|
| + if (!cleanup_on_signaling_thread_.is_null()) {
|
| + cleanup_on_signaling_thread_.Run();
|
| + }
|
| + }
|
| +
|
| + base::Closure cleanup_on_signaling_thread_;
|
| + rtc::Thread signaling_thread_;
|
| + rtc::Thread worker_thread_;
|
| + rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +// RTCCOnfiguration
|
| +
|
| +// static
|
| +scoped_ptr<RTCConfiguration> RTCConfiguration::CreateInstance() {
|
| + return make_scoped_ptr(new RTCConfiguration::Impl());
|
| +}
|
| +
|
| +// SessionDependencyFactory
|
| +
|
| +// static
|
| +bool SessionDependencyFactory::InitializeSSL() {
|
| + return rtc::InitializeSSL();
|
| +}
|
| +
|
| +// static
|
| +bool SessionDependencyFactory::CleanupSSL() {
|
| + return rtc::CleanupSSL();
|
| +}
|
| +
|
| +// static
|
| +scoped_ptr<SessionDependencyFactory> SessionDependencyFactory::CreateInstance(
|
| + const base::Closure& cleanup_on_signaling_thread) {
|
| + return make_scoped_ptr(new SessionDependencyFactoryImpl(
|
| + cleanup_on_signaling_thread));
|
| +}
|
| +
|
| +} // namespace devtools_bridge
|
|
|