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#ifndef REMOTING_HOST_CAST_EXTENSION_SESSION_H_
6#define REMOTING_HOST_CAST_EXTENSION_SESSION_H_
7
8#include <string>
9
10#include "base/memory/ref_counted.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/threading/thread.h"
13#include "base/timer/timer.h"
14#include "base/values.h"
15#include "jingle/glue/thread_wrapper.h"
16#include "remoting/host/host_extension_session.h"
17#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
18#include "third_party/webrtc/base/scoped_ref_ptr.h"
19#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
20
21namespace base {
22class SingleThreadTaskRunner;
23class WaitableEvent;
24}  // namespace base
25
26namespace net {
27class URLRequestContextGetter;
28}  // namespace net
29
30namespace webrtc {
31class MediaStreamInterface;
32}  // namespace webrtc
33
34namespace remoting {
35
36class CastCreateSessionDescriptionObserver;
37
38namespace protocol {
39struct NetworkSettings;
40}  // namespace protocol
41
42// A HostExtensionSession implementation that enables WebRTC support using
43// the PeerConnection native API.
44class CastExtensionSession : public HostExtensionSession,
45                             public webrtc::PeerConnectionObserver {
46 public:
47  virtual ~CastExtensionSession();
48
49  // Creates and returns a CastExtensionSession object, after performing
50  // initialization steps on it. The caller must take ownership of the returned
51  // object.
52  static scoped_ptr<CastExtensionSession> Create(
53      scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
54      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
55      const protocol::NetworkSettings& network_settings,
56      ClientSessionControl* client_session_control,
57      protocol::ClientStub* client_stub);
58
59  // Called by webrtc::CreateSessionDescriptionObserver implementation.
60  void OnCreateSessionDescription(webrtc::SessionDescriptionInterface* desc);
61  void OnCreateSessionDescriptionFailure(const std::string& error);
62
63  // HostExtensionSession interface.
64  virtual void OnCreateVideoCapturer(
65      scoped_ptr<webrtc::DesktopCapturer>* capturer) OVERRIDE;
66  virtual bool ModifiesVideoPipeline() const OVERRIDE;
67  virtual bool OnExtensionMessage(
68      ClientSessionControl* client_session_control,
69      protocol::ClientStub* client_stub,
70      const protocol::ExtensionMessage& message) OVERRIDE;
71
72  // webrtc::PeerConnectionObserver interface.
73  virtual void OnError() OVERRIDE;
74  virtual void OnSignalingChange(
75      webrtc::PeerConnectionInterface::SignalingState new_state) OVERRIDE;
76  virtual void OnStateChange(
77      webrtc::PeerConnectionObserver::StateType state_changed) OVERRIDE;
78  virtual void OnAddStream(webrtc::MediaStreamInterface* stream) OVERRIDE;
79  virtual void OnRemoveStream(webrtc::MediaStreamInterface* stream) OVERRIDE;
80  virtual void OnDataChannel(
81      webrtc::DataChannelInterface* data_channel) OVERRIDE;
82  virtual void OnRenegotiationNeeded() OVERRIDE;
83  virtual void OnIceConnectionChange(
84      webrtc::PeerConnectionInterface::IceConnectionState new_state) OVERRIDE;
85  virtual void OnIceGatheringChange(
86      webrtc::PeerConnectionInterface::IceGatheringState new_state) OVERRIDE;
87  virtual void OnIceCandidate(
88      const webrtc::IceCandidateInterface* candidate) OVERRIDE;
89  virtual void OnIceComplete() OVERRIDE;
90
91 private:
92  CastExtensionSession(
93      scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
94      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
95      const protocol::NetworkSettings& network_settings,
96      ClientSessionControl* client_session_control,
97      protocol::ClientStub* client_stub);
98
99  // Parses |message| for a Session Description and sets the remote
100  // description, returning true if successful.
101  bool ParseAndSetRemoteDescription(base::DictionaryValue* message);
102
103  // Parses |message| for a PeerConnection ICE candidate and adds it to the
104  // Peer Connection, returning true if successful.
105  bool ParseAndAddICECandidate(base::DictionaryValue* message);
106
107  // Sends a message to the client through |client_stub_|. This method must be
108  // called on the network thread.
109  //
110  // A protocol::ExtensionMessage consists of two string fields: type and data.
111  //
112  // The type field must be |kExtensionMessageType|.
113  // The data field must be a JSON formatted string with two compulsory
114  // top level keys: |kTopLevelSubject| and |kTopLevelData|.
115  //
116  // The |subject| of a message describes the message to the receiving peer,
117  // effectively identifying the command the receiving peer should perform.
118  // The |subject| MUST be one of constants formatted as kSubject* defined in
119  // the .cc file. This set of subjects is identical between host and client,
120  // thus standardizing how they communicate.
121  // The |data| of a message depends on the |subject| of the message.
122  //
123  // Examples of what ExtensionMessage.data() could look like:
124  //
125  // Host Ready Message:
126  // Notifies the remote peer that we are ready to receive an offer.
127  //
128  // {
129  //   "subject": "ready",
130  //   "chromoting_data": "Host Ready to receive offers"
131  // }
132  //
133  // WebRTC Offer Message:
134  // Represents the offer received from the remote peer. The local
135  // peer would then respond with a webrtc_answer message.
136  // {
137  //   "subject": "webrtc_offer",
138  //   "chromoting_data": {
139  //      "sdp" : "...",
140  //      "type" : "offer"
141  //    }
142  // }
143  //
144  // WebRTC Candidate Message:
145  // Represents an ICE candidate received from the remote peer. Each peer
146  // shares its local ICE candidates in this way, until a connection is
147  // established.
148  //
149  // {
150  //   "subject": "webrtc_candidate",
151  //   "chromoting_data": {
152  //      "candidate" : "...",
153  //      "sdpMid" : "...",
154  //      "sdpMLineIndex" : "..."
155  //    }
156  // }
157  //
158  bool SendMessageToClient(const std::string& subject, const std::string& data);
159
160  // Creates the jingle wrapper for the current thread, sets send to allowed,
161  // and saves a pointer to the relevant thread pointer in ptr. If |event|
162  // is not NULL, signals the event on completion.
163  void EnsureTaskAndSetSend(rtc::Thread** ptr,
164                            base::WaitableEvent* event = NULL);
165
166  // Wraps each task runner in JingleThreadWrapper using EnsureTaskAndSetSend(),
167  // returning true if successful. Wrapping the task runners allows them to be
168  // shared with and used by the (about to be created) PeerConnectionFactory.
169  bool WrapTasksAndSave();
170
171  // Initializes PeerConnectionFactory and PeerConnection and sends a "ready"
172  // message to client. Returns true if these steps are performed successfully.
173  bool InitializePeerConnection();
174
175  // Constructs a CastVideoCapturerAdapter, a VideoSource, a VideoTrack and a
176  // MediaStream |stream_|, which it adds to the |peer_connection_|. Returns
177  // true if these steps are performed successfully. This method is called only
178  // when a PeerConnection offer is received from the client.
179  bool SetupVideoStream(scoped_ptr<webrtc::DesktopCapturer> desktop_capturer);
180
181  // Polls a single stats report from the PeerConnection immediately. Called
182  // periodically using |stats_polling_timer_| after a PeerConnection has been
183  // established.
184  void PollPeerConnectionStats();
185
186  // Closes |peer_connection_|, releases |peer_connection_|, |stream_| and
187  // |peer_conn_factory_| and stops the worker thread.
188  void CleanupPeerConnection();
189
190  // Check if the connection is active.
191  bool connection_active() const;
192
193  // TaskRunners that will be used to setup the PeerConnectionFactory's
194  // signalling thread and worker thread respectively.
195  scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
196  scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_;
197
198  // Objects related to the WebRTC PeerConnection.
199  rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
200  rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_conn_factory_;
201  rtc::scoped_refptr<webrtc::MediaStreamInterface> stream_;
202  rtc::scoped_refptr<CastCreateSessionDescriptionObserver>
203      create_session_desc_observer_;
204
205  // Parameters passed to ChromiumPortAllocatorFactory on creation.
206  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
207  const protocol::NetworkSettings& network_settings_;
208
209  // Interface to interact with ClientSession.
210  ClientSessionControl* client_session_control_;
211
212  // Interface through which messages can be sent to the client.
213  protocol::ClientStub* client_stub_;
214
215  // Used to track webrtc connection statistics.
216  rtc::scoped_refptr<webrtc::StatsObserver> stats_observer_;
217
218  // Used to repeatedly poll stats from the |peer_connection_|.
219  base::RepeatingTimer<CastExtensionSession> stats_polling_timer_;
220
221  // True if a PeerConnection offer from the client has been received. This
222  // necessarily means that the host is not the caller in this attempted
223  // peer connection.
224  bool received_offer_;
225
226  // True if the webrtc::ScreenCapturer has been grabbed through the
227  // OnCreateVideoCapturer() callback.
228  bool has_grabbed_capturer_;
229
230  // PeerConnection signaling and worker threads created from
231  // JingleThreadWrappers. Each is created by calling
232  // jingle_glue::EnsureForCurrentMessageLoop() and thus deletes itself
233  // automatically when the associated MessageLoop is destroyed.
234  rtc::Thread* signaling_thread_wrapper_;
235  rtc::Thread* worker_thread_wrapper_;
236
237  // Worker thread that is wrapped to create |worker_thread_wrapper_|.
238  base::Thread worker_thread_;
239
240  DISALLOW_COPY_AND_ASSIGN(CastExtensionSession);
241};
242
243}  // namespace remoting
244
245#endif  // REMOTING_HOST_CAST_EXTENSION_SESSION_H_
246