|  | // Copyright (c) 2013 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 CONTENT_BROWSER_WEBRTC_WEBRTC_INTERNALS_H_ | 
|  | #define CONTENT_BROWSER_WEBRTC_WEBRTC_INTERNALS_H_ | 
|  |  | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <unordered_set> | 
|  |  | 
|  | #include "base/containers/queue.h" | 
|  | #include "base/gtest_prod_util.h" | 
|  | #include "base/memory/weak_ptr.h" | 
|  | #include "base/observer_list.h" | 
|  | #include "base/process/process.h" | 
|  | #include "base/threading/thread_checker.h" | 
|  | #include "base/values.h" | 
|  | #include "content/common/content_export.h" | 
|  | #include "content/public/browser/global_routing_id.h" | 
|  | #include "content/public/browser/peer_connection_tracker_host_observer.h" | 
|  | #include "content/public/browser/render_process_host_observer.h" | 
|  | #include "media/media_buildflags.h" | 
|  | #include "mojo/public/cpp/bindings/remote.h" | 
|  | #include "services/device/public/mojom/wake_lock.mojom.h" | 
|  | #include "ui/shell_dialogs/select_file_dialog.h" | 
|  |  | 
|  | namespace media { | 
|  | class AudioDebugRecordingSession; | 
|  | } | 
|  |  | 
|  | namespace content { | 
|  |  | 
|  | class WebContents; | 
|  | class WebRtcInternalsConnectionsObserver; | 
|  | class WebRTCInternalsUIObserver; | 
|  |  | 
|  | // This is a singleton class running in the browser UI thread. | 
|  | // It collects peer connection infomation from the renderers, | 
|  | // forwards the data to WebRTCInternalsUIObserver and | 
|  | // sends data collecting commands to the renderers. | 
|  | class CONTENT_EXPORT WebRTCInternals : public PeerConnectionTrackerHostObserver, | 
|  | public RenderProcessHostObserver, | 
|  | public ui::SelectFileDialog::Listener { | 
|  | public: | 
|  | // * CreateSingletonInstance() ensures that no previous instantiation of the | 
|  | //   class was performed, then instantiates the class and returns the object. | 
|  | // * GetInstance() returns the object previously constructed using | 
|  | //   CreateSingletonInstance(). It may return null in tests. | 
|  | // * Creation is separated from access because WebRTCInternals may only be | 
|  | //   created from a context that allows blocking. If GetInstance were allowed | 
|  | //   to instantiate, as with a lazily constructed singleton, it would be | 
|  | //   difficult to guarantee that its construction is always first attempted | 
|  | //   from a context that allows it. | 
|  | static WebRTCInternals* CreateSingletonInstance(); | 
|  | static WebRTCInternals* GetInstance(); | 
|  |  | 
|  | ~WebRTCInternals() override; | 
|  |  | 
|  | // PeerConnectionTrackerHostObserver implementation. | 
|  | void OnPeerConnectionAdded(GlobalFrameRoutingId frame_id, | 
|  | int lid, | 
|  | base::ProcessId pid, | 
|  | const std::string& url, | 
|  | const std::string& rtc_configuration, | 
|  | const std::string& constraints) override; | 
|  | void OnPeerConnectionRemoved(GlobalFrameRoutingId frame_id, int lid) override; | 
|  | void OnPeerConnectionUpdated(GlobalFrameRoutingId frame_id, | 
|  | int lid, | 
|  | const std::string& type, | 
|  | const std::string& value) override; | 
|  | void OnAddStandardStats(GlobalFrameRoutingId frame_id, | 
|  | int lid, | 
|  | base::Value value) override; | 
|  | void OnAddLegacyStats(GlobalFrameRoutingId frame_id, | 
|  | int lid, | 
|  | base::Value value) override; | 
|  | void OnGetUserMedia(GlobalFrameRoutingId frame_id, | 
|  | base::ProcessId pid, | 
|  | const std::string& origin, | 
|  | bool audio, | 
|  | bool video, | 
|  | const std::string& audio_constraints, | 
|  | const std::string& video_constraints) override; | 
|  |  | 
|  | // Methods for adding or removing WebRTCInternalsUIObserver. | 
|  | void AddObserver(WebRTCInternalsUIObserver* observer); | 
|  | void RemoveObserver(WebRTCInternalsUIObserver* observer); | 
|  |  | 
|  | // Methods for adding or removing WebRtcInternalsConnectionsObserver. | 
|  | // |observer| is notified when there is a change in the count of active WebRTC | 
|  | // connections. | 
|  | void AddConnectionsObserver(WebRtcInternalsConnectionsObserver* observer); | 
|  | void RemoveConnectionsObserver(WebRtcInternalsConnectionsObserver* observer); | 
|  |  | 
|  | // Sends all update data to |observer|. | 
|  | void UpdateObserver(WebRTCInternalsUIObserver* observer); | 
|  |  | 
|  | // Enables or disables diagnostic audio recordings for debugging purposes. | 
|  | void EnableAudioDebugRecordings(content::WebContents* web_contents); | 
|  | void DisableAudioDebugRecordings(); | 
|  |  | 
|  | bool IsAudioDebugRecordingsEnabled() const; | 
|  | const base::FilePath& GetAudioDebugRecordingsFilePath() const; | 
|  |  | 
|  | // Enables or disables diagnostic event log. | 
|  | void EnableLocalEventLogRecordings(content::WebContents* web_contents); | 
|  | void DisableLocalEventLogRecordings(); | 
|  |  | 
|  | bool IsEventLogRecordingsEnabled() const; | 
|  | bool CanToggleEventLogRecordings() const; | 
|  |  | 
|  | int num_connected_connections() const { return num_connected_connections_; } | 
|  |  | 
|  | protected: | 
|  | // Constructor/Destructor are protected to allow tests to derive from the | 
|  | // class and do per-instance testing without having to use the global | 
|  | // instance. | 
|  | // The default ctor sets |aggregate_updates_ms| to 500ms. | 
|  | WebRTCInternals(); | 
|  | WebRTCInternals(int aggregate_updates_ms, bool should_block_power_saving); | 
|  |  | 
|  | mojo::Remote<device::mojom::WakeLock> wake_lock_; | 
|  |  | 
|  | private: | 
|  | FRIEND_TEST_ALL_PREFIXES(WebRtcAudioDebugRecordingsBrowserTest, | 
|  | CallWithAudioDebugRecordings); | 
|  | FRIEND_TEST_ALL_PREFIXES(WebRtcAudioDebugRecordingsBrowserTest, | 
|  | CallWithAudioDebugRecordingsEnabledThenDisabled); | 
|  | FRIEND_TEST_ALL_PREFIXES(WebRtcAudioDebugRecordingsBrowserTest, | 
|  | TwoCallsWithAudioDebugRecordings); | 
|  | FRIEND_TEST_ALL_PREFIXES(WebRtcInternalsTest, | 
|  | AudioDebugRecordingsFileSelectionCanceled); | 
|  |  | 
|  | static WebRTCInternals* g_webrtc_internals; | 
|  |  | 
|  | void SendUpdate(const std::string& event_name, base::Value event_data); | 
|  |  | 
|  | // RenderProcessHostObserver implementation. | 
|  | void RenderProcessExited(RenderProcessHost* host, | 
|  | const ChildProcessTerminationInfo& info) override; | 
|  |  | 
|  | // ui::SelectFileDialog::Listener implementation. | 
|  | void FileSelected(const base::FilePath& path, | 
|  | int index, | 
|  | void* unused_params) override; | 
|  | void FileSelectionCanceled(void* params) override; | 
|  |  | 
|  | // Called when a renderer exits (including crashes). | 
|  | void OnRendererExit(int render_process_id); | 
|  |  | 
|  | // Enables diagnostic audio recordings on all render process hosts using | 
|  | // |audio_debug_recordings_file_path_|. | 
|  | void EnableAudioDebugRecordingsOnAllRenderProcessHosts(); | 
|  |  | 
|  | // Updates the number of open PeerConnections. Called when a PeerConnection | 
|  | // is stopped or removed. | 
|  | void MaybeClosePeerConnection(base::Value* record); | 
|  |  | 
|  | void MaybeMarkPeerConnectionAsConnected(base::Value* record); | 
|  | void MaybeMarkPeerConnectionAsNotConnected(base::Value* record); | 
|  |  | 
|  | // Called whenever a PeerConnection is created or stopped in order to | 
|  | // request/cancel a wake lock on suspending the current application for power | 
|  | // saving. | 
|  | void UpdateWakeLock(); | 
|  |  | 
|  | device::mojom::WakeLock* GetWakeLock(); | 
|  |  | 
|  | // Called on a timer to deliver updates to javascript. | 
|  | // We throttle and bulk together updates to avoid DOS like scenarios where | 
|  | // a page uses a lot of peerconnection instances with many event | 
|  | // notifications. | 
|  | void ProcessPendingUpdates(); | 
|  |  | 
|  | // Returns an iterator for peer_connection_data_.GetList (an end() iterator | 
|  | // if not found). | 
|  | base::CheckedContiguousIterator<base::Value> FindRecord( | 
|  | GlobalFrameRoutingId frame_id, | 
|  | int lid); | 
|  |  | 
|  | base::ObserverList<WebRTCInternalsUIObserver>::Unchecked observers_; | 
|  |  | 
|  | base::ObserverList<WebRtcInternalsConnectionsObserver> connections_observers_; | 
|  |  | 
|  | // |peer_connection_data_| is a list containing all the PeerConnection | 
|  | // updates. | 
|  | // Each item of the list represents the data for one PeerConnection, which | 
|  | // contains these fields: | 
|  | // "rid" -- the renderer id. | 
|  | // "pid" -- OS process id of the renderer that creates the PeerConnection. | 
|  | // "lid" -- local Id assigned to the PeerConnection. | 
|  | // "url" -- url of the web page that created the PeerConnection. | 
|  | // "rtcConfiguration" -- serialized rtcConfiguration object. | 
|  | // "constraints" -- serialized legacy peerconnection constraints. | 
|  | // used to initialize the PeerConnection respectively. | 
|  | // "log" -- a ListValue contains all the updates for the PeerConnection. Each | 
|  | // list item is a DictionaryValue containing "time", which is the number of | 
|  | // milliseconds since epoch as a string, and "type" and "value", both of which | 
|  | // are strings representing the event. | 
|  | base::ListValue peer_connection_data_; | 
|  |  | 
|  | // A list of getUserMedia requests. Each item is a DictionaryValue that | 
|  | // contains these fields: | 
|  | // "rid" -- the renderer id. | 
|  | // "pid" -- proceddId of the renderer. | 
|  | // "origin" -- the security origin of the request. | 
|  | // "audio" -- the serialized audio constraints if audio is requested. | 
|  | // "video" -- the serialized video constraints if video is requested. | 
|  | base::ListValue get_user_media_requests_; | 
|  |  | 
|  | // For managing select file dialog. | 
|  | scoped_refptr<ui::SelectFileDialog> select_file_dialog_; | 
|  | enum class SelectionType { | 
|  | kRtcEventLogs, | 
|  | kAudioDebugRecordings | 
|  | } selection_type_; | 
|  |  | 
|  | // Diagnostic audio recording state. | 
|  | base::FilePath audio_debug_recordings_file_path_; | 
|  | std::unique_ptr<media::AudioDebugRecordingSession> | 
|  | audio_debug_recording_session_; | 
|  |  | 
|  | // If non-empty, WebRTC (local) event logging should be enabled using this | 
|  | // path, and may not be turned off, except by restarting the browser. | 
|  | const base::FilePath command_line_derived_logging_path_; | 
|  |  | 
|  | // Diagnostic event log recording state. These are meaningful only when | 
|  | // |command_line_derived_logging_path_| is empty. | 
|  | bool event_log_recordings_; | 
|  | base::FilePath event_log_recordings_file_path_; | 
|  |  | 
|  | // While |num_connected_connections_| is greater than zero, request a wake | 
|  | // lock service. This prevents the application from being suspended while | 
|  | // remoting. | 
|  | int num_connected_connections_; | 
|  | const bool should_block_power_saving_; | 
|  |  | 
|  | // Set of render process hosts that |this| is registered as an observer on. | 
|  | std::unordered_set<int> render_process_id_set_; | 
|  |  | 
|  | // Used to bulk up updates that we send to javascript. | 
|  | // The class owns the value/dictionary and command name of an update. | 
|  | // For each update, a PendingUpdate is stored in the |pending_updates_| queue | 
|  | // and deleted as soon as the update has been delivered. | 
|  | // The class is moveble and not copyable to avoid copying while still allowing | 
|  | // us to use an stl container without needing scoped_ptr or similar. | 
|  | // The class is single threaded, so all operations must occur on the same | 
|  | // thread. | 
|  | class PendingUpdate { | 
|  | public: | 
|  | PendingUpdate(const std::string& event_name, base::Value event_data); | 
|  | PendingUpdate(PendingUpdate&& other); | 
|  | ~PendingUpdate(); | 
|  |  | 
|  | const std::string& event_name() const; | 
|  | const base::Value* event_data() const; | 
|  |  | 
|  | private: | 
|  | base::ThreadChecker thread_checker_; | 
|  | const std::string event_name_; | 
|  | base::Value event_data_; | 
|  | DISALLOW_COPY_AND_ASSIGN(PendingUpdate); | 
|  | }; | 
|  |  | 
|  | base::queue<PendingUpdate> pending_updates_; | 
|  | const int aggregate_updates_ms_; | 
|  |  | 
|  | // Weak factory for this object that we use for bulking up updates. | 
|  | base::WeakPtrFactory<WebRTCInternals> weak_factory_{this}; | 
|  | }; | 
|  |  | 
|  | }  // namespace content | 
|  |  | 
|  | #endif  // CONTENT_BROWSER_WEBRTC_WEBRTC_INTERNALS_H_ |