Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/media/webrtc_log_uploader.h" | 5 #include "chrome/browser/media/webrtc_log_uploader.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/files/file_enumerator.h" | 8 #include "base/files/file_enumerator.h" |
| 9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 const uint32 kIntermediateCompressionBufferBytes = 256 * 1024; // 256 KB | 29 const uint32 kIntermediateCompressionBufferBytes = 256 * 1024; // 256 KB |
| 30 const int kLogListLimitLines = 50; | 30 const int kLogListLimitLines = 50; |
| 31 | 31 |
| 32 const char kUploadURL[] = "https://clients2.google.com/cr/report"; | 32 const char kUploadURL[] = "https://clients2.google.com/cr/report"; |
| 33 const char kUploadContentType[] = "multipart/form-data"; | 33 const char kUploadContentType[] = "multipart/form-data"; |
| 34 const char kMultipartBoundary[] = | 34 const char kMultipartBoundary[] = |
| 35 "----**--yradnuoBgoLtrapitluMklaTelgooG--**----"; | 35 "----**--yradnuoBgoLtrapitluMklaTelgooG--**----"; |
| 36 | 36 |
| 37 const int kHttpResponseOk = 200; | 37 const int kHttpResponseOk = 200; |
| 38 | 38 |
| 39 // Adds the header section for a gzip file to the multipart |post_data|. | |
| 40 void AddMultipartFileContentHeader(std::string* post_data, | |
| 41 const std::string& content_name, | |
| 42 const std::string& file_name) { | |
| 43 post_data->append("--"); | |
| 44 post_data->append(kMultipartBoundary); | |
| 45 post_data->append("\r\nContent-Disposition: form-data; name=\""); | |
| 46 post_data->append(content_name); | |
| 47 post_data->append("\"; filename=\""); | |
| 48 post_data->append(file_name); | |
| 49 post_data->append("\"\r\nContent-Type: application/gzip\r\n\r\n"); | |
| 50 } | |
| 51 | |
| 52 // Adds |compressed_log| to |post_data|. | |
| 53 void AddLogData(std::string* post_data, | |
| 54 const std::vector<uint8>& compressed_log) { | |
| 55 AddMultipartFileContentHeader(post_data, "webrtc_log", "webrtc_log.gz"); | |
| 56 post_data->append(reinterpret_cast<const char*>(&compressed_log[0]), | |
| 57 compressed_log.size()); | |
| 58 post_data->append("\r\n"); | |
| 59 } | |
| 60 | |
| 61 // Adds the RTP dump data to |post_data|. | |
| 62 void AddRtpDumpData(std::string* post_data, | |
| 63 const std::string& name, | |
| 64 const std::string& dump_data) { | |
| 65 AddMultipartFileContentHeader(post_data, name, name + ".gz"); | |
|
vrk (LEFT CHROMIUM)
2014/05/28 23:55:07
nit: I'd suggest you remove the |file_name| parame
| |
| 66 post_data->append(dump_data.data(), dump_data.size()); | |
| 67 post_data->append("\r\n"); | |
| 68 } | |
| 69 | |
| 39 } // namespace | 70 } // namespace |
| 40 | 71 |
| 72 WebRtcRtpDumpDescription::WebRtcRtpDumpDescription(const std::string& name, | |
| 73 const base::FilePath& path) | |
| 74 : name(name), path(path) { | |
| 75 } | |
| 76 | |
| 41 WebRtcLogUploadDoneData::WebRtcLogUploadDoneData() {} | 77 WebRtcLogUploadDoneData::WebRtcLogUploadDoneData() {} |
| 42 | 78 |
| 43 WebRtcLogUploadDoneData::~WebRtcLogUploadDoneData() {} | 79 WebRtcLogUploadDoneData::~WebRtcLogUploadDoneData() {} |
| 44 | 80 |
| 45 WebRtcLogUploader::WebRtcLogUploader() | 81 WebRtcLogUploader::WebRtcLogUploader() |
| 46 : log_count_(0), | 82 : log_count_(0), |
| 47 post_data_(NULL), | 83 post_data_(NULL), |
| 48 shutting_down_(false) { | 84 shutting_down_(false) { |
| 49 file_thread_checker_.DetachFromThread(); | 85 file_thread_checker_.DetachFromThread(); |
| 50 } | 86 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 62 DCHECK(!shutting_down_); | 98 DCHECK(!shutting_down_); |
| 63 int response_code = source->GetResponseCode(); | 99 int response_code = source->GetResponseCode(); |
| 64 UploadDoneDataMap::iterator it = upload_done_data_.find(source); | 100 UploadDoneDataMap::iterator it = upload_done_data_.find(source); |
| 65 if (it != upload_done_data_.end()) { | 101 if (it != upload_done_data_.end()) { |
| 66 // The log path can be empty here if we failed getting it before. We still | 102 // The log path can be empty here if we failed getting it before. We still |
| 67 // upload the log if that's the case. | 103 // upload the log if that's the case. |
| 68 std::string report_id; | 104 std::string report_id; |
| 69 if (response_code == kHttpResponseOk && | 105 if (response_code == kHttpResponseOk && |
| 70 source->GetResponseAsString(&report_id) && | 106 source->GetResponseAsString(&report_id) && |
| 71 !it->second.log_path.empty()) { | 107 !it->second.log_path.empty()) { |
| 108 // TODO(jiayl): Add the RTP dump records to chrome://webrtc-logs. | |
| 72 base::FilePath log_list_path = | 109 base::FilePath log_list_path = |
| 73 WebRtcLogList::GetWebRtcLogListFileForDirectory(it->second.log_path); | 110 WebRtcLogList::GetWebRtcLogListFileForDirectory(it->second.log_path); |
| 74 content::BrowserThread::PostTask( | 111 content::BrowserThread::PostTask( |
| 75 content::BrowserThread::FILE, | 112 content::BrowserThread::FILE, |
| 76 FROM_HERE, | 113 FROM_HERE, |
| 77 base::Bind(&WebRtcLogUploader::AddUploadedLogInfoToUploadListFile, | 114 base::Bind(&WebRtcLogUploader::AddUploadedLogInfoToUploadListFile, |
| 78 base::Unretained(this), | 115 base::Unretained(this), |
| 79 log_list_path, | 116 log_list_path, |
| 80 it->second.local_log_id, | 117 it->second.local_log_id, |
| 81 report_id)); | 118 report_id)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 base::FilePath log_list_path = | 169 base::FilePath log_list_path = |
| 133 WebRtcLogList::GetWebRtcLogListFileForDirectory( | 170 WebRtcLogList::GetWebRtcLogListFileForDirectory( |
| 134 upload_done_data.log_path); | 171 upload_done_data.log_path); |
| 135 AddLocallyStoredLogInfoToUploadListFile(log_list_path, local_log_id); | 172 AddLocallyStoredLogInfoToUploadListFile(log_list_path, local_log_id); |
| 136 } | 173 } |
| 137 | 174 |
| 138 WebRtcLogUploadDoneData upload_done_data_with_log_id = upload_done_data; | 175 WebRtcLogUploadDoneData upload_done_data_with_log_id = upload_done_data; |
| 139 upload_done_data_with_log_id.local_log_id = local_log_id; | 176 upload_done_data_with_log_id.local_log_id = local_log_id; |
| 140 | 177 |
| 141 scoped_ptr<std::string> post_data(new std::string()); | 178 scoped_ptr<std::string> post_data(new std::string()); |
| 142 SetupMultipart(post_data.get(), compressed_log, meta_data); | 179 SetupMultipart( |
| 180 post_data.get(), compressed_log, upload_done_data.rtp_dumps, meta_data); | |
| 143 | 181 |
| 144 // If a test has set the test string pointer, write to it and skip uploading. | 182 // If a test has set the test string pointer, write to it and skip uploading. |
| 145 // Still fire the upload callback so that we can run an extension API test | 183 // Still fire the upload callback so that we can run an extension API test |
| 146 // using the test framework for that without hanging. | 184 // using the test framework for that without hanging. |
| 147 // TODO(grunell): Remove this when the api test for this feature is fully | 185 // TODO(grunell): Remove this when the api test for this feature is fully |
| 148 // implemented according to the test plan. http://crbug.com/257329. | 186 // implemented according to the test plan. http://crbug.com/257329. |
| 149 if (post_data_) { | 187 if (post_data_) { |
| 150 *post_data_ = *post_data; | 188 *post_data_ = *post_data; |
| 151 NotifyUploadDone(kHttpResponseOk, "", upload_done_data_with_log_id); | 189 NotifyUploadDone(kHttpResponseOk, "", upload_done_data_with_log_id); |
| 152 return; | 190 return; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 174 ++it) { | 212 ++it) { |
| 175 delete it->first; | 213 delete it->first; |
| 176 } | 214 } |
| 177 upload_done_data_.clear(); | 215 upload_done_data_.clear(); |
| 178 shutting_down_ = true; | 216 shutting_down_ = true; |
| 179 } | 217 } |
| 180 | 218 |
| 181 void WebRtcLogUploader::SetupMultipart( | 219 void WebRtcLogUploader::SetupMultipart( |
| 182 std::string* post_data, | 220 std::string* post_data, |
| 183 const std::vector<uint8>& compressed_log, | 221 const std::vector<uint8>& compressed_log, |
| 222 const std::vector<WebRtcRtpDumpDescription>& rtp_dumps, | |
| 184 const std::map<std::string, std::string>& meta_data) { | 223 const std::map<std::string, std::string>& meta_data) { |
| 185 #if defined(OS_WIN) | 224 #if defined(OS_WIN) |
| 186 const char product[] = "Chrome"; | 225 const char product[] = "Chrome"; |
| 187 #elif defined(OS_MACOSX) | 226 #elif defined(OS_MACOSX) |
| 188 const char product[] = "Chrome_Mac"; | 227 const char product[] = "Chrome_Mac"; |
| 189 #elif defined(OS_LINUX) | 228 #elif defined(OS_LINUX) |
| 190 #if !defined(ADDRESS_SANITIZER) | 229 #if !defined(ADDRESS_SANITIZER) |
| 191 const char product[] = "Chrome_Linux"; | 230 const char product[] = "Chrome_Linux"; |
| 192 #else | 231 #else |
| 193 const char product[] = "Chrome_Linux_ASan"; | 232 const char product[] = "Chrome_Linux_ASan"; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 210 "", post_data); | 249 "", post_data); |
| 211 | 250 |
| 212 // Add custom meta data. | 251 // Add custom meta data. |
| 213 std::map<std::string, std::string>::const_iterator it = meta_data.begin(); | 252 std::map<std::string, std::string>::const_iterator it = meta_data.begin(); |
| 214 for (; it != meta_data.end(); ++it) { | 253 for (; it != meta_data.end(); ++it) { |
| 215 net::AddMultipartValueForUpload(it->first, it->second, kMultipartBoundary, | 254 net::AddMultipartValueForUpload(it->first, it->second, kMultipartBoundary, |
| 216 "", post_data); | 255 "", post_data); |
| 217 } | 256 } |
| 218 | 257 |
| 219 AddLogData(post_data, compressed_log); | 258 AddLogData(post_data, compressed_log); |
| 259 | |
| 260 // Add the rtp dumps if any. | |
| 261 for (std::vector<WebRtcRtpDumpDescription>::const_iterator it = | |
| 262 rtp_dumps.begin(); | |
| 263 it != rtp_dumps.end(); | |
| 264 ++it) { | |
| 265 if (it->path.empty() || !base::PathExists(it->path)) { | |
| 266 LOG(WARNING) << "Unexpected empty RTP dump."; | |
| 267 break; | |
| 268 } | |
| 269 | |
| 270 std::string dump_data; | |
| 271 if (base::ReadFileToString(it->path, &dump_data)) | |
| 272 AddRtpDumpData(post_data, it->name, dump_data); | |
|
vrk (LEFT CHROMIUM)
2014/05/28 23:55:07
Instead of defining "rtpdump_recv" in WebRtcLoggin
| |
| 273 } | |
| 274 | |
| 220 net::AddMultipartFinalDelimiterForUpload(kMultipartBoundary, post_data); | 275 net::AddMultipartFinalDelimiterForUpload(kMultipartBoundary, post_data); |
| 221 } | 276 } |
| 222 | 277 |
| 223 void WebRtcLogUploader::AddLogData(std::string* post_data, | |
| 224 const std::vector<uint8>& compressed_log) { | |
| 225 post_data->append("--"); | |
| 226 post_data->append(kMultipartBoundary); | |
| 227 post_data->append("\r\n"); | |
| 228 post_data->append("Content-Disposition: form-data; name=\"webrtc_log\""); | |
| 229 post_data->append("; filename=\"webrtc_log.gz\"\r\n"); | |
| 230 post_data->append("Content-Type: application/gzip\r\n\r\n"); | |
| 231 post_data->append(reinterpret_cast<const char*>(&compressed_log[0]), | |
| 232 compressed_log.size()); | |
| 233 post_data->append("\r\n"); | |
| 234 } | |
| 235 | |
| 236 void WebRtcLogUploader::CompressLog(std::vector<uint8>* compressed_log, | 278 void WebRtcLogUploader::CompressLog(std::vector<uint8>* compressed_log, |
| 237 uint8* input, | 279 uint8* input, |
| 238 uint32 input_size) { | 280 uint32 input_size) { |
| 239 PartialCircularBuffer read_pcb(input, input_size); | 281 PartialCircularBuffer read_pcb(input, input_size); |
| 240 | 282 |
| 241 z_stream stream = {0}; | 283 z_stream stream = {0}; |
| 242 int result = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, | 284 int result = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, |
| 243 // windowBits = 15 is default, 16 is added to | 285 // windowBits = 15 is default, 16 is added to |
| 244 // produce a gzip header + trailer. | 286 // produce a gzip header + trailer. |
| 245 15 + 16, | 287 15 + 16, |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 if (!success) { | 459 if (!success) { |
| 418 error_message = "Uploading failed, response code: " + | 460 error_message = "Uploading failed, response code: " + |
| 419 base::IntToString(response_code); | 461 base::IntToString(response_code); |
| 420 } | 462 } |
| 421 content::BrowserThread::PostTask( | 463 content::BrowserThread::PostTask( |
| 422 content::BrowserThread::UI, FROM_HERE, | 464 content::BrowserThread::UI, FROM_HERE, |
| 423 base::Bind(upload_done_data.callback, success, report_id, | 465 base::Bind(upload_done_data.callback, success, report_id, |
| 424 error_message)); | 466 error_message)); |
| 425 } | 467 } |
| 426 } | 468 } |
| OLD | NEW |