| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 #include <utility> | 4 #include <utility> |
| 5 | 5 |
| 6 #include "base/bind.h" | 6 #include "base/bind.h" |
| 7 #include "base/files/file_util.h" | 7 #include "base/files/file_util.h" |
| 8 #include "base/json/json_writer.h" | 8 #include "base/json/json_writer.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/strings/pattern.h" | 10 #include "base/strings/pattern.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 class StringTraceDataEndpoint : public TraceDataEndpoint { | 22 class StringTraceDataEndpoint : public TraceDataEndpoint { |
| 23 public: | 23 public: |
| 24 typedef base::Callback<void(std::unique_ptr<const base::DictionaryValue>, | 24 typedef base::Callback<void(std::unique_ptr<const base::DictionaryValue>, |
| 25 base::RefCountedString*)> | 25 base::RefCountedString*)> |
| 26 CompletionCallback; | 26 CompletionCallback; |
| 27 | 27 |
| 28 explicit StringTraceDataEndpoint(CompletionCallback callback) | 28 explicit StringTraceDataEndpoint(CompletionCallback callback) |
| 29 : completion_callback_(callback) {} | 29 : completion_callback_(callback) {} |
| 30 | 30 |
| 31 void ReceiveTraceFinalContents( | 31 void ReceiveTraceFinalContents( |
| 32 std::unique_ptr<const base::DictionaryValue> metadata, | 32 std::unique_ptr<const base::DictionaryValue> metadata) override { |
| 33 const std::string& contents) override { | 33 std::string tmp = trace_.str(); |
| 34 std::string tmp = contents; | 34 trace_.str(""); |
| 35 trace_.clear(); |
| 35 scoped_refptr<base::RefCountedString> str = | 36 scoped_refptr<base::RefCountedString> str = |
| 36 base::RefCountedString::TakeString(&tmp); | 37 base::RefCountedString::TakeString(&tmp); |
| 37 | 38 |
| 38 BrowserThread::PostTask( | 39 BrowserThread::PostTask( |
| 39 BrowserThread::UI, FROM_HERE, | 40 BrowserThread::UI, FROM_HERE, |
| 40 base::Bind(completion_callback_, base::Passed(std::move(metadata)), | 41 base::Bind(completion_callback_, base::Passed(std::move(metadata)), |
| 41 base::RetainedRef(str))); | 42 base::RetainedRef(str))); |
| 42 } | 43 } |
| 43 | 44 |
| 45 void ReceiveTraceChunk(const std::string& chunk) override { trace_ << chunk; } |
| 46 |
| 44 private: | 47 private: |
| 45 ~StringTraceDataEndpoint() override {} | 48 ~StringTraceDataEndpoint() override {} |
| 46 | 49 |
| 47 CompletionCallback completion_callback_; | 50 CompletionCallback completion_callback_; |
| 51 std::ostringstream trace_; |
| 48 | 52 |
| 49 DISALLOW_COPY_AND_ASSIGN(StringTraceDataEndpoint); | 53 DISALLOW_COPY_AND_ASSIGN(StringTraceDataEndpoint); |
| 50 }; | 54 }; |
| 51 | 55 |
| 52 class FileTraceDataEndpoint : public TraceDataEndpoint { | 56 class FileTraceDataEndpoint : public TraceDataEndpoint { |
| 53 public: | 57 public: |
| 54 explicit FileTraceDataEndpoint(const base::FilePath& trace_file_path, | 58 explicit FileTraceDataEndpoint(const base::FilePath& trace_file_path, |
| 55 const base::Closure& callback) | 59 const base::Closure& callback) |
| 56 : file_path_(trace_file_path), | 60 : file_path_(trace_file_path), |
| 57 completion_callback_(callback), | 61 completion_callback_(callback), |
| 58 file_(NULL) {} | 62 file_(NULL) {} |
| 59 | 63 |
| 60 void ReceiveTraceChunk(const std::string& chunk) override { | 64 void ReceiveTraceChunk(const std::string& chunk) override { |
| 61 std::string tmp = chunk; | 65 std::string tmp = chunk; |
| 62 scoped_refptr<base::RefCountedString> chunk_ptr = | 66 scoped_refptr<base::RefCountedString> chunk_ptr = |
| 63 base::RefCountedString::TakeString(&tmp); | 67 base::RefCountedString::TakeString(&tmp); |
| 64 BrowserThread::PostTask( | 68 BrowserThread::PostTask( |
| 65 BrowserThread::FILE, FROM_HERE, | 69 BrowserThread::FILE, FROM_HERE, |
| 66 base::Bind(&FileTraceDataEndpoint::ReceiveTraceChunkOnFileThread, this, | 70 base::Bind(&FileTraceDataEndpoint::ReceiveTraceChunkOnFileThread, this, |
| 67 chunk_ptr)); | 71 chunk_ptr)); |
| 68 } | 72 } |
| 69 | 73 |
| 70 void ReceiveTraceFinalContents(std::unique_ptr<const base::DictionaryValue>, | 74 void ReceiveTraceFinalContents( |
| 71 const std::string& contents) override { | 75 std::unique_ptr<const base::DictionaryValue>) override { |
| 72 BrowserThread::PostTask( | 76 BrowserThread::PostTask( |
| 73 BrowserThread::FILE, FROM_HERE, | 77 BrowserThread::FILE, FROM_HERE, |
| 74 base::Bind(&FileTraceDataEndpoint::CloseOnFileThread, this)); | 78 base::Bind(&FileTraceDataEndpoint::CloseOnFileThread, this)); |
| 75 } | 79 } |
| 76 | 80 |
| 77 private: | 81 private: |
| 78 ~FileTraceDataEndpoint() override { DCHECK(file_ == NULL); } | 82 ~FileTraceDataEndpoint() override { DCHECK(file_ == NULL); } |
| 79 | 83 |
| 80 void ReceiveTraceChunkOnFileThread( | 84 void ReceiveTraceChunkOnFileThread( |
| 81 const scoped_refptr<base::RefCountedString> chunk) { | 85 const scoped_refptr<base::RefCountedString> chunk) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 const std::map<std::string, std::string>& GetAgentTrace() const; | 135 const std::map<std::string, std::string>& GetAgentTrace() const; |
| 132 std::unique_ptr<base::DictionaryValue> TakeMetadata(); | 136 std::unique_ptr<base::DictionaryValue> TakeMetadata(); |
| 133 | 137 |
| 134 private: | 138 private: |
| 135 std::map<std::string, std::string> additional_tracing_agent_trace_; | 139 std::map<std::string, std::string> additional_tracing_agent_trace_; |
| 136 std::unique_ptr<base::DictionaryValue> metadata_; | 140 std::unique_ptr<base::DictionaryValue> metadata_; |
| 137 | 141 |
| 138 DISALLOW_COPY_AND_ASSIGN(TraceDataSinkImplBase); | 142 DISALLOW_COPY_AND_ASSIGN(TraceDataSinkImplBase); |
| 139 }; | 143 }; |
| 140 | 144 |
| 141 class StringTraceDataSink : public TraceDataSinkImplBase { | 145 class JSONTraceDataSink : public TraceDataSinkImplBase { |
| 142 public: | 146 public: |
| 143 explicit StringTraceDataSink(scoped_refptr<TraceDataEndpoint> endpoint) | 147 explicit JSONTraceDataSink(scoped_refptr<TraceDataEndpoint> endpoint) |
| 144 : endpoint_(endpoint) {} | 148 : endpoint_(endpoint), had_received_first_chunk_(false) {} |
| 145 | 149 |
| 146 void AddTraceChunk(const std::string& chunk) override { | 150 void AddTraceChunk(const std::string& chunk) override { |
| 147 std::string trace_string; | 151 std::string trace_string; |
| 148 if (trace_.empty()) | 152 if (had_received_first_chunk_) |
| 153 trace_string = ","; |
| 154 else |
| 149 trace_string = "{\"" + std::string(kChromeTraceLabel) + "\":["; | 155 trace_string = "{\"" + std::string(kChromeTraceLabel) + "\":["; |
| 150 else | |
| 151 trace_string = ","; | |
| 152 trace_string += chunk; | 156 trace_string += chunk; |
| 157 had_received_first_chunk_ = true; |
| 153 | 158 |
| 154 AddTraceChunkAndPassToEndpoint(trace_string); | 159 endpoint_->ReceiveTraceChunk(trace_string); |
| 155 } | |
| 156 | |
| 157 void AddTraceChunkAndPassToEndpoint(const std::string& chunk) { | |
| 158 trace_ += chunk; | |
| 159 | |
| 160 endpoint_->ReceiveTraceChunk(chunk); | |
| 161 } | 160 } |
| 162 | 161 |
| 163 void Close() override { | 162 void Close() override { |
| 164 AddTraceChunkAndPassToEndpoint("]"); | 163 endpoint_->ReceiveTraceChunk("]"); |
| 165 | 164 |
| 166 for (auto const &it : GetAgentTrace()) | 165 for (auto const &it : GetAgentTrace()) |
| 167 AddTraceChunkAndPassToEndpoint(",\"" + it.first + "\": " + it.second); | 166 endpoint_->ReceiveTraceChunk(",\"" + it.first + "\": " + it.second); |
| 168 | 167 |
| 169 std::unique_ptr<base::DictionaryValue> metadata(TakeMetadata()); | 168 std::unique_ptr<base::DictionaryValue> metadata(TakeMetadata()); |
| 170 std::string metadataJSON; | 169 std::string metadataJSON; |
| 171 | 170 |
| 172 if (base::JSONWriter::Write(*metadata, &metadataJSON) && | 171 if (base::JSONWriter::Write(*metadata, &metadataJSON) && |
| 173 !metadataJSON.empty()) { | 172 !metadataJSON.empty()) { |
| 174 AddTraceChunkAndPassToEndpoint( | 173 endpoint_->ReceiveTraceChunk(",\"" + std::string(kMetadataTraceLabel) + |
| 175 ",\"" + std::string(kMetadataTraceLabel) + "\": " + metadataJSON); | 174 "\": " + metadataJSON); |
| 176 } | 175 } |
| 177 | 176 |
| 178 AddTraceChunkAndPassToEndpoint("}"); | 177 endpoint_->ReceiveTraceChunk("}"); |
| 179 | 178 endpoint_->ReceiveTraceFinalContents(std::move(metadata)); |
| 180 endpoint_->ReceiveTraceFinalContents(std::move(metadata), trace_); | |
| 181 } | 179 } |
| 182 | 180 |
| 183 private: | 181 private: |
| 184 ~StringTraceDataSink() override {} | 182 ~JSONTraceDataSink() override {} |
| 185 | 183 |
| 186 scoped_refptr<TraceDataEndpoint> endpoint_; | 184 scoped_refptr<TraceDataEndpoint> endpoint_; |
| 187 std::string trace_; | 185 bool had_received_first_chunk_; |
| 188 | 186 DISALLOW_COPY_AND_ASSIGN(JSONTraceDataSink); |
| 189 DISALLOW_COPY_AND_ASSIGN(StringTraceDataSink); | |
| 190 }; | 187 }; |
| 191 | 188 |
| 192 class CompressedStringTraceDataSink : public TraceDataSinkImplBase { | 189 class CompressedStringTraceDataSink : public TraceDataSinkImplBase { |
| 193 public: | 190 public: |
| 194 explicit CompressedStringTraceDataSink( | 191 explicit CompressedStringTraceDataSink( |
| 195 scoped_refptr<TraceDataEndpoint> endpoint) | 192 scoped_refptr<TraceDataEndpoint> endpoint) |
| 196 : endpoint_(endpoint), already_tried_open_(false) {} | 193 : endpoint_(endpoint), already_tried_open_(false), |
| 194 had_received_first_chunk_(false) {} |
| 197 | 195 |
| 198 void AddTraceChunk(const std::string& chunk) override { | 196 void AddTraceChunk(const std::string& chunk) override { |
| 199 std::string tmp = chunk; | 197 std::string tmp = chunk; |
| 200 scoped_refptr<base::RefCountedString> chunk_ptr = | 198 scoped_refptr<base::RefCountedString> chunk_ptr = |
| 201 base::RefCountedString::TakeString(&tmp); | 199 base::RefCountedString::TakeString(&tmp); |
| 202 BrowserThread::PostTask( | 200 BrowserThread::PostTask( |
| 203 BrowserThread::FILE, FROM_HERE, | 201 BrowserThread::FILE, FROM_HERE, |
| 204 base::Bind(&CompressedStringTraceDataSink::AddTraceChunkOnFileThread, | 202 base::Bind(&CompressedStringTraceDataSink::AddTraceChunkOnFileThread, |
| 205 this, chunk_ptr)); | 203 this, chunk_ptr)); |
| 206 } | 204 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 234 MAX_WBITS + 16, | 232 MAX_WBITS + 16, |
| 235 8, // memLevel = 8 is default. | 233 8, // memLevel = 8 is default. |
| 236 Z_DEFAULT_STRATEGY); | 234 Z_DEFAULT_STRATEGY); |
| 237 return result == 0; | 235 return result == 0; |
| 238 } | 236 } |
| 239 | 237 |
| 240 void AddTraceChunkOnFileThread( | 238 void AddTraceChunkOnFileThread( |
| 241 const scoped_refptr<base::RefCountedString> chunk_ptr) { | 239 const scoped_refptr<base::RefCountedString> chunk_ptr) { |
| 242 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 240 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 243 std::string trace; | 241 std::string trace; |
| 244 if (compressed_trace_data_.empty()) | 242 if (had_received_first_chunk_) |
| 243 trace = ","; |
| 244 else |
| 245 trace = "{\"" + std::string(kChromeTraceLabel) + "\":["; | 245 trace = "{\"" + std::string(kChromeTraceLabel) + "\":["; |
| 246 else | 246 had_received_first_chunk_ = true; |
| 247 trace = ","; | |
| 248 trace += chunk_ptr->data(); | 247 trace += chunk_ptr->data(); |
| 249 AddTraceChunkAndCompressOnFileThread(trace, false); | 248 AddTraceChunkAndCompressOnFileThread(trace, false); |
| 250 } | 249 } |
| 251 | 250 |
| 252 void AddTraceChunkAndCompressOnFileThread(const std::string& chunk, | 251 void AddTraceChunkAndCompressOnFileThread(const std::string& chunk, |
| 253 bool finished) { | 252 bool finished) { |
| 254 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 253 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 255 if (!OpenZStreamOnFileThread()) | 254 if (!OpenZStreamOnFileThread()) |
| 256 return; | 255 return; |
| 257 | 256 |
| 258 const int kChunkSize = 0x4000; | 257 const int kChunkSize = 0x4000; |
| 259 | 258 |
| 260 char buffer[kChunkSize]; | 259 char buffer[kChunkSize]; |
| 261 int err; | 260 int err; |
| 262 stream_->avail_in = chunk.size(); | 261 stream_->avail_in = chunk.size(); |
| 263 stream_->next_in = (unsigned char*)chunk.data(); | 262 stream_->next_in = (unsigned char*)chunk.data(); |
| 264 do { | 263 do { |
| 265 stream_->avail_out = kChunkSize; | 264 stream_->avail_out = kChunkSize; |
| 266 stream_->next_out = (unsigned char*)buffer; | 265 stream_->next_out = (unsigned char*)buffer; |
| 267 err = deflate(stream_.get(), finished ? Z_FINISH : Z_NO_FLUSH); | 266 err = deflate(stream_.get(), finished ? Z_FINISH : Z_NO_FLUSH); |
| 268 if (err != Z_OK && (err != Z_STREAM_END && finished)) { | 267 if (err != Z_OK && (err != Z_STREAM_END && finished)) { |
| 269 stream_.reset(); | 268 stream_.reset(); |
| 270 return; | 269 return; |
| 271 } | 270 } |
| 272 | 271 |
| 273 int bytes = kChunkSize - stream_->avail_out; | 272 int bytes = kChunkSize - stream_->avail_out; |
| 274 if (bytes) { | 273 if (bytes) { |
| 275 std::string compressed_chunk = std::string(buffer, bytes); | 274 std::string compressed_chunk = std::string(buffer, bytes); |
| 276 compressed_trace_data_ += compressed_chunk; | |
| 277 endpoint_->ReceiveTraceChunk(compressed_chunk); | 275 endpoint_->ReceiveTraceChunk(compressed_chunk); |
| 278 } | 276 } |
| 279 } while (stream_->avail_out == 0); | 277 } while (stream_->avail_out == 0); |
| 280 } | 278 } |
| 281 | 279 |
| 282 void CloseOnFileThread() { | 280 void CloseOnFileThread() { |
| 283 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 281 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 284 if (!OpenZStreamOnFileThread()) | 282 if (!OpenZStreamOnFileThread()) |
| 285 return; | 283 return; |
| 286 | 284 |
| 287 if (compressed_trace_data_.empty()) { | 285 if (!had_received_first_chunk_) { |
| 288 AddTraceChunkAndCompressOnFileThread( | 286 AddTraceChunkAndCompressOnFileThread( |
| 289 "{\"" + std::string(kChromeTraceLabel) + "\":[", false); | 287 "{\"" + std::string(kChromeTraceLabel) + "\":[", false); |
| 290 } | 288 } |
| 291 AddTraceChunkAndCompressOnFileThread("]", false); | 289 AddTraceChunkAndCompressOnFileThread("]", false); |
| 292 | 290 |
| 293 for (auto const &it : GetAgentTrace()) { | 291 for (auto const &it : GetAgentTrace()) { |
| 294 AddTraceChunkAndCompressOnFileThread( | 292 AddTraceChunkAndCompressOnFileThread( |
| 295 ",\"" + it.first + "\": " + it.second, false); | 293 ",\"" + it.first + "\": " + it.second, false); |
| 296 } | 294 } |
| 297 | 295 |
| 298 std::unique_ptr<base::DictionaryValue> metadata(TakeMetadata()); | 296 std::unique_ptr<base::DictionaryValue> metadata(TakeMetadata()); |
| 299 std::string metadataJSON; | 297 std::string metadataJSON; |
| 300 if (base::JSONWriter::Write(*metadata, &metadataJSON) && | 298 if (base::JSONWriter::Write(*metadata, &metadataJSON) && |
| 301 !metadataJSON.empty()) { | 299 !metadataJSON.empty()) { |
| 302 AddTraceChunkAndCompressOnFileThread( | 300 AddTraceChunkAndCompressOnFileThread( |
| 303 ",\"" + std::string(kMetadataTraceLabel) + "\": " + metadataJSON, | 301 ",\"" + std::string(kMetadataTraceLabel) + "\": " + metadataJSON, |
| 304 false); | 302 false); |
| 305 } | 303 } |
| 306 AddTraceChunkAndCompressOnFileThread("}", true); | 304 AddTraceChunkAndCompressOnFileThread("}", true); |
| 307 | 305 |
| 308 deflateEnd(stream_.get()); | 306 deflateEnd(stream_.get()); |
| 309 stream_.reset(); | 307 stream_.reset(); |
| 310 | 308 |
| 311 endpoint_->ReceiveTraceFinalContents(std::move(metadata), | 309 endpoint_->ReceiveTraceFinalContents(std::move(metadata)); |
| 312 compressed_trace_data_); | |
| 313 } | 310 } |
| 314 | 311 |
| 315 scoped_refptr<TraceDataEndpoint> endpoint_; | 312 scoped_refptr<TraceDataEndpoint> endpoint_; |
| 316 std::unique_ptr<z_stream> stream_; | 313 std::unique_ptr<z_stream> stream_; |
| 317 bool already_tried_open_; | 314 bool already_tried_open_; |
| 318 std::string compressed_trace_data_; | 315 bool had_received_first_chunk_; |
| 319 | 316 |
| 320 DISALLOW_COPY_AND_ASSIGN(CompressedStringTraceDataSink); | 317 DISALLOW_COPY_AND_ASSIGN(CompressedStringTraceDataSink); |
| 321 }; | 318 }; |
| 322 | 319 |
| 323 } // namespace | 320 } // namespace |
| 324 | 321 |
| 325 TracingController::TraceDataSink::TraceDataSink() {} | 322 TracingController::TraceDataSink::TraceDataSink() {} |
| 326 TracingController::TraceDataSink::~TraceDataSink() {} | 323 TracingController::TraceDataSink::~TraceDataSink() {} |
| 327 | 324 |
| 328 void TraceDataSinkImplBase::AddAgentTrace(const std::string& trace_label, | 325 void TraceDataSinkImplBase::AddAgentTrace(const std::string& trace_label, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 343 } | 340 } |
| 344 | 341 |
| 345 std::unique_ptr<base::DictionaryValue> TraceDataSinkImplBase::TakeMetadata() { | 342 std::unique_ptr<base::DictionaryValue> TraceDataSinkImplBase::TakeMetadata() { |
| 346 return std::move(metadata_); | 343 return std::move(metadata_); |
| 347 } | 344 } |
| 348 | 345 |
| 349 scoped_refptr<TracingController::TraceDataSink> | 346 scoped_refptr<TracingController::TraceDataSink> |
| 350 TracingController::CreateStringSink( | 347 TracingController::CreateStringSink( |
| 351 const base::Callback<void(std::unique_ptr<const base::DictionaryValue>, | 348 const base::Callback<void(std::unique_ptr<const base::DictionaryValue>, |
| 352 base::RefCountedString*)>& callback) { | 349 base::RefCountedString*)>& callback) { |
| 353 return new StringTraceDataSink(new StringTraceDataEndpoint(callback)); | 350 return new JSONTraceDataSink(new StringTraceDataEndpoint(callback)); |
| 354 } | 351 } |
| 355 | 352 |
| 356 scoped_refptr<TracingController::TraceDataSink> | 353 scoped_refptr<TracingController::TraceDataSink> |
| 357 TracingController::CreateFileSink(const base::FilePath& file_path, | 354 TracingController::CreateFileSink(const base::FilePath& file_path, |
| 358 const base::Closure& callback) { | 355 const base::Closure& callback) { |
| 359 return new StringTraceDataSink( | 356 return new JSONTraceDataSink(new FileTraceDataEndpoint(file_path, callback)); |
| 360 new FileTraceDataEndpoint(file_path, callback)); | |
| 361 } | 357 } |
| 362 | 358 |
| 363 scoped_refptr<TracingController::TraceDataSink> | 359 scoped_refptr<TracingController::TraceDataSink> |
| 364 TracingControllerImpl::CreateCompressedStringSink( | 360 TracingControllerImpl::CreateCompressedStringSink( |
| 365 scoped_refptr<TraceDataEndpoint> endpoint) { | 361 scoped_refptr<TraceDataEndpoint> endpoint) { |
| 366 return new CompressedStringTraceDataSink(endpoint); | 362 return new CompressedStringTraceDataSink(endpoint); |
| 367 } | 363 } |
| 368 | 364 |
| 369 scoped_refptr<TraceDataEndpoint> TracingControllerImpl::CreateCallbackEndpoint( | 365 scoped_refptr<TraceDataEndpoint> TracingControllerImpl::CreateCallbackEndpoint( |
| 370 const base::Callback<void(std::unique_ptr<const base::DictionaryValue>, | 366 const base::Callback<void(std::unique_ptr<const base::DictionaryValue>, |
| 371 base::RefCountedString*)>& callback) { | 367 base::RefCountedString*)>& callback) { |
| 372 return new StringTraceDataEndpoint(callback); | 368 return new StringTraceDataEndpoint(callback); |
| 373 } | 369 } |
| 374 | 370 |
| 375 } // namespace content | 371 } // namespace content |
| OLD | NEW |