// 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. #ifndef REMOTING_HOST_CAST_EXTENSION_SESSION_H_ #define REMOTING_HOST_CAST_EXTENSION_SESSION_H_ #include #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/threading/thread.h" #include "base/timer/timer.h" #include "base/values.h" #include "jingle/glue/thread_wrapper.h" #include "remoting/host/host_extension_session.h" #include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h" #include "third_party/webrtc/base/scoped_ref_ptr.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" namespace base { class SingleThreadTaskRunner; class WaitableEvent; } // namespace base namespace net { class URLRequestContextGetter; } // namespace net namespace webrtc { class MediaStreamInterface; } // namespace webrtc namespace remoting { class CastCreateSessionDescriptionObserver; namespace protocol { struct NetworkSettings; } // namespace protocol // A HostExtensionSession implementation that enables WebRTC support using // the PeerConnection native API. class CastExtensionSession : public HostExtensionSession, public webrtc::PeerConnectionObserver { public: ~CastExtensionSession() override; // Creates and returns a CastExtensionSession object, after performing // initialization steps on it. The caller must take ownership of the returned // object. static scoped_ptr Create( scoped_refptr caller_task_runner, scoped_refptr url_request_context_getter, const protocol::NetworkSettings& network_settings, ClientSessionControl* client_session_control, protocol::ClientStub* client_stub); // Called by webrtc::CreateSessionDescriptionObserver implementation. void OnCreateSessionDescription(webrtc::SessionDescriptionInterface* desc); void OnCreateSessionDescriptionFailure(const std::string& error); // HostExtensionSession interface. void OnCreateVideoCapturer( scoped_ptr* capturer) override; bool ModifiesVideoPipeline() const override; bool OnExtensionMessage(ClientSessionControl* client_session_control, protocol::ClientStub* client_stub, const protocol::ExtensionMessage& message) override; // webrtc::PeerConnectionObserver interface. void OnSignalingChange( webrtc::PeerConnectionInterface::SignalingState new_state) override; void OnStateChange( webrtc::PeerConnectionObserver::StateType state_changed) override; void OnAddStream(webrtc::MediaStreamInterface* stream) override; void OnRemoveStream(webrtc::MediaStreamInterface* stream) override; void OnDataChannel(webrtc::DataChannelInterface* data_channel) override; void OnRenegotiationNeeded() override; void OnIceConnectionChange( webrtc::PeerConnectionInterface::IceConnectionState new_state) override; void OnIceGatheringChange( webrtc::PeerConnectionInterface::IceGatheringState new_state) override; void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override; void OnIceComplete() override; private: CastExtensionSession( scoped_refptr caller_task_runner, scoped_refptr url_request_context_getter, const protocol::NetworkSettings& network_settings, ClientSessionControl* client_session_control, protocol::ClientStub* client_stub); // Parses |message| for a Session Description and sets the remote // description, returning true if successful. bool ParseAndSetRemoteDescription(base::DictionaryValue* message); // Parses |message| for a PeerConnection ICE candidate and adds it to the // Peer Connection, returning true if successful. bool ParseAndAddICECandidate(base::DictionaryValue* message); // Sends a message to the client through |client_stub_|. This method must be // called on the network thread. // // A protocol::ExtensionMessage consists of two string fields: type and data. // // The type field must be |kExtensionMessageType|. // The data field must be a JSON formatted string with two compulsory // top level keys: |kTopLevelSubject| and |kTopLevelData|. // // The |subject| of a message describes the message to the receiving peer, // effectively identifying the command the receiving peer should perform. // The |subject| MUST be one of constants formatted as kSubject* defined in // the .cc file. This set of subjects is identical between host and client, // thus standardizing how they communicate. // The |data| of a message depends on the |subject| of the message. // // Examples of what ExtensionMessage.data() could look like: // // Host Ready Message: // Notifies the remote peer that we are ready to receive an offer. // // { // "subject": "ready", // "chromoting_data": "Host Ready to receive offers" // } // // WebRTC Offer Message: // Represents the offer received from the remote peer. The local // peer would then respond with a webrtc_answer message. // { // "subject": "webrtc_offer", // "chromoting_data": { // "sdp" : "...", // "type" : "offer" // } // } // // WebRTC Candidate Message: // Represents an ICE candidate received from the remote peer. Each peer // shares its local ICE candidates in this way, until a connection is // established. // // { // "subject": "webrtc_candidate", // "chromoting_data": { // "candidate" : "...", // "sdpMid" : "...", // "sdpMLineIndex" : "..." // } // } // bool SendMessageToClient(const std::string& subject, const std::string& data); // Creates the jingle wrapper for the current thread, sets send to allowed, // and saves a pointer to the relevant thread pointer in ptr. If |event| // is not nullptr, signals the event on completion. void EnsureTaskAndSetSend(rtc::Thread** ptr, base::WaitableEvent* event = nullptr); // Wraps each task runner in JingleThreadWrapper using EnsureTaskAndSetSend(), // returning true if successful. Wrapping the task runners allows them to be // shared with and used by the (about to be created) PeerConnectionFactory. bool WrapTasksAndSave(); // Initializes PeerConnectionFactory and PeerConnection and sends a "ready" // message to client. Returns true if these steps are performed successfully. bool InitializePeerConnection(); // Constructs a CastVideoCapturerAdapter, a VideoSource, a VideoTrack and a // MediaStream |stream_|, which it adds to the |peer_connection_|. Returns // true if these steps are performed successfully. This method is called only // when a PeerConnection offer is received from the client. bool SetupVideoStream(scoped_ptr desktop_capturer); // Polls a single stats report from the PeerConnection immediately. Called // periodically using |stats_polling_timer_| after a PeerConnection has been // established. void PollPeerConnectionStats(); // Closes |peer_connection_|, releases |peer_connection_|, |stream_| and // |peer_conn_factory_| and stops the worker thread. void CleanupPeerConnection(); // Check if the connection is active. bool connection_active() const; // TaskRunners that will be used to setup the PeerConnectionFactory's // signalling thread and worker thread respectively. scoped_refptr caller_task_runner_; scoped_refptr worker_task_runner_; // Objects related to the WebRTC PeerConnection. rtc::scoped_refptr peer_connection_; rtc::scoped_refptr peer_conn_factory_; rtc::scoped_refptr stream_; rtc::scoped_refptr create_session_desc_observer_; // Parameters passed to ChromiumPortAllocatorFactory on creation. scoped_refptr url_request_context_getter_; const protocol::NetworkSettings& network_settings_; // Interface to interact with ClientSession. ClientSessionControl* client_session_control_; // Interface through which messages can be sent to the client. protocol::ClientStub* client_stub_; // Used to track webrtc connection statistics. rtc::scoped_refptr stats_observer_; // Used to repeatedly poll stats from the |peer_connection_|. base::RepeatingTimer stats_polling_timer_; // True if a PeerConnection offer from the client has been received. This // necessarily means that the host is not the caller in this attempted // peer connection. bool received_offer_; // True if the webrtc::ScreenCapturer has been grabbed through the // OnCreateVideoCapturer() callback. bool has_grabbed_capturer_; // PeerConnection signaling and worker threads created from // JingleThreadWrappers. Each is created by calling // jingle_glue::EnsureForCurrentMessageLoop() and thus deletes itself // automatically when the associated MessageLoop is destroyed. rtc::Thread* signaling_thread_wrapper_; rtc::Thread* worker_thread_wrapper_; // Worker thread that is wrapped to create |worker_thread_wrapper_|. base::Thread worker_thread_; DISALLOW_COPY_AND_ASSIGN(CastExtensionSession); }; } // namespace remoting #endif // REMOTING_HOST_CAST_EXTENSION_SESSION_H_