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