| // 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 <string> |
| |
| #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<CastExtensionSession> Create( |
| scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
| scoped_refptr<net::URLRequestContextGetter> 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<webrtc::DesktopCapturer>* 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<base::SingleThreadTaskRunner> caller_task_runner, |
| scoped_refptr<net::URLRequestContextGetter> 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<webrtc::DesktopCapturer> 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<base::SingleThreadTaskRunner> caller_task_runner_; |
| scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_; |
| |
| // Objects related to the WebRTC PeerConnection. |
| rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_; |
| rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_conn_factory_; |
| rtc::scoped_refptr<webrtc::MediaStreamInterface> stream_; |
| rtc::scoped_refptr<CastCreateSessionDescriptionObserver> |
| create_session_desc_observer_; |
| |
| // Parameters passed to ChromiumPortAllocatorFactory on creation. |
| scoped_refptr<net::URLRequestContextGetter> 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<webrtc::StatsObserver> 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_ |