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