1 // Copyright (c) 2013 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 CONTENT_BROWSER_WEBRTC_WEBRTC_INTERNALS_H_
6 #define CONTENT_BROWSER_WEBRTC_WEBRTC_INTERNALS_H_
7 
8 #include <memory>
9 #include <string>
10 #include <unordered_set>
11 
12 #include "base/containers/queue.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/observer_list.h"
16 #include "base/process/process.h"
17 #include "base/threading/thread_checker.h"
18 #include "base/values.h"
19 #include "content/common/content_export.h"
20 #include "content/public/browser/render_process_host_observer.h"
21 #include "media/media_buildflags.h"
22 #include "mojo/public/cpp/bindings/remote.h"
23 #include "services/device/public/mojom/wake_lock.mojom.h"
24 #include "ui/shell_dialogs/select_file_dialog.h"
25 
26 namespace media {
27 class AudioDebugRecordingSession;
28 }
29 
30 namespace content {
31 
32 class WebContents;
33 class WebRtcInternalsConnectionsObserver;
34 class WebRTCInternalsUIObserver;
35 
36 // This is a singleton class running in the browser UI thread.
37 // It collects peer connection infomation from the renderers,
38 // forwards the data to WebRTCInternalsUIObserver and
39 // sends data collecting commands to the renderers.
40 class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
41                                        public ui::SelectFileDialog::Listener {
42  public:
43   // * CreateSingletonInstance() ensures that no previous instantiation of the
44   //   class was performed, then instantiates the class and returns the object.
45   // * GetInstance() returns the object previously constructed using
46   //   CreateSingletonInstance(). It may return null in tests.
47   // * Creation is separated from access because WebRTCInternals may only be
48   //   created from a context that allows blocking. If GetInstance were allowed
49   //   to instantiate, as with a lazily constructed singleton, it would be
50   //   difficult to guarantee that its construction is always first attempted
51   //   from a context that allows it.
52   static WebRTCInternals* CreateSingletonInstance();
53   static WebRTCInternals* GetInstance();
54 
55   ~WebRTCInternals() override;
56 
57   // This method is called when a PeerConnection is created.
58   // |render_process_id| is the id of the render process (not OS pid), which is
59   // needed because we might not be able to get the OS process id when the
60   // render process terminates and we want to clean up.
61   // |pid| is the renderer process id, |lid| is the renderer local id used to
62   // identify a PeerConnection, |url| is the url of the tab owning the
63   // PeerConnection, |rtc_configuration| is the serialized RTCConfiguration,
64   // |constraints| is the media constraints used to initialize the
65   // PeerConnection.
66   void OnAddPeerConnection(int render_process_id,
67                            base::ProcessId pid,
68                            int lid,
69                            const std::string& url,
70                            const std::string& rtc_configuration,
71                            const std::string& constraints);
72 
73   // This method is called when PeerConnection is destroyed.
74   // |pid| is the renderer process id, |lid| is the renderer local id.
75   void OnRemovePeerConnection(base::ProcessId pid, int lid);
76 
77   // This method is called when a PeerConnection is updated.
78   // |pid| is the renderer process id, |lid| is the renderer local id,
79   // |type| is the update type, |value| is the detail of the update.
80   void OnUpdatePeerConnection(base::ProcessId pid,
81                               int lid,
82                               const std::string& type,
83                               const std::string& value);
84 
85   // These methods are called when results from
86   // PeerConnectionInterface::GetStats (legacy or standard API) are available.
87   // |pid| is the renderer process id, |lid| is the renderer local id, |value|
88   // is the list of stats reports.
89   void OnAddStandardStats(base::ProcessId pid, int lid, base::Value value);
90   void OnAddLegacyStats(base::ProcessId pid, int lid, base::Value value);
91 
92   // This method is called when getUserMedia is called. |render_process_id| is
93   // the id of the render process (not OS pid), which is needed because we might
94   // not be able to get the OS process id when the render process terminates and
95   // we want to clean up. |pid| is the renderer OS process id, |origin| is the
96   // security origin of the getUserMedia call, |audio| is true if audio stream
97   // is requested, |video| is true if the video stream is requested,
98   // |audio_constraints| is the constraints for the audio, |video_constraints|
99   // is the constraints for the video.
100   void OnGetUserMedia(int render_process_id,
101                       base::ProcessId pid,
102                       const std::string& origin,
103                       bool audio,
104                       bool video,
105                       const std::string& audio_constraints,
106                       const std::string& video_constraints);
107 
108   // Methods for adding or removing WebRTCInternalsUIObserver.
109   void AddObserver(WebRTCInternalsUIObserver* observer);
110   void RemoveObserver(WebRTCInternalsUIObserver* observer);
111 
112   // Methods for adding or removing WebRtcInternalsConnectionsObserver.
113   // |observer| is notified when there is a change in the count of active WebRTC
114   // connections.
115   void AddConnectionsObserver(WebRtcInternalsConnectionsObserver* observer);
116   void RemoveConnectionsObserver(WebRtcInternalsConnectionsObserver* observer);
117 
118   // Sends all update data to |observer|.
119   void UpdateObserver(WebRTCInternalsUIObserver* observer);
120 
121   // Enables or disables diagnostic audio recordings for debugging purposes.
122   void EnableAudioDebugRecordings(content::WebContents* web_contents);
123   void DisableAudioDebugRecordings();
124 
125   bool IsAudioDebugRecordingsEnabled() const;
126   const base::FilePath& GetAudioDebugRecordingsFilePath() const;
127 
128   // Enables or disables diagnostic event log.
129   void EnableLocalEventLogRecordings(content::WebContents* web_contents);
130   void DisableLocalEventLogRecordings();
131 
132   bool IsEventLogRecordingsEnabled() const;
133   bool CanToggleEventLogRecordings() const;
134 
num_connected_connections()135   int num_connected_connections() const { return num_connected_connections_; }
136 
137  protected:
138   // Constructor/Destructor are protected to allow tests to derive from the
139   // class and do per-instance testing without having to use the global
140   // instance.
141   // The default ctor sets |aggregate_updates_ms| to 500ms.
142   WebRTCInternals();
143   WebRTCInternals(int aggregate_updates_ms, bool should_block_power_saving);
144 
145   mojo::Remote<device::mojom::WakeLock> wake_lock_;
146 
147  private:
148   FRIEND_TEST_ALL_PREFIXES(WebRtcAudioDebugRecordingsBrowserTest,
149                            CallWithAudioDebugRecordings);
150   FRIEND_TEST_ALL_PREFIXES(WebRtcAudioDebugRecordingsBrowserTest,
151                            CallWithAudioDebugRecordingsEnabledThenDisabled);
152   FRIEND_TEST_ALL_PREFIXES(WebRtcAudioDebugRecordingsBrowserTest,
153                            TwoCallsWithAudioDebugRecordings);
154   FRIEND_TEST_ALL_PREFIXES(WebRtcInternalsTest,
155                            AudioDebugRecordingsFileSelectionCanceled);
156 
157   static WebRTCInternals* g_webrtc_internals;
158 
159   void SendUpdate(const char* command,
160                   std::unique_ptr<base::Value> value);
161 
162   // RenderProcessHostObserver implementation.
163   void RenderProcessExited(RenderProcessHost* host,
164                            const ChildProcessTerminationInfo& info) override;
165 
166   // ui::SelectFileDialog::Listener implementation.
167   void FileSelected(const base::FilePath& path,
168                     int index,
169                     void* unused_params) override;
170   void FileSelectionCanceled(void* params) override;
171 
172   // Called when a renderer exits (including crashes).
173   void OnRendererExit(int render_process_id);
174 
175 #if BUILDFLAG(ENABLE_WEBRTC)
176   // Enables diagnostic audio recordings on all render process hosts using
177   // |audio_debug_recordings_file_path_|.
178   void EnableAudioDebugRecordingsOnAllRenderProcessHosts();
179 #endif
180 
181   // Updates the number of open PeerConnections. Called when a PeerConnection
182   // is stopped or removed.
183   void MaybeClosePeerConnection(base::DictionaryValue* record);
184 
185   void MaybeMarkPeerConnectionAsConnected(base::DictionaryValue* record);
186   void MaybeMarkPeerConnectionAsNotConnected(base::DictionaryValue* record);
187 
188   // Called whenever a PeerConnection is created or stopped in order to
189   // request/cancel a wake lock on suspending the current application for power
190   // saving.
191   void UpdateWakeLock();
192 
193   device::mojom::WakeLock* GetWakeLock();
194 
195   // Called on a timer to deliver updates to javascript.
196   // We throttle and bulk together updates to avoid DOS like scenarios where
197   // a page uses a lot of peerconnection instances with many event
198   // notifications.
199   void ProcessPendingUpdates();
200 
201   base::DictionaryValue* FindRecord(base::ProcessId pid,
202                                     int lid,
203                                     size_t* index = nullptr);
204 
205   base::ObserverList<WebRTCInternalsUIObserver>::Unchecked observers_;
206 
207   base::ObserverList<WebRtcInternalsConnectionsObserver> connections_observers_;
208 
209   // |peer_connection_data_| is a list containing all the PeerConnection
210   // updates.
211   // Each item of the list represents the data for one PeerConnection, which
212   // contains these fields:
213   // "rid" -- the renderer id.
214   // "pid" -- OS process id of the renderer that creates the PeerConnection.
215   // "lid" -- local Id assigned to the PeerConnection.
216   // "url" -- url of the web page that created the PeerConnection.
217   // "servers" and "constraints" -- server configuration and media constraints
218   // used to initialize the PeerConnection respectively.
219   // "log" -- a ListValue contains all the updates for the PeerConnection. Each
220   // list item is a DictionaryValue containing "time", which is the number of
221   // milliseconds since epoch as a string, and "type" and "value", both of which
222   // are strings representing the event.
223   base::ListValue peer_connection_data_;
224 
225   // A list of getUserMedia requests. Each item is a DictionaryValue that
226   // contains these fields:
227   // "rid" -- the renderer id.
228   // "pid" -- proceddId of the renderer.
229   // "origin" -- the security origin of the request.
230   // "audio" -- the serialized audio constraints if audio is requested.
231   // "video" -- the serialized video constraints if video is requested.
232   base::ListValue get_user_media_requests_;
233 
234   // For managing select file dialog.
235   scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
236   enum class SelectionType {
237     kRtcEventLogs,
238     kAudioDebugRecordings
239   } selection_type_;
240 
241   // Diagnostic audio recording state.
242   base::FilePath audio_debug_recordings_file_path_;
243   std::unique_ptr<media::AudioDebugRecordingSession>
244       audio_debug_recording_session_;
245 
246   // If non-empty, WebRTC (local) event logging should be enabled using this
247   // path, and may not be turned off, except by restarting the browser.
248   const base::FilePath command_line_derived_logging_path_;
249 
250   // Diagnostic event log recording state. These are meaningful only when
251   // |command_line_derived_logging_path_| is empty.
252   bool event_log_recordings_;
253   base::FilePath event_log_recordings_file_path_;
254 
255   // While |num_connected_connections_| is greater than zero, request a wake
256   // lock service. This prevents the application from being suspended while
257   // remoting.
258   int num_connected_connections_;
259   const bool should_block_power_saving_;
260 
261   // Set of render process hosts that |this| is registered as an observer on.
262   std::unordered_set<int> render_process_id_set_;
263 
264   // Used to bulk up updates that we send to javascript.
265   // The class owns the value/dictionary and command name of an update.
266   // For each update, a PendingUpdate is stored in the |pending_updates_| queue
267   // and deleted as soon as the update has been delivered.
268   // The class is moveble and not copyable to avoid copying while still allowing
269   // us to use an stl container without needing scoped_ptr or similar.
270   // The class is single threaded, so all operations must occur on the same
271   // thread.
272   class PendingUpdate {
273    public:
274     PendingUpdate(const char* command,
275                   std::unique_ptr<base::Value> value);
276     PendingUpdate(PendingUpdate&& other);
277     ~PendingUpdate();
278 
279     const char* command() const;
280     const base::Value* value() const;
281 
282    private:
283     base::ThreadChecker thread_checker_;
284     const char* command_;
285     std::unique_ptr<base::Value> value_;
286     DISALLOW_COPY_AND_ASSIGN(PendingUpdate);
287   };
288 
289   base::queue<PendingUpdate> pending_updates_;
290   const int aggregate_updates_ms_;
291 
292   // Weak factory for this object that we use for bulking up updates.
293   base::WeakPtrFactory<WebRTCInternals> weak_factory_{this};
294 };
295 
296 }  // namespace content
297 
298 #endif  // CONTENT_BROWSER_WEBRTC_WEBRTC_INTERNALS_H_
299