blob: f70d6adacd0b521245213e8e749ba84cf45ec277 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// 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 <string>
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/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,
};
};
// 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, const std::string&, const std::string&)>
UploadDoneCallback;
// 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;
};
WebRtcLogUploader();
~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 and that the log should 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 LoggingStoppedDontUpload().
// |upload_done_data.local_log_id| is set and used internally and should be
// left empty.
void LoggingStoppedDoUpload(std::unique_ptr<WebRtcLogBuffer> log_buffer,
std::unique_ptr<WebRtcLogMetaDataMap> meta_data,
UploadDoneData upload_done_data);
// 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_;
}
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(base::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
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;
DISALLOW_COPY_AND_ASSIGN(WebRtcLogUploader);
};
#endif // CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_LOG_UPLOADER_H_