| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 #include "content/browser/trace_subscriber_stdio.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/debug/trace_event.h" | |
| 9 #include "base/logging.h" | |
| 10 #include "base/threading/sequenced_worker_pool.h" | |
| 11 #include "content/public/browser/browser_thread.h" | |
| 12 | |
| 13 namespace content { | |
| 14 | |
| 15 // All method calls on this class are done on a SequencedWorkerPool thread. | |
| 16 class TraceSubscriberStdioImpl | |
| 17 : public base::RefCountedThreadSafe<TraceSubscriberStdioImpl> { | |
| 18 public: | |
| 19 explicit TraceSubscriberStdioImpl(const FilePath& path) | |
| 20 : path_(path), | |
| 21 file_(0) {} | |
| 22 | |
| 23 void OnStart() { | |
| 24 DCHECK(!file_); | |
| 25 trace_buffer_.SetOutputCallback( | |
| 26 base::Bind(&TraceSubscriberStdioImpl::Write, this)); | |
| 27 file_ = file_util::OpenFile(path_, "w+"); | |
| 28 if (IsValid()) { | |
| 29 LOG(INFO) << "Logging performance trace to file: " << path_.value(); | |
| 30 trace_buffer_.Start(); | |
| 31 } else { | |
| 32 LOG(ERROR) << "Failed to open performance trace file: " << path_.value(); | |
| 33 } | |
| 34 } | |
| 35 | |
| 36 void OnData(const scoped_refptr<base::RefCountedString>& data_ptr) { | |
| 37 trace_buffer_.AddFragment(data_ptr->data()); | |
| 38 } | |
| 39 | |
| 40 void OnEnd() { | |
| 41 trace_buffer_.Finish(); | |
| 42 CloseFile(); | |
| 43 } | |
| 44 | |
| 45 private: | |
| 46 friend class base::RefCountedThreadSafe<TraceSubscriberStdioImpl>; | |
| 47 | |
| 48 ~TraceSubscriberStdioImpl() { | |
| 49 CloseFile(); | |
| 50 } | |
| 51 | |
| 52 bool IsValid() const { | |
| 53 return file_ && (0 == ferror(file_)); | |
| 54 } | |
| 55 | |
| 56 void CloseFile() { | |
| 57 if (file_) { | |
| 58 fclose(file_); | |
| 59 file_ = 0; | |
| 60 } | |
| 61 // This is important, as it breaks a reference cycle. | |
| 62 trace_buffer_.SetOutputCallback( | |
| 63 base::debug::TraceResultBuffer::OutputCallback()); | |
| 64 } | |
| 65 | |
| 66 void Write(const std::string& output_str) { | |
| 67 if (IsValid()) { | |
| 68 size_t written = fwrite(output_str.data(), 1, output_str.size(), file_); | |
| 69 if (written != output_str.size()) { | |
| 70 LOG(ERROR) << "Error " << ferror(file_) << " in fwrite() to trace file"; | |
| 71 CloseFile(); | |
| 72 } | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 FilePath path_; | |
| 77 FILE* file_; | |
| 78 base::debug::TraceResultBuffer trace_buffer_; | |
| 79 }; | |
| 80 | |
| 81 TraceSubscriberStdio::TraceSubscriberStdio(const FilePath& path) | |
| 82 : impl_(new TraceSubscriberStdioImpl(path)) { | |
| 83 BrowserThread::PostBlockingPoolSequencedTask( | |
| 84 __FILE__, FROM_HERE, | |
| 85 base::Bind(&TraceSubscriberStdioImpl::OnStart, impl_)); | |
| 86 } | |
| 87 | |
| 88 TraceSubscriberStdio::~TraceSubscriberStdio() { | |
| 89 } | |
| 90 | |
| 91 void TraceSubscriberStdio::OnEndTracingComplete() { | |
| 92 BrowserThread::PostBlockingPoolSequencedTask( | |
| 93 __FILE__, FROM_HERE, | |
| 94 base::Bind(&TraceSubscriberStdioImpl::OnEnd, impl_)); | |
| 95 } | |
| 96 | |
| 97 void TraceSubscriberStdio::OnTraceDataCollected( | |
| 98 const scoped_refptr<base::RefCountedString>& data_ptr) { | |
| 99 BrowserThread::PostBlockingPoolSequencedTask( | |
| 100 __FILE__, FROM_HERE, | |
| 101 base::Bind(&TraceSubscriberStdioImpl::OnData, impl_, data_ptr)); | |
| 102 } | |
| 103 | |
| 104 } // namespace content | |
| OLD | NEW |