Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "components/devtools_bridge/session_dependency_factory.h" | |
| 6 | |
| 7 #include "components/devtools_bridge/abstract_data_channel.h" | |
| 8 #include "components/devtools_bridge/abstract_peer_connection.h" | |
| 9 #include "components/devtools_bridge/rtc_configuration.h" | |
| 10 #include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface .h" | |
| 11 #include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h " | |
| 12 #include "third_party/webrtc/base/bind.h" | |
| 13 #include "third_party/webrtc/base/ssladapter.h" | |
| 14 #include "third_party/webrtc/base/thread.h" | |
| 15 | |
| 16 namespace devtools_bridge { | |
| 17 | |
| 18 class RTCConfiguration::Impl | |
| 19 : public RTCConfiguration, | |
| 20 public webrtc::PeerConnectionInterface::RTCConfiguration { | |
| 21 public: | |
| 22 | |
| 23 virtual void AddIceServer( | |
| 24 std::string const& uri, | |
| 25 std::string const& username, | |
| 26 std::string const& credential) override { | |
| 27 webrtc::PeerConnectionInterface::IceServer server; | |
| 28 server.uri = uri; | |
| 29 server.username = username; | |
| 30 server.password = credential; | |
| 31 servers.push_back(server); | |
| 32 } | |
| 33 | |
| 34 Impl const& impl() const override { | |
|
mnaganov (inactive)
2014/11/10 18:10:26
Also "const& Impl"
SeRya
2014/11/11 08:08:19
Done.
| |
| 35 return *this; | |
| 36 } | |
| 37 | |
| 38 private: | |
| 39 webrtc::PeerConnectionInterface::RTCConfiguration base_; | |
| 40 }; | |
| 41 | |
| 42 namespace { | |
| 43 | |
| 44 template <typename T> | |
| 45 void CheckedRelease(rtc::scoped_refptr<T>* ptr) { | |
| 46 CHECK_EQ(0, ptr->release()->Release()); | |
| 47 } | |
| 48 | |
| 49 class MediaConstraints | |
| 50 : public webrtc::MediaConstraintsInterface { | |
| 51 public: | |
| 52 virtual ~MediaConstraints() {} | |
| 53 | |
| 54 virtual const Constraints& GetMandatory() const override { | |
| 55 return mandatory_; | |
| 56 } | |
| 57 | |
| 58 virtual const Constraints& GetOptional() const override { | |
| 59 return optional_; | |
| 60 } | |
| 61 | |
| 62 void AddMandatory(std::string const& key, std::string const& value) { | |
| 63 mandatory_.push_back(Constraint(key, value)); | |
| 64 } | |
| 65 | |
| 66 private: | |
| 67 Constraints mandatory_; | |
| 68 Constraints optional_; | |
| 69 }; | |
| 70 | |
| 71 class DataChannelImpl : public AbstractDataChannel { | |
| 72 public: | |
| 73 explicit DataChannelImpl( | |
| 74 rtc::scoped_refptr<webrtc::DataChannelInterface> impl) : impl_(impl) { | |
| 75 } | |
| 76 | |
| 77 // TODO(serya): Implement. | |
| 78 | |
| 79 private: | |
| 80 rtc::scoped_refptr<webrtc::DataChannelInterface> const impl_; | |
| 81 }; | |
| 82 | |
| 83 class PeerConnectionObserverImpl | |
| 84 : public webrtc::PeerConnectionObserver { | |
| 85 public: | |
| 86 PeerConnectionObserverImpl(AbstractPeerConnection::Delegate* delegate) | |
| 87 : delegate_(delegate), | |
| 88 connected_(false) { | |
| 89 } | |
| 90 | |
| 91 virtual void OnAddStream(webrtc::MediaStreamInterface* stream) override {} | |
| 92 | |
| 93 virtual void OnRemoveStream(webrtc::MediaStreamInterface* stream) override {} | |
| 94 | |
| 95 virtual void OnDataChannel(webrtc::DataChannelInterface* data_channel) | |
| 96 override {} | |
| 97 | |
| 98 virtual void OnRenegotiationNeeded() override {} | |
| 99 | |
| 100 virtual void OnSignalingChange( | |
| 101 webrtc::PeerConnectionInterface::SignalingState new_state) override { | |
| 102 } | |
| 103 | |
| 104 virtual void OnIceConnectionChange( | |
| 105 webrtc::PeerConnectionInterface::IceConnectionState new_state) override { | |
| 106 bool connected = | |
| 107 new_state == webrtc::PeerConnectionInterface::kIceConnectionConnected || | |
| 108 new_state == webrtc::PeerConnectionInterface::kIceConnectionCompleted; | |
| 109 | |
| 110 if (connected != connected_) { | |
| 111 connected_ = connected; | |
| 112 delegate_->OnIceConnectionChange(connected_); | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) | |
| 117 override { | |
| 118 std::string sdp; | |
| 119 candidate->ToString(&sdp); | |
| 120 | |
| 121 delegate_->OnIceCandidate( | |
| 122 candidate->sdp_mid(), candidate->sdp_mline_index(), sdp); | |
| 123 } | |
| 124 | |
| 125 private: | |
| 126 AbstractPeerConnection::Delegate* const delegate_; | |
| 127 bool connected_; | |
| 128 }; | |
| 129 | |
| 130 /** | |
| 131 * Helper object which may outlive PeerConnectionImpl. Provides access | |
| 132 * to the connection and the delegate to operaion callback objects | |
| 133 * in a safe way. Always accessible on the signaling thread. | |
| 134 */ | |
| 135 class PeerConnectionHolder : public rtc::RefCountInterface { | |
| 136 public: | |
| 137 PeerConnectionHolder( | |
| 138 rtc::Thread* signaling_thread, | |
| 139 webrtc::PeerConnectionInterface* connection, | |
| 140 AbstractPeerConnection::Delegate* delegate) | |
| 141 : signaling_thread_(signaling_thread), | |
|
mnaganov (inactive)
2014/11/10 18:10:26
I think indentation is a bit odd here.
SeRya
2014/11/11 08:08:19
Done.
| |
| 142 connection_(connection), | |
| 143 delegate_(delegate), | |
| 144 disposed_(false) { | |
| 145 } | |
| 146 | |
| 147 virtual ~PeerConnectionHolder() { | |
| 148 DCHECK(disposed_); | |
| 149 } | |
| 150 | |
| 151 void Dispose() { | |
| 152 DCHECK(!IsDisposed()); | |
| 153 disposed_ = true; | |
| 154 } | |
| 155 | |
| 156 webrtc::PeerConnectionInterface* connection() { | |
| 157 DCHECK(!IsDisposed()); | |
| 158 return connection_; | |
| 159 } | |
| 160 | |
| 161 AbstractPeerConnection::Delegate* delegate() { | |
| 162 DCHECK(!IsDisposed()); | |
| 163 return delegate_; | |
| 164 } | |
| 165 | |
| 166 bool IsDisposed() { | |
| 167 DCHECK(signaling_thread_->IsCurrent()); | |
| 168 return disposed_; | |
| 169 } | |
| 170 | |
| 171 private: | |
| 172 rtc::Thread* const signaling_thread_; | |
| 173 webrtc::PeerConnectionInterface* const connection_; | |
| 174 AbstractPeerConnection::Delegate* const delegate_; | |
| 175 bool disposed_; | |
| 176 }; | |
| 177 | |
| 178 class CreateAndSetHandler | |
| 179 : public webrtc::CreateSessionDescriptionObserver, | |
| 180 public webrtc::SetSessionDescriptionObserver { | |
| 181 public: | |
| 182 explicit CreateAndSetHandler( | |
| 183 rtc::scoped_refptr<PeerConnectionHolder> holder) | |
| 184 : holder_(holder) { | |
| 185 } | |
| 186 | |
| 187 virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) override { | |
| 188 if (holder_->IsDisposed()) return; | |
| 189 | |
| 190 type_ = desc->type(); | |
| 191 if (desc->ToString(&description_)) { | |
| 192 holder_->connection()->SetLocalDescription(this, desc); | |
| 193 } else { | |
| 194 OnFailure("Can't serialize session description"); | |
| 195 } | |
| 196 } | |
| 197 | |
| 198 virtual void OnSuccess() override { | |
| 199 if (holder_->IsDisposed()) return; | |
| 200 | |
| 201 if (type_ == webrtc::SessionDescriptionInterface::kOffer) { | |
| 202 holder_->delegate()->OnLocalOfferCreatedAndSetSet(description_); | |
| 203 } else { | |
| 204 DCHECK_EQ(webrtc::SessionDescriptionInterface::kAnswer, type_); | |
| 205 | |
| 206 holder_->delegate()->OnLocalAnswerCreatedAndSetSet(description_); | |
| 207 } | |
| 208 } | |
| 209 | |
| 210 virtual void OnFailure(const std::string& error) override { | |
| 211 if (holder_->IsDisposed()) return; | |
| 212 | |
| 213 holder_->delegate()->OnFailure(error); | |
| 214 } | |
| 215 | |
| 216 private: | |
| 217 rtc::scoped_refptr<PeerConnectionHolder> const holder_; | |
| 218 std::string type_; | |
| 219 std::string description_; | |
| 220 }; | |
| 221 | |
| 222 class SetRemoteDescriptionHandler | |
| 223 : public webrtc::SetSessionDescriptionObserver { | |
| 224 public: | |
| 225 SetRemoteDescriptionHandler( | |
| 226 rtc::scoped_refptr<PeerConnectionHolder> holder) | |
| 227 : holder_(holder) { | |
| 228 } | |
| 229 | |
| 230 virtual void OnSuccess() override { | |
| 231 if (holder_->IsDisposed()) return; | |
| 232 | |
| 233 holder_->delegate()->OnRemoteDescriptionSet(); | |
| 234 } | |
| 235 | |
| 236 virtual void OnFailure(const std::string& error) override { | |
| 237 if (holder_->IsDisposed()) return; | |
| 238 | |
| 239 holder_->delegate()->OnFailure(error); | |
| 240 } | |
| 241 | |
| 242 private: | |
| 243 rtc::scoped_refptr<PeerConnectionHolder> const holder_; | |
| 244 }; | |
| 245 | |
| 246 class PeerConnectionImpl : public AbstractPeerConnection { | |
| 247 public: | |
| 248 PeerConnectionImpl( | |
| 249 rtc::Thread* signaling_thread, | |
| 250 rtc::scoped_refptr<webrtc::PeerConnectionInterface> connection, | |
| 251 scoped_ptr<PeerConnectionObserverImpl> observer, | |
| 252 scoped_ptr<AbstractPeerConnection::Delegate> delegate) | |
| 253 : holder_(new rtc::RefCountedObject<PeerConnectionHolder>( | |
| 254 signaling_thread, connection.get(), delegate.get())), | |
| 255 signaling_thread_(signaling_thread), | |
| 256 connection_(connection), | |
| 257 observer_(observer.Pass()), | |
| 258 delegate_(delegate.Pass()) { | |
| 259 } | |
| 260 | |
| 261 virtual ~PeerConnectionImpl() { | |
| 262 signaling_thread_->Invoke<void>(rtc::Bind( | |
| 263 &PeerConnectionImpl::DisposeOnSignalingThread, this)); | |
| 264 } | |
| 265 | |
| 266 virtual void CreateAndSetLocalOffer() override { | |
| 267 connection_->CreateOffer(MakeCreateAndSetHandler(), NULL); | |
| 268 } | |
| 269 | |
| 270 virtual void CreateAndSetLocalAnswer() override { | |
| 271 connection_->CreateAnswer(MakeCreateAndSetHandler(), NULL); | |
| 272 } | |
| 273 | |
| 274 virtual void SetRemoteOffer(std::string const& description) override { | |
| 275 SetRemoteDescription( | |
| 276 webrtc::SessionDescriptionInterface::kOffer, description); | |
| 277 } | |
| 278 | |
| 279 virtual void SetRemoteAnswer(std::string const& description) override { | |
| 280 SetRemoteDescription( | |
| 281 webrtc::SessionDescriptionInterface::kAnswer, description); | |
| 282 } | |
| 283 | |
| 284 void SetRemoteDescription( | |
| 285 std::string const& type, std::string const& description) { | |
| 286 webrtc::SdpParseError error; | |
| 287 scoped_ptr<webrtc::SessionDescriptionInterface> value( | |
| 288 webrtc::CreateSessionDescription(type, description, &error)); | |
| 289 if (value == NULL) { | |
| 290 OnParseError(error); | |
| 291 return; | |
| 292 } | |
| 293 // Takes ownership on |value|. | |
| 294 connection_->SetRemoteDescription( | |
| 295 new rtc::RefCountedObject<SetRemoteDescriptionHandler>(holder_), | |
| 296 value.release()); | |
| 297 } | |
| 298 | |
| 299 virtual void AddIceCandidate( | |
| 300 std::string const& sdp_mid, | |
| 301 int sdp_mline_index, | |
| 302 std::string const& sdp) override { | |
| 303 webrtc::SdpParseError error; | |
| 304 auto candidate = webrtc::CreateIceCandidate( | |
| 305 sdp_mid, sdp_mline_index, sdp, &error); | |
| 306 if (candidate == NULL) { | |
| 307 OnParseError(error); | |
| 308 return; | |
| 309 } | |
| 310 // Doesn't takes ownership. | |
| 311 connection_->AddIceCandidate(candidate); | |
| 312 delete candidate; | |
| 313 } | |
| 314 | |
| 315 virtual scoped_ptr<AbstractDataChannel> CreateDataChannel( | |
| 316 int channelId) override { | |
| 317 webrtc::DataChannelInit init; | |
| 318 init.reliable = true; | |
| 319 init.ordered = true; | |
| 320 init.negotiated = true; | |
| 321 init.id = channelId; | |
| 322 | |
| 323 return make_scoped_ptr(new DataChannelImpl( | |
| 324 connection_->CreateDataChannel("", &init))); | |
| 325 } | |
| 326 | |
| 327 private: | |
| 328 webrtc::CreateSessionDescriptionObserver* MakeCreateAndSetHandler() { | |
| 329 return new rtc::RefCountedObject<CreateAndSetHandler>(holder_); | |
| 330 } | |
| 331 | |
| 332 void DisposeOnSignalingThread() { | |
| 333 DCHECK(signaling_thread_->IsCurrent()); | |
| 334 | |
| 335 CheckedRelease(&connection_); | |
| 336 holder_->Dispose(); | |
| 337 } | |
| 338 | |
| 339 void OnParseError(webrtc::SdpParseError const& error) { | |
| 340 // TODO(serya): Send on signaling thread. | |
| 341 } | |
| 342 | |
| 343 rtc::scoped_refptr<PeerConnectionHolder> const holder_; | |
| 344 rtc::Thread* const signaling_thread_; | |
| 345 rtc::scoped_refptr<webrtc::PeerConnectionInterface> connection_; | |
| 346 scoped_ptr<PeerConnectionObserverImpl> const observer_; | |
| 347 scoped_ptr<AbstractPeerConnection::Delegate> const delegate_; | |
| 348 }; | |
| 349 | |
| 350 class SessionDependencyFactoryImpl : public SessionDependencyFactory { | |
| 351 public: | |
| 352 SessionDependencyFactoryImpl( | |
| 353 base::Closure const& cleanup_on_signaling_thread) | |
| 354 : cleanup_on_signaling_thread_(cleanup_on_signaling_thread) { | |
| 355 signaling_thread_.SetName("signaling_thread", NULL); | |
| 356 signaling_thread_.Start(); | |
| 357 worker_thread_.SetName("worker_thread", NULL); | |
| 358 worker_thread_.Start(); | |
| 359 | |
| 360 factory_ = webrtc::CreatePeerConnectionFactory( | |
| 361 &worker_thread_, &signaling_thread_, NULL, NULL, NULL); | |
| 362 } | |
| 363 | |
| 364 virtual ~SessionDependencyFactoryImpl() { | |
| 365 signaling_thread_.Invoke<void>(rtc::Bind( | |
| 366 &SessionDependencyFactoryImpl::DisposeOnSignalingThread, this)); | |
| 367 } | |
| 368 | |
| 369 virtual scoped_ptr<AbstractPeerConnection> CreatePeerConnection( | |
| 370 scoped_ptr<RTCConfiguration> config, | |
| 371 scoped_ptr<AbstractPeerConnection::Delegate> delegate) override { | |
| 372 auto observer = make_scoped_ptr( | |
| 373 new PeerConnectionObserverImpl(delegate.get())); | |
| 374 | |
| 375 MediaConstraints constraints; | |
| 376 constraints.AddMandatory( | |
| 377 MediaConstraints::kEnableDtlsSrtp, MediaConstraints::kValueTrue); | |
| 378 | |
| 379 auto connection = factory_->CreatePeerConnection( | |
| 380 config->impl(), &constraints, NULL, NULL, observer.get()); | |
| 381 | |
| 382 return make_scoped_ptr(new PeerConnectionImpl( | |
| 383 &signaling_thread_, connection, observer.Pass(), delegate.Pass())); | |
| 384 } | |
| 385 | |
| 386 private: | |
| 387 void DisposeOnSignalingThread() { | |
| 388 DCHECK(signaling_thread_.IsCurrent()); | |
| 389 CheckedRelease(&factory_); | |
| 390 if (!cleanup_on_signaling_thread_.is_null()) { | |
| 391 cleanup_on_signaling_thread_.Run(); | |
| 392 } | |
| 393 } | |
| 394 | |
| 395 base::Closure cleanup_on_signaling_thread_; | |
| 396 rtc::Thread signaling_thread_; | |
| 397 rtc::Thread worker_thread_; | |
| 398 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory_; | |
| 399 }; | |
| 400 | |
| 401 } // namespace | |
| 402 | |
| 403 // RTCCOnfiguration | |
| 404 | |
| 405 // static | |
| 406 scoped_ptr<RTCConfiguration> RTCConfiguration::CreateInstance() { | |
| 407 return make_scoped_ptr(new RTCConfiguration::Impl()); | |
| 408 } | |
| 409 | |
| 410 // SessionDependencyFactory | |
| 411 | |
| 412 // static | |
| 413 bool SessionDependencyFactory::InitializeSSL() { | |
| 414 return rtc::InitializeSSL(); | |
| 415 } | |
| 416 | |
| 417 // static | |
| 418 bool SessionDependencyFactory::CleanupSSL() { | |
| 419 return rtc::CleanupSSL(); | |
| 420 } | |
| 421 | |
| 422 // static | |
| 423 scoped_ptr<SessionDependencyFactory> SessionDependencyFactory::CreateInstance( | |
| 424 base::Closure const& cleanup_on_signaling_thread) { | |
| 425 return make_scoped_ptr(new SessionDependencyFactoryImpl( | |
| 426 cleanup_on_signaling_thread)); | |
| 427 } | |
| 428 | |
| 429 } // namespace devtools_bridge | |
| OLD | NEW |