1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
|
// Copyright 2013 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_LOG_UPLOADER_H_
#define CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_LOG_UPLOADER_H_
#include <stdint.h>
#include <list>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "chrome/browser/media/webrtc/webrtc_log_buffer.h"
#include "url/gurl.h"
namespace network {
class SimpleURLLoader;
}
typedef struct z_stream_s z_stream;
struct WebRtcLogPaths {
base::FilePath directory;
base::FilePath incoming_rtp_dump;
base::FilePath outgoing_rtp_dump;
};
typedef std::map<std::string, std::string> WebRtcLogMetaDataMap;
// Upload failure reasons used for UMA stats. A failure reason can be one of
// those listed here or a response code for the upload HTTP request. The
// values in this list must be less than 100 and cannot be changed.
struct WebRtcLogUploadFailureReason {
enum {
kInvalidState = 0,
kStoredLogNotFound = 1,
kNetworkError = 2,
};
};
// Changes the crash product under which text and event logs are uploaded
// to have a "_webrtc" suffix, and removes the "-webrtc" suffix from the
// crash version field.
// eg, when enabled: product: "Chrome_Mac_webrtc", version: "121.0.6151.0"
// when disabled: product: "Chrome_Mac", version: "121.0.6151.0-webrtc"
BASE_DECLARE_FEATURE(kWebRTCLogUploadSuffix);
// Returns the product string to use for crash log uploads.
std::string GetLogUploadProduct();
// Returns the version string to use for crash log uploads.
std::string GetLogUploadVersion();
// WebRtcLogUploader uploads WebRTC logs, keeps count of how many logs have
// been started and denies further logs if a limit is reached. It also adds
// the timestamp and report ID of the uploded log to a text file. There must
// only be one object of this type.
class WebRtcLogUploader {
public:
typedef base::OnceCallback<void(bool, const std::string&)>
GenericDoneCallback;
typedef base::OnceCallback<void(bool is_upload_successful,
const std::string& report_id,
const std::string& error_message)>
UploadDoneCallback;
static constexpr char kLogUploadDisabledMsg[] =
"WebRtc text log upload is disabled";
// Used when uploading is done to perform post-upload actions. |paths| is
// also used pre-upload.
struct UploadDoneData {
UploadDoneData();
UploadDoneData(UploadDoneData&& other);
~UploadDoneData();
WebRtcLogPaths paths;
UploadDoneCallback callback;
std::string local_log_id;
// Used for statistics. See |WebRtcLoggingHandlerHost::web_app_id_|.
int web_app_id;
};
static WebRtcLogUploader* GetInstance();
WebRtcLogUploader();
WebRtcLogUploader(const WebRtcLogUploader&) = delete;
WebRtcLogUploader& operator=(const WebRtcLogUploader&) = delete;
~WebRtcLogUploader();
// Returns true is number of logs limit is not reached yet. Increases log
// count if true is returned. Must be called before UploadLog().
bool ApplyForStartLogging();
// Notifies that logging has stopped and that the log should not be uploaded.
// Decreases log count. May only be called if permission to log has been
// granted by calling ApplyForStartLogging() and getting true in return.
// After this function has been called, a new permission must be granted.
// Call either this function or LoggingStoppedDoUpload().
void LoggingStoppedDontUpload();
// Notifies that that logging has stopped. Stores text logs in gz file.
// Logs are uploaded if allowed by policy. Decreases log count.
// May only be called if permission to log has been
// granted by calling ApplyForStartLogging() and getting true in return. After
// this function has been called, a new permission must be granted. Call
// either this function or LoggingStoppedDontUpload().
// |upload_done_data.local_log_id| is set and used internally and should be
// left empty.
void OnLoggingStopped(std::unique_ptr<WebRtcLogBuffer> log_buffer,
std::unique_ptr<WebRtcLogMetaDataMap> meta_data,
UploadDoneData upload_done_data,
bool is_text_log_upload_allowed);
// Uploads a previously stored log (see LoggingStoppedDoStore()).
void UploadStoredLog(UploadDoneData upload_data);
// Similarly to LoggingStoppedDoUpload(), we store the log in compressed
// format on disk but add the option to specify a unique |log_id| for later
// identification and potential upload.
void LoggingStoppedDoStore(const WebRtcLogPaths& log_paths,
const std::string& log_id,
std::unique_ptr<WebRtcLogBuffer> log_buffer,
std::unique_ptr<WebRtcLogMetaDataMap> meta_data,
GenericDoneCallback done_callback);
// Cancels URL fetcher operation by deleting all URL fetchers. This cancels
// any pending uploads and releases SystemURLRequestContextGetter references.
// Sets |shutdown_| which prevents new fetchers from being created.
void Shutdown();
// For testing purposes. If called, the multipart will not be uploaded, but
// written to |post_data_| instead.
void OverrideUploadWithBufferForTesting(std::string* post_data) {
DCHECK((post_data && !post_data_) || (!post_data && post_data_));
post_data_ = post_data;
}
// For testing purposes.
void SetUploadUrlForTesting(const GURL& url) {
DCHECK((!url.is_empty() && upload_url_for_testing_.is_empty()) ||
(url.is_empty() && !upload_url_for_testing_.is_empty()));
upload_url_for_testing_ = url;
}
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner()
const {
return background_task_runner_;
}
void NotifyUploadDisabled(UploadDoneData upload_done_data);
private:
// Allow the test class to call AddLocallyStoredLogInfoToUploadListFile.
friend class WebRtcLogUploaderTest;
FRIEND_TEST_ALL_PREFIXES(WebRtcLogUploaderTest,
AddLocallyStoredLogInfoToUploadListFile);
FRIEND_TEST_ALL_PREFIXES(WebRtcLogUploaderTest,
AddUploadedLogInfoToUploadListFile);
// Sets up a multipart body to be uploaded. The body is produced according
// to RFC 2046.
void SetupMultipart(std::string* post_data,
const std::string& compressed_log,
const base::FilePath& incoming_rtp_dump,
const base::FilePath& outgoing_rtp_dump,
const std::map<std::string, std::string>& meta_data);
std::string CompressLog(WebRtcLogBuffer* buffer);
void UploadCompressedLog(UploadDoneData upload_done_data,
std::unique_ptr<std::string> post_data);
void DecreaseLogCount();
// Must be called on the FILE thread.
void WriteCompressedLogToFile(const std::string& compressed_log,
const base::FilePath& log_file_path);
void PrepareMultipartPostData(const std::string& compressed_log,
std::unique_ptr<WebRtcLogMetaDataMap> meta_data,
UploadDoneData upload_done_data);
// Append information (upload time, report ID and local ID) about a log to a
// log list file, limited to |kLogListLimitLines| entries. This list is used
// for viewing the logs under chrome://webrtc-logs, see WebRtcLogUploadList.
// The list has the format:
// [upload_time],[report_id],[local_id],[capture_time]
// Each line represents a log.
// * |upload_time| is the time when the log was uploaded in Unix time.
// * |report_id| is the ID reported back by the server.
// * |local_id| is the ID for the locally stored log. It's the time stored
// in Unix time and it's also used as file name.
// * |capture_time| is the Unix time when the log was captured.
// AddLocallyStoredLogInfoToUploadListFile() will first be called.
// |upload_time| and |report_id| will be left empty in the entry written to
// the list file. If uploading is successful,
// AddUploadedLogInfoToUploadListFile() will be called and those empty fields
// will be filled out.
// Must be called on the FILE thread.
void AddLocallyStoredLogInfoToUploadListFile(
const base::FilePath& upload_list_path,
const std::string& local_log_id);
static void AddUploadedLogInfoToUploadListFile(
const base::FilePath& upload_list_path,
const std::string& local_log_id,
const std::string& report_id);
// Notifies users that upload has completed and logs UMA stats.
// |response_code| not having a value means that no response code could be
// retrieved, in which case |network_error_code| should be something other
// than net::OK.
void NotifyUploadDoneAndLogStats(std::optional<int> response_code,
int network_error_code,
const std::string& report_id,
UploadDoneData upload_done_data);
using SimpleURLLoaderList =
std::list<std::unique_ptr<network::SimpleURLLoader>>;
void OnSimpleLoaderComplete(SimpleURLLoaderList::iterator it,
UploadDoneData upload_done_data,
std::unique_ptr<std::string> response_body);
SEQUENCE_CHECKER(main_sequence_checker_);
// Main sequence where this class was constructed.
scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
// Background sequence where we run background, potentially blocking,
// operations.
scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
// Keeps track of number of currently open logs. Must only be accessed from
// the main sequence.
int log_count_ = 0;
// For testing purposes, see OverrideUploadWithBufferForTesting. Only accessed
// on the background sequence
raw_ptr<std::string> post_data_ = nullptr;
// For testing purposes.
GURL upload_url_for_testing_;
// Only accessed on the main sequence.
SimpleURLLoaderList pending_uploads_;
// When true, don't create new URL loaders.
bool shutdown_ = false;
};
#endif // CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_LOG_UPLOADER_H_
|