Index: content/browser/tracing/tracing_controller_impl.cc |
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc |
index d2e8a31854617e550deb33c5c749404cc6a951a8..6eea271f6df2b3a4476d9a95ba33fa537823c73a 100644 |
--- a/content/browser/tracing/tracing_controller_impl.cc |
+++ b/content/browser/tracing/tracing_controller_impl.cc |
@@ -28,15 +28,94 @@ TracingController* TracingController::GetInstance() { |
return TracingControllerImpl::GetInstance(); |
} |
+class TracingControllerImpl::ResultFile { |
+ public: |
+ explicit ResultFile(const base::FilePath& path); |
+ void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&TracingControllerImpl::ResultFile::WriteTask, |
+ base::Unretained(this), events_str_ptr)); |
+ } |
+ void Close(const base::Closure& callback) { |
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&TracingControllerImpl::ResultFile::CloseTask, |
+ base::Unretained(this), callback)); |
+ } |
+ const base::FilePath& path() const { return path_; } |
+ |
+ private: |
+ void OpenTask(); |
+ void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr); |
+ void CloseTask(const base::Closure& callback); |
+ |
+ FILE* file_; |
+ base::FilePath path_; |
+ bool has_at_least_one_result_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ResultFile); |
+}; |
+ |
+TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path) |
+ : file_(NULL), |
+ path_(path), |
+ has_at_least_one_result_(false) { |
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&TracingControllerImpl::ResultFile::OpenTask, |
+ base::Unretained(this))); |
+} |
+ |
+void TracingControllerImpl::ResultFile::OpenTask() { |
+ if (path_.empty()) |
+ file_util::CreateTemporaryFile(&path_); |
+ file_ = file_util::OpenFile(path_, "w"); |
+ if (!file_) { |
+ LOG(ERROR) << "Failed to open " << path_.value(); |
+ return; |
+ } |
+ const char* preamble = "{\"traceEvents\": ["; |
+ size_t written = fwrite(preamble, strlen(preamble), 1, file_); |
+ DCHECK(written == 1); |
+} |
+ |
+void TracingControllerImpl::ResultFile::WriteTask( |
+ const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
+ if (!file_) |
+ return; |
+ |
+ // If there is already a result in the file, then put a commma |
+ // before the next batch of results. |
+ if (has_at_least_one_result_) |
+ fwrite(",", 1, 1, file_); |
+ has_at_least_one_result_ = true; |
+ size_t written = fwrite(events_str_ptr->data().c_str(), |
+ events_str_ptr->data().size(), 1, |
+ file_); |
+ DCHECK(written == 1); |
+} |
+ |
+void TracingControllerImpl::ResultFile::CloseTask( |
+ const base::Closure& callback) { |
+ if (!file_) |
+ return; |
+ |
+ const char* trailout = "]}"; |
+ size_t written = fwrite(trailout, strlen(trailout), 1, file_); |
+ DCHECK(written == 1); |
+ file_util::CloseFile(file_); |
+ file_ = NULL; |
+ |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); |
+} |
+ |
+ |
TracingControllerImpl::TracingControllerImpl() : |
pending_disable_recording_ack_count_(0), |
pending_capture_monitoring_snapshot_ack_count_(0), |
is_recording_(false), |
is_monitoring_(false), |
+ trace_options_(TraceLog::RECORD_UNTIL_FULL), |
category_filter_( |
- base::debug::CategoryFilter::kDefaultCategoryFilterString), |
- result_file_(0), |
- result_file_has_at_least_one_result_(false) { |
+ base::debug::CategoryFilter::kDefaultCategoryFilterString) { |
} |
TracingControllerImpl::~TracingControllerImpl() { |
@@ -59,7 +138,7 @@ void TracingControllerImpl::GetCategories( |
EnableRecording(base::debug::CategoryFilter("*"), |
TracingController::Options(), |
EnableRecordingDoneCallback()); |
- DisableRecording(TracingFileResultCallback()); |
+ DisableRecording(base::FilePath(), TracingFileResultCallback()); |
} |
bool TracingControllerImpl::EnableRecording( |
@@ -94,6 +173,7 @@ bool TracingControllerImpl::EnableRecording( |
} |
bool TracingControllerImpl::DisableRecording( |
+ const base::FilePath& result_file_path, |
const TracingFileResultCallback& callback) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
@@ -111,17 +191,8 @@ bool TracingControllerImpl::DisableRecording( |
TraceLog::GetInstance()->AddClockSyncMetadataEvent(); |
#endif |
- // We don't need to create a temporary file when getting categories. |
- if (pending_get_categories_done_callback_.is_null()) { |
- base::FilePath temporary_file; |
- file_util::CreateTemporaryFile(&temporary_file); |
- result_file_path_.reset(new base::FilePath(temporary_file)); |
- result_file_ = file_util::OpenFile(*result_file_path_, "w"); |
- result_file_has_at_least_one_result_ = false; |
- const char* preamble = "{\"traceEvents\": ["; |
- size_t written = fwrite(preamble, strlen(preamble), 1, result_file_); |
- DCHECK(written == 1); |
- } |
+ if (!callback.is_null() || !result_file_path.empty()) |
+ result_file_.reset(new ResultFile(result_file_path)); |
// There could be a case where there are no child processes and filters_ |
// is empty. In that case we can immediately tell the subscriber that tracing |
@@ -203,6 +274,7 @@ void TracingControllerImpl::GetMonitoringStatus( |
} |
void TracingControllerImpl::CaptureMonitoringSnapshot( |
+ const base::FilePath& result_file_path, |
const TracingFileResultCallback& callback) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
@@ -211,14 +283,8 @@ void TracingControllerImpl::CaptureMonitoringSnapshot( |
pending_capture_monitoring_snapshot_done_callback_ = callback; |
- base::FilePath temporary_file; |
- file_util::CreateTemporaryFile(&temporary_file); |
- result_file_path_.reset(new base::FilePath(temporary_file)); |
- result_file_ = file_util::OpenFile(*result_file_path_, "w"); |
- result_file_has_at_least_one_result_ = false; |
- const char* preamble = "{\"traceEvents\": ["; |
- size_t written = fwrite(preamble, strlen(preamble), 1, result_file_); |
- DCHECK(written == 1); |
+ if (!callback.is_null() || !result_file_path.empty()) |
+ monitoring_snapshot_file_.reset(new ResultFile(result_file_path)); |
// There could be a case where there are no child processes and filters_ |
// is empty. In that case we can immediately tell the subscriber that tracing |
@@ -308,15 +374,24 @@ void TracingControllerImpl::OnDisableRecordingAcked( |
if (!pending_get_categories_done_callback_.is_null()) { |
pending_get_categories_done_callback_.Run(known_category_groups_); |
pending_get_categories_done_callback_.Reset(); |
- } else if (!pending_disable_recording_done_callback_.is_null()) { |
- const char* trailout = "]}"; |
- size_t written = fwrite(trailout, strlen(trailout), 1, result_file_); |
- DCHECK(written == 1); |
- file_util::CloseFile(result_file_); |
- result_file_ = 0; |
- pending_disable_recording_done_callback_.Run(result_file_path_.Pass()); |
+ } else if (result_file_) { |
+ result_file_->Close( |
+ base::Bind(&TracingControllerImpl::OnResultFileClosed, |
+ base::Unretained(this))); |
+ } |
+} |
+ |
+void TracingControllerImpl::OnResultFileClosed() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ if (!result_file_) |
+ return; |
+ |
+ if (!pending_disable_recording_done_callback_.is_null()) { |
+ pending_disable_recording_done_callback_.Run(result_file_->path()); |
pending_disable_recording_done_callback_.Reset(); |
} |
+ result_file_.reset(); |
} |
void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked() { |
@@ -342,16 +417,25 @@ void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked() { |
if (pending_capture_monitoring_snapshot_ack_count_ != 0) |
return; |
+ if (monitoring_snapshot_file_) { |
+ monitoring_snapshot_file_->Close( |
+ base::Bind(&TracingControllerImpl::OnMonitoringSnapshotFileClosed, |
+ base::Unretained(this))); |
+ } |
+} |
+ |
+void TracingControllerImpl::OnMonitoringSnapshotFileClosed() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ if (!monitoring_snapshot_file_) |
+ return; |
+ |
if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) { |
- const char* trailout = "]}"; |
- size_t written = fwrite(trailout, strlen(trailout), 1, result_file_); |
- DCHECK(written == 1); |
- file_util::CloseFile(result_file_); |
- result_file_ = 0; |
pending_capture_monitoring_snapshot_done_callback_.Run( |
- result_file_path_.Pass()); |
+ monitoring_snapshot_file_->path()); |
pending_capture_monitoring_snapshot_done_callback_.Reset(); |
} |
+ monitoring_snapshot_file_.reset(); |
} |
void TracingControllerImpl::OnTraceDataCollected( |
@@ -365,22 +449,21 @@ void TracingControllerImpl::OnTraceDataCollected( |
return; |
} |
- // Drop trace events if we are just getting categories. |
- if (!pending_get_categories_done_callback_.is_null()) |
- return; |
+ if (result_file_) |
+ result_file_->Write(events_str_ptr); |
+} |
- // If there is already a result in the file, then put a commma |
- // before the next batch of results. |
- if (result_file_has_at_least_one_result_) { |
- size_t written = fwrite(",", 1, 1, result_file_); |
- DCHECK(written == 1); |
- } else { |
- result_file_has_at_least_one_result_ = true; |
+void TracingControllerImpl::OnMonitoringTraceDataCollected( |
+ const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected, |
+ base::Unretained(this), events_str_ptr)); |
+ return; |
} |
- size_t written = fwrite(events_str_ptr->data().c_str(), |
- events_str_ptr->data().size(), 1, |
- result_file_); |
- DCHECK(written == 1); |
+ |
+ if (!monitoring_snapshot_file_) |
+ monitoring_snapshot_file_->Write(events_str_ptr); |
} |
void TracingControllerImpl::OnLocalTraceDataCollected( |
@@ -402,7 +485,7 @@ void TracingControllerImpl::OnLocalMonitoringTraceDataCollected( |
const scoped_refptr<base::RefCountedString>& events_str_ptr, |
bool has_more_events) { |
if (events_str_ptr->data().size()) |
- OnTraceDataCollected(events_str_ptr); |
+ OnMonitoringTraceDataCollected(events_str_ptr); |
if (has_more_events) |
return; |