// Copyright 2017 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_EVENT_LOG_MANAGER_COMMON_H_ #define CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_EVENT_LOG_MANAGER_COMMON_H_ #include <memory> #include <optional> #include <string> #include "base/files/file_path.h" #include "base/time/time.h" #include "build/build_config.h" #include "ipc/ipc_message.h" class Profile; namespace content { class BrowserContext; } // namespace content namespace webrtc_event_logging { // This file is intended for: // 1. Code shared between WebRtcEventLogManager, WebRtcLocalEventLogManager // and WebRtcRemoteEventLogManager. // 2. Code specific to either of the above classes, but which also needs // to be seen by unit tests (such as constants). extern const size_t kWebRtcEventLogManagerUnlimitedFileSize; extern const size_t kDefaultMaxLocalLogFileSizeBytes; extern const size_t kMaxNumberLocalWebRtcEventLogFiles; extern const size_t kMaxRemoteLogFileSizeBytes; extern const int kMaxOutputPeriodMs; // Maximum size for a response from Crash, which is the upload ID. extern const size_t kWebRtcEventLogMaxUploadIdBytes; // The number of digits required to encode a remote-bound log ID. extern const size_t kWebRtcEventLogIdLength; // Min/max legal web-app IDs. extern const size_t kMinWebRtcEventLogWebAppId; extern const size_t kMaxWebRtcEventLogWebAppId; // Sentinel value, guaranteed not to fall inside the range of min-max valid IDs. extern const size_t kInvalidWebRtcEventLogWebAppId; // Limit over the number of concurrently active (currently being written to // disk) remote-bound log files. This limits IO operations, and so it is // applied globally (all browser contexts are limited together). extern const size_t kMaxActiveRemoteBoundWebRtcEventLogs; // Limit over the number of pending logs (logs stored on disk and awaiting to // be uploaded to a remote server). This limit avoids excessive storage. If a // user chooses to have multiple profiles (and hence browser contexts) on a // system, it is assumed that the user has enough storage to accommodate // the increased storage consumption that comes with it. Therefore, this // limit is applied per browser context. extern const size_t kMaxPendingRemoteBoundWebRtcEventLogs; // Max number of history files that may be kept; after this number is exceeded, // the oldest logs should be pruned. extern const size_t kMaxWebRtcEventLogHistoryFiles; // Overhead incurred by GZIP due to its header and footer. extern const size_t kGzipOverheadBytes; // Remote-bound log files' names will be of the format: // [prefix]_[web_app_id]_[log_id].[ext] // Where: // * |prefix| is equal to kRemoteBoundWebRtcEventLogFileNamePrefix. // * |web_app_id| is a number between kMinWebRtcEventLogWebAppId and // kMaxWebRtcEventLogWebAppId, with zero padding. // * |log_id| is composed of 32 random characters from '0'-'9' and 'A'-'F'. // * |ext| is the extension determined by the used LogCompressor::Factory, // which will be either kWebRtcEventLogUncompressedExtension or // kWebRtcEventLogGzippedExtension. extern const char kRemoteBoundWebRtcEventLogFileNamePrefix[]; extern const base::FilePath::CharType kWebRtcEventLogUncompressedExtension[]; extern const base::FilePath::CharType kWebRtcEventLogGzippedExtension[]; // Logs themselves are kept on disk for kRemoteBoundWebRtcEventLogsMaxRetention, // or until uploaded. Smaller history files are kept for a longer time, allowing // Chrome to display on chrome://webrtc-logs/ that these files were captured // and later uploaded. extern const base::FilePath::CharType kWebRtcEventLogHistoryExtension[]; // Remote-bound event logs will not be uploaded if the time since their last // modification (meaning the time when they were completed) exceeds this value. // Such expired files will be purged from disk when examined. extern const base::TimeDelta kRemoteBoundWebRtcEventLogsMaxRetention; // These are made globally visible so that unit tests may check for them. extern const char kStartRemoteLoggingFailureAlreadyLogging[]; extern const char kStartRemoteLoggingFailureDeadRenderProcessHost[]; extern const char kStartRemoteLoggingFailureFeatureDisabled[]; extern const char kStartRemoteLoggingFailureFileCreationError[]; extern const char kStartRemoteLoggingFailureFilePathUsedHistory[]; extern const char kStartRemoteLoggingFailureFilePathUsedLog[]; extern const char kStartRemoteLoggingFailureIllegalWebAppId[]; extern const char kStartRemoteLoggingFailureLoggingDisabledBrowserContext[]; extern const char kStartRemoteLoggingFailureMaxSizeTooLarge[]; extern const char kStartRemoteLoggingFailureMaxSizeTooSmall[]; extern const char kStartRemoteLoggingFailureNoAdditionalActiveLogsAllowed[]; extern const char kStartRemoteLoggingFailureOutputPeriodMsTooLarge[]; extern const char kStartRemoteLoggingFailureUnknownOrInactivePeerConnection[]; extern const char kStartRemoteLoggingFailureUnlimitedSizeDisallowed[]; // Values for the histogram for the result of the API call to collect // a WebRTC event log. // Must match the numbering of WebRtcEventLoggingApiEnum in enums.xml. // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class WebRtcEventLoggingApiUma { … }; void UmaRecordWebRtcEventLoggingApi(WebRtcEventLoggingApiUma result); // Values for the histogram for the result of the upload of a WebRTC event log. // Must match the numbering of WebRtcEventLoggingUploadEnum in enums.xml. // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class WebRtcEventLoggingUploadUma { … }; void UmaRecordWebRtcEventLoggingUpload(WebRtcEventLoggingUploadUma result); // Success is signalled by 0. // All negative values signal errors. // Positive values are not used. void UmaRecordWebRtcEventLoggingNetErrorType(int net_error); // For a given Chrome session, this is a unique key for PeerConnections. // It's not, however, unique between sessions (after Chrome is restarted). struct WebRtcEventLogPeerConnectionKey { … }; // Sentinel value for an unknown BrowserContext. extern const WebRtcEventLogPeerConnectionKey::BrowserContextId kNullBrowserContextId; // Holds housekeeping information about log files. struct WebRtcLogFileInfo { … }; // An observer for notifications of local log files being started/stopped, and // the paths which will be used for these logs. class WebRtcLocalEventLogsObserver { … }; // An observer for notifications of remote-bound log files being // started/stopped. The start event would likely only interest unit tests // (because it exposes the randomized filename to them). The stop event is of // general interest, because it would often mean that WebRTC can stop sending // us event logs for this peer connection. // Some cases where OnRemoteLogStopped would be called include: // 1. The PeerConnection has become inactive. // 2. The file's maximum size has been reached. // 3. Any type of error while writing to the file. class WebRtcRemoteEventLogsObserver { … }; // Writes a log to a file while observing a maximum size. class LogFileWriter { … }; // Produces LogFileWriter instances that perform no compression. class BaseLogFileWriterFactory : public LogFileWriter::Factory { … }; // Interface for a class that provides compression of a stream, while attempting // to observe a limit on the size. // // One should note that: // * For compressors that use a footer, to guarantee proper decompression, // the footer must be written to the file. // * In such a case, usually, nothing can be omitted from the file, or the // footer's CRC (if used) would be wrong. // * Determining a string's size pre-compression, without performing the actual // compression, is heuristic in nature. // // Therefore, compression might terminate (FULL) earlier than it // must, or even in theory (which we attempt to avoid in practice) exceed the // size allowed it, in which case the file will be discarded (ERROR). class LogCompressor { … }; // Estimates the compressed size, without performing compression (except in // unit tests, where performance is of lesser importance). // This interface allows unit tests to simulate specific cases, such as // over/under-estimation, and show that the code using the LogCompressor // deals with them correctly. (E.g., if the estimation expects the compression // to not go over-budget, but then it does.) // The estimator is expected to be stateful. That is, the order of calls to // EstimateCompressedSize() should correspond to the order of calls // to Compress(). class CompressedSizeEstimator { … }; // Provides a conservative estimation of the number of bytes required to // compress a string using GZIP. This estimation is not expected to ever // be overly optimistic, but the code using it should nevertheless be prepared // to deal with that theoretical possibility. class DefaultGzippedSizeEstimator : public CompressedSizeEstimator { … }; // Interface for producing LogCompressorGzip objects. class GzipLogCompressorFactory : public LogCompressor::Factory { … }; // Produces LogFileWriter instances that perform compression using GZIP. class GzippedLogFileWriterFactory : public LogFileWriter::Factory { … }; // Create a random identifier of 32 hexadecimal (uppercase) characters. std::string CreateWebRtcEventLogId(); // Translate a BrowserContext into an ID. This lets us associate PeerConnections // with BrowserContexts, while making sure that we never call the // BrowserContext's methods outside of the UI thread (because we can't call them // at all without a cast that would alert us to the danger). WebRtcEventLogPeerConnectionKey::BrowserContextId GetBrowserContextId( const content::BrowserContext* browser_context); // Fetches the BrowserContext associated with the render process ID, then // returns its BrowserContextId. (If the render process has already died, // it would have no BrowserContext associated, so the ID associated with a // null BrowserContext will be returned.) WebRtcEventLogPeerConnectionKey::BrowserContextId GetBrowserContextId( int render_process_id); // Given a BrowserContext's directory, return the path to the directory where // we store the pending remote-bound logs associated with this BrowserContext. // This function may be called on any task queue. base::FilePath GetRemoteBoundWebRtcEventLogsDir( const base::FilePath& browser_context_dir); // Produce the path to a remote-bound WebRTC event log file with the given // log ID, web-app ID and extension, in the given directory. base::FilePath WebRtcEventLogPath( const base::FilePath& remote_logs_dir, const std::string& log_id, size_t web_app_id, const base::FilePath::StringPieceType& extension); // Checks whether the path/filename would be a valid reference to a remote-bound // even log. These functions do not examine the file's content or its extension. bool IsValidRemoteBoundLogFilename(const std::string& filename); bool IsValidRemoteBoundLogFilePath(const base::FilePath& path); // Given WebRTC event log's path, return the path to the history file that // is, or would be, associated with it. base::FilePath GetWebRtcEventLogHistoryFilePath(const base::FilePath& path); // Attempts to extract the local ID from the file's path. Returns the empty // string in case of an error. std::string ExtractRemoteBoundWebRtcEventLogLocalIdFromPath( const base::FilePath& path); // Attempts to extract the web-app ID from the file's path. // Returns kInvalidWebRtcEventLogWebAppId in case of an error. size_t ExtractRemoteBoundWebRtcEventLogWebAppIdFromPath( const base::FilePath& path); // Used to determine the default value for the policy controlling event logging. bool DoesProfileDefaultToLoggingEnabled(const Profile* const profile); } // namespace webrtc_event_logging #endif // CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_EVENT_LOG_MANAGER_COMMON_H_