1 // Copyright 2017 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 CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_EVENT_LOG_MANAGER_H_ 6 #define CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_EVENT_LOG_MANAGER_H_ 7 8 #include <map> 9 #include <memory> 10 #include <utility> 11 #include <vector> 12 13 #include "base/callback.h" 14 #include "base/containers/flat_set.h" 15 #include "base/files/file_path.h" 16 #include "base/memory/scoped_refptr.h" 17 #include "base/time/clock.h" 18 #include "base/time/time.h" 19 #include "base/updateable_sequenced_task_runner.h" 20 #include "chrome/browser/media/webrtc/webrtc_event_log_manager_common.h" 21 #include "chrome/browser/media/webrtc/webrtc_event_log_manager_local.h" 22 #include "chrome/browser/media/webrtc/webrtc_event_log_manager_remote.h" 23 #include "components/prefs/pref_change_registrar.h" 24 #include "components/upload_list/upload_list.h" 25 #include "content/public/browser/render_process_host_observer.h" 26 #include "content/public/browser/webrtc_event_logger.h" 27 28 class WebRTCInternalsIntegrationBrowserTest; 29 30 namespace content { 31 class BrowserContext; 32 class NetworkConnectionTracker; 33 } // namespace content 34 35 namespace webrtc_event_logging { 36 37 // This is a singleton class running in the browser UI thread (ownership of 38 // the only instance lies in BrowserContext). It is in charge of writing WebRTC 39 // event logs to temporary files, then uploading those files to remote servers, 40 // as well as of writing the logs to files which were manually indicated by the 41 // user from the WebRTCIntenals. (A log may simulatenously be written to both, 42 // either, or none.) 43 // The only instance of this class is owned by BrowserProcessImpl. It is 44 // destroyed from ~BrowserProcessImpl(), at which point any tasks posted to the 45 // internal SequencedTaskRunner, or coming from another thread, would no longer 46 // execute. 47 class WebRtcEventLogManager final : public content::RenderProcessHostObserver, 48 public content::WebRtcEventLogger, 49 public WebRtcLocalEventLogsObserver, 50 public WebRtcRemoteEventLogsObserver { 51 public: 52 using BrowserContextId = WebRtcEventLogPeerConnectionKey::BrowserContextId; 53 54 // To turn WebRTC on and off, we go through PeerConnectionTrackerProxy. In 55 // order to make this toggling easily testable, PeerConnectionTrackerProxyImpl 56 // will send real messages to PeerConnectionTracker, whereas 57 // PeerConnectionTrackerProxyForTesting will be a mock that just makes sure 58 // the correct messages were attempted to be sent. 59 class PeerConnectionTrackerProxy { 60 public: 61 virtual ~PeerConnectionTrackerProxy() = default; 62 63 virtual void EnableWebRtcEventLogging( 64 const WebRtcEventLogPeerConnectionKey& key, 65 int output_period_ms) = 0; 66 67 virtual void DisableWebRtcEventLogging( 68 const WebRtcEventLogPeerConnectionKey& key) = 0; 69 }; 70 71 // Ensures that no previous instantiation of the class was performed, then 72 // instantiates the class and returns the object (ownership is transfered to 73 // the caller). Subsequent calls to GetInstance() will return this object, 74 // until it is destructed, at which pointer nullptr will be returned by 75 // subsequent calls. 76 static std::unique_ptr<WebRtcEventLogManager> CreateSingletonInstance(); 77 78 // Returns the object previously constructed using CreateSingletonInstance(), 79 // if it was constructed and was not yet destroyed; nullptr otherwise. 80 static WebRtcEventLogManager* GetInstance(); 81 82 // Given a BrowserContext, return the path to the directory where its 83 // remote-bound event logs are kept. 84 // Since incognito sessions don't have such a directory, an empty 85 // base::FilePath will be returned for them. 86 static base::FilePath GetRemoteBoundWebRtcEventLogsDir( 87 content::BrowserContext* browser_context); 88 89 ~WebRtcEventLogManager() override; 90 91 void EnableForBrowserContext(content::BrowserContext* browser_context, 92 base::OnceClosure reply); 93 94 void DisableForBrowserContext(content::BrowserContext* browser_context, 95 base::OnceClosure reply); 96 97 void PeerConnectionAdded(int render_process_id, 98 int lid, // Renderer-local PeerConnection ID. 99 base::OnceCallback<void(bool)> reply) override; 100 101 void PeerConnectionRemoved(int render_process_id, 102 int lid, // Renderer-local PeerConnection ID. 103 base::OnceCallback<void(bool)> reply) override; 104 105 // From the logger's perspective, we treat stopping a peer connection the 106 // same as we do its removal. Should a stopped peer connection be later 107 // removed, the removal callback will assume the value |false|. 108 void PeerConnectionStopped(int render_process_id, 109 int lid, // Renderer-local PeerConnection ID. 110 base::OnceCallback<void(bool)> reply) override; 111 112 void PeerConnectionSessionIdSet( 113 int render_process_id, 114 int lid, 115 const std::string& session_id, 116 base::OnceCallback<void(bool)> reply) override; 117 118 // The file's actual path is derived from |base_path| by adding a timestamp, 119 // the render process ID and the PeerConnection's local ID. 120 void EnableLocalLogging(const base::FilePath& base_path, 121 base::OnceCallback<void(bool)> reply) override; 122 void EnableLocalLogging(const base::FilePath& base_path, 123 size_t max_file_size_bytes, 124 base::OnceCallback<void(bool)> reply); 125 126 void DisableLocalLogging(base::OnceCallback<void(bool)> reply) override; 127 128 void OnWebRtcEventLogWrite( 129 int render_process_id, 130 int lid, // Renderer-local PeerConnection ID. 131 const std::string& message, 132 base::OnceCallback<void(std::pair<bool, bool>)> reply) override; 133 134 // Start logging a peer connection's WebRTC events to a file, which will 135 // later be uploaded to a remote server. If a reply is provided, it will be 136 // posted back to BrowserThread::UI with the log-identifier (if successful) 137 // of the created log or (if unsuccessful) the error message. 138 // See the comment in WebRtcRemoteEventLogManager::StartRemoteLogging for 139 // more details. 140 void StartRemoteLogging( 141 int render_process_id, 142 const std::string& session_id, 143 size_t max_file_size_bytes, 144 int output_period_ms, 145 size_t web_app_id, 146 base::OnceCallback<void(bool, const std::string&, const std::string&)> 147 reply); 148 149 // Clear WebRTC event logs associated with a given browser context, in a given 150 // time range (|delete_begin| inclusive, |delete_end| exclusive), then 151 // post |reply| back to the thread from which the method was originally 152 // invoked (which can be any thread). 153 void ClearCacheForBrowserContext( 154 const content::BrowserContext* browser_context, 155 const base::Time& delete_begin, 156 const base::Time& delete_end, 157 base::OnceClosure reply); 158 159 // Get the logging history (relevant only to remote-bound logs). This includes 160 // information such as when logs were captured, when they were uploaded, 161 // and what their ID in the remote server was. 162 // Must be called on the UI thread. 163 // The results to the query are posted using |reply| back to the UI thread. 164 // If |browser_context_id| is not the ID a profile for which remote-bound 165 // logging is enabled, an empty list is returned. 166 // The returned vector is sorted by capture time in ascending order. 167 void GetHistory( 168 BrowserContextId browser_context_id, 169 base::OnceCallback<void(const std::vector<UploadList::UploadInfo>&)> 170 reply); 171 172 // Set (or unset) an observer that will be informed whenever a local log file 173 // is started/stopped. The observer needs to be able to either run from 174 // anywhere. If you need the code to run on specific runners or queues, have 175 // the observer post them there. 176 // If a reply callback is given, it will be posted back to BrowserThread::UI 177 // after the observer has been set. 178 void SetLocalLogsObserver(WebRtcLocalEventLogsObserver* observer, 179 base::OnceClosure reply); 180 181 // Set (or unset) an observer that will be informed whenever a remote log file 182 // is started/stopped. Note that this refers to writing these files to disk, 183 // not for uploading them to the server. 184 // The observer needs to be able to either run from anywhere. If you need the 185 // code to run on specific runners or queues, have the observer post 186 // them there. 187 // If a reply callback is given, it will be posted back to BrowserThread::UI 188 // after the observer has been set. 189 void SetRemoteLogsObserver(WebRtcRemoteEventLogsObserver* observer, 190 base::OnceClosure reply); 191 192 private: 193 friend class WebRtcEventLogManagerTestBase; 194 friend class ::WebRTCInternalsIntegrationBrowserTest; 195 196 using PeerConnectionKey = WebRtcEventLogPeerConnectionKey; 197 198 // This bitmap allows us to track for which clients (local/remote logging) 199 // we have turned WebRTC event logging on for a given peer connection, so that 200 // we may turn it off only when the last client no longer needs it. 201 enum LoggingTarget : unsigned int { 202 kLocalLogging = 1 << 0, 203 kRemoteLogging = 1 << 1 204 }; 205 using LoggingTargetBitmap = std::underlying_type<LoggingTarget>::type; 206 207 WebRtcEventLogManager(); 208 209 bool IsRemoteLoggingAllowedForBrowserContext( 210 content::BrowserContext* browser_context) const; 211 212 // Determines the exact subclass of LogFileWriter::Factory to be used for 213 // producing remote-bound logs. 214 std::unique_ptr<LogFileWriter::Factory> CreateRemoteLogFileWriterFactory(); 215 216 // RenderProcessHostObserver implementation. 217 void RenderProcessExited( 218 content::RenderProcessHost* host, 219 const content::ChildProcessTerminationInfo& info) override; 220 void RenderProcessHostDestroyed(content::RenderProcessHost* host) override; 221 222 // RenderProcessExited() and RenderProcessHostDestroyed() treated similarly 223 // by this function. 224 void RenderProcessHostExitedDestroyed(content::RenderProcessHost* host); 225 226 // WebRtcLocalEventLogsObserver implementation: 227 void OnLocalLogStarted(PeerConnectionKey peer_connection, 228 const base::FilePath& file_path) override; 229 void OnLocalLogStopped(PeerConnectionKey peer_connection) override; 230 231 // WebRtcRemoteEventLogsObserver implementation: 232 void OnRemoteLogStarted(PeerConnectionKey key, 233 const base::FilePath& file_path, 234 int output_period_ms) override; 235 void OnRemoteLogStopped(PeerConnectionKey key) override; 236 237 void OnLoggingTargetStarted(LoggingTarget target, 238 PeerConnectionKey key, 239 int output_period_ms); 240 void OnLoggingTargetStopped(LoggingTarget target, PeerConnectionKey key); 241 242 void StartListeningForPrefChangeForBrowserContext( 243 content::BrowserContext* browser_context); 244 void StopListeningForPrefChangeForBrowserContext( 245 content::BrowserContext* browser_context); 246 247 void OnPrefChange(content::BrowserContext* browser_context); 248 249 // network_connection_tracker() is not available during instantiation; 250 // we get it when the first profile is loaded, which is also the earliest 251 // time when it could be needed. 252 // The LogFileWriter::Factory is similarly deferred, but for a different 253 // reason - it makes it easier to allow unit tests to inject their own. 254 // OnFirstBrowserContextLoaded() is on the UI thread. 255 // OnFirstBrowserContextLoadedInternal() is the task sent to |task_runner_|. 256 void OnFirstBrowserContextLoaded(); 257 void OnFirstBrowserContextLoadedInternal( 258 network::NetworkConnectionTracker* network_connection_tracker, 259 std::unique_ptr<LogFileWriter::Factory> log_file_writer_factory); 260 261 void EnableRemoteBoundLoggingForBrowserContext( 262 BrowserContextId browser_context_id, 263 const base::FilePath& browser_context_dir, 264 base::OnceClosure reply); 265 266 void DisableRemoteBoundLoggingForBrowserContext( 267 BrowserContextId browser_context_id, 268 base::OnceClosure reply); 269 270 void RemovePendingRemoteBoundLogsForNotEnabledBrowserContext( 271 BrowserContextId browser_context_id, 272 const base::FilePath& browser_context_dir, 273 base::OnceClosure reply); 274 275 void PeerConnectionAddedInternal(PeerConnectionKey key, 276 base::OnceCallback<void(bool)> reply); 277 void PeerConnectionRemovedInternal(PeerConnectionKey key, 278 base::OnceCallback<void(bool)> reply); 279 280 void PeerConnectionSessionIdSetInternal(PeerConnectionKey key, 281 const std::string& session_id, 282 base::OnceCallback<void(bool)> reply); 283 284 void EnableLocalLoggingInternal(const base::FilePath& base_path, 285 size_t max_file_size_bytes, 286 base::OnceCallback<void(bool)> reply); 287 void DisableLocalLoggingInternal(base::OnceCallback<void(bool)> reply); 288 289 void OnWebRtcEventLogWriteInternal( 290 PeerConnectionKey key, 291 const std::string& message, 292 base::OnceCallback<void(std::pair<bool, bool>)> reply); 293 294 void StartRemoteLoggingInternal( 295 int render_process_id, 296 BrowserContextId browser_context_id, 297 const std::string& session_id, 298 const base::FilePath& browser_context_dir, 299 size_t max_file_size_bytes, 300 int output_period_ms, 301 size_t web_app_id, 302 base::OnceCallback<void(bool, const std::string&, const std::string&)> 303 reply); 304 305 void ClearCacheForBrowserContextInternal(BrowserContextId browser_context_id, 306 const base::Time& delete_begin, 307 const base::Time& delete_end); 308 309 void OnClearCacheForBrowserContextDoneInternal(base::OnceClosure reply); 310 311 void GetHistoryInternal( 312 BrowserContextId browser_context_id, 313 base::OnceCallback<void(const std::vector<UploadList::UploadInfo>&)> 314 reply); 315 316 void RenderProcessExitedInternal(int render_process_id); 317 318 void SetLocalLogsObserverInternal(WebRtcLocalEventLogsObserver* observer, 319 base::OnceClosure reply); 320 321 void SetRemoteLogsObserverInternal(WebRtcRemoteEventLogsObserver* observer, 322 base::OnceClosure reply); 323 324 // Injects a fake clock, to be used by tests. For example, this could be 325 // used to inject a frozen clock, thereby allowing unit tests to know what a 326 // local log's filename would end up being. 327 void SetClockForTesting(base::Clock* clock, base::OnceClosure reply); 328 329 // Injects a PeerConnectionTrackerProxy for testing. The normal tracker proxy 330 // is used to communicate back to WebRTC whether event logging is desired for 331 // a given peer connection. Using this function, those indications can be 332 // intercepted by a unit test. 333 void SetPeerConnectionTrackerProxyForTesting( 334 std::unique_ptr<PeerConnectionTrackerProxy> pc_tracker_proxy, 335 base::OnceClosure reply); 336 337 // Injects a fake uploader, to be used by unit tests. 338 void SetWebRtcEventLogUploaderFactoryForTesting( 339 std::unique_ptr<WebRtcEventLogUploader::Factory> uploader_factory, 340 base::OnceClosure reply); 341 342 // Sets a LogFileWriter factory for remote-bound files. 343 // Only usable in tests. 344 // Must be called before the first browser context is enabled. 345 // Effective immediately. 346 void SetRemoteLogFileWriterFactoryForTesting( 347 std::unique_ptr<LogFileWriter::Factory> factory); 348 349 // It is not always feasible to check in unit tests that uploads do not occur 350 // at a certain time, because that's (sometimes) racy with the event that 351 // suppresses the upload. We therefore allow unit tests to glimpse into the 352 // black box and verify that the box is aware that it should not upload. 353 void UploadConditionsHoldForTesting(base::OnceCallback<void(bool)> callback); 354 355 // This allows unit tests that do not wish to change the task runner to still 356 // check when certain operations are finished. 357 // TODO(crbug.com/775415): Remove this and use PostNullTaskForTesting instead. 358 scoped_refptr<base::SequencedTaskRunner> GetTaskRunnerForTesting(); 359 360 void PostNullTaskForTesting(base::OnceClosure reply); 361 362 // Documented in WebRtcRemoteEventLogManager. 363 void ShutDownForTesting(base::OnceClosure reply); 364 365 static WebRtcEventLogManager* g_webrtc_event_log_manager; 366 367 // The main logic will run sequentially on this runner, on which blocking 368 // tasks are allowed. 369 scoped_refptr<base::UpdateableSequencedTaskRunner> task_runner_; 370 371 // The number of user-blocking tasks. 372 // The priority of |task_runner_| is increased to USER_BLOCKING when this is 373 // non-zero, and reduced to BEST_EFFORT when zero. 374 // This object is only to be accessed on the UI thread. 375 size_t num_user_blocking_tasks_; 376 377 // Indicates whether remote-bound logging is generally allowed, although 378 // possibly not for all profiles. This makes it possible for remote-bound to 379 // be disabled through Finch. 380 // TODO(crbug.com/775415): Remove this kill-switch. 381 const bool remote_logging_feature_enabled_; 382 383 // Observer which will be informed whenever a local log file is started or 384 // stopped. Its callbacks are called synchronously from |task_runner_|, 385 // so the observer needs to be able to either run from any (sequenced) runner. 386 WebRtcLocalEventLogsObserver* local_logs_observer_; 387 388 // Observer which will be informed whenever a remote log file is started or 389 // stopped. Its callbacks are called synchronously from |task_runner_|, 390 // so the observer needs to be able to either run from any (sequenced) runner. 391 WebRtcRemoteEventLogsObserver* remote_logs_observer_; 392 393 // Manages local-bound logs - logs stored on the local filesystem when 394 // logging has been explicitly enabled by the user. 395 WebRtcLocalEventLogManager local_logs_manager_; 396 397 // Manages remote-bound logs - logs which will be sent to a remote server. 398 // This is only possible when the appropriate Chrome policy is configured. 399 WebRtcRemoteEventLogManager remote_logs_manager_; 400 401 // Each loaded BrowserContext is mapped to a PrefChangeRegistrar, which keeps 402 // us informed about preference changes, thereby allowing as to support 403 // dynamic refresh. 404 std::map<BrowserContextId, PrefChangeRegistrar> pref_change_registrars_; 405 406 // This keeps track of which peer connections have event logging turned on 407 // in WebRTC, and for which client(s). 408 std::map<PeerConnectionKey, LoggingTargetBitmap> 409 peer_connections_with_event_logging_enabled_in_webrtc_; 410 411 // The set of RenderProcessHosts with which the manager is registered for 412 // observation. Allows us to register for each RPH only once, and get notified 413 // when it exits (cleanly or due to a crash). 414 // This object is only to be accessed on the UI thread. 415 base::flat_set<content::RenderProcessHost*> observed_render_process_hosts_; 416 417 // In production, this holds a small object that just tells WebRTC (via 418 // PeerConnectionTracker) to start/stop producing event logs for a specific 419 // peer connection. In (relevant) unit tests, a mock will be injected. 420 std::unique_ptr<PeerConnectionTrackerProxy> pc_tracker_proxy_; 421 422 // The globals network_connection_tracker() and system_request_context() are 423 // sent down to |remote_logs_manager_| with the first enabled browser context. 424 // This member must only be accessed on the UI thread. 425 bool first_browser_context_initializations_done_; 426 427 // May only be set for tests, in which case, it will be passed to 428 // |remote_logs_manager_| when (and if) produced. 429 std::unique_ptr<LogFileWriter::Factory> 430 remote_log_file_writer_factory_for_testing_; 431 432 DISALLOW_COPY_AND_ASSIGN(WebRtcEventLogManager); 433 }; 434 435 } // namespace webrtc_event_logging 436 437 #endif // CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_EVENT_LOG_MANAGER_H_ 438