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 "components/tracing/child_trace_message_filter.h"
6
7#include "base/debug/trace_event.h"
8#include "base/message_loop/message_loop_proxy.h"
9#include "components/tracing/tracing_messages.h"
10#include "ipc/ipc_channel.h"
11
12using base::debug::TraceLog;
13
14namespace tracing {
15
16ChildTraceMessageFilter::ChildTraceMessageFilter(
17    base::MessageLoopProxy* ipc_message_loop)
18    : sender_(NULL),
19      ipc_message_loop_(ipc_message_loop) {}
20
21void ChildTraceMessageFilter::OnFilterAdded(IPC::Sender* sender) {
22  sender_ = sender;
23  sender_->Send(new TracingHostMsg_ChildSupportsTracing());
24}
25
26void ChildTraceMessageFilter::OnFilterRemoved() {
27  sender_ = NULL;
28}
29
30bool ChildTraceMessageFilter::OnMessageReceived(const IPC::Message& message) {
31  bool handled = true;
32  IPC_BEGIN_MESSAGE_MAP(ChildTraceMessageFilter, message)
33    IPC_MESSAGE_HANDLER(TracingMsg_BeginTracing, OnBeginTracing)
34    IPC_MESSAGE_HANDLER(TracingMsg_EndTracing, OnEndTracing)
35    IPC_MESSAGE_HANDLER(TracingMsg_EnableMonitoring, OnEnableMonitoring)
36    IPC_MESSAGE_HANDLER(TracingMsg_DisableMonitoring, OnDisableMonitoring)
37    IPC_MESSAGE_HANDLER(TracingMsg_CaptureMonitoringSnapshot,
38                        OnCaptureMonitoringSnapshot)
39    IPC_MESSAGE_HANDLER(TracingMsg_GetTraceBufferPercentFull,
40                        OnGetTraceBufferPercentFull)
41    IPC_MESSAGE_HANDLER(TracingMsg_SetWatchEvent, OnSetWatchEvent)
42    IPC_MESSAGE_HANDLER(TracingMsg_CancelWatchEvent, OnCancelWatchEvent)
43    IPC_MESSAGE_UNHANDLED(handled = false)
44  IPC_END_MESSAGE_MAP()
45  return handled;
46}
47
48ChildTraceMessageFilter::~ChildTraceMessageFilter() {}
49
50void ChildTraceMessageFilter::OnBeginTracing(
51    const std::string& category_filter_str,
52    base::TimeTicks browser_time,
53    int options) {
54#if defined(__native_client__)
55  // NaCl and system times are offset by a bit, so subtract some time from
56  // the captured timestamps. The value might be off by a bit due to messaging
57  // latency.
58  base::TimeDelta time_offset = base::TimeTicks::NowFromSystemTraceTime() -
59      browser_time;
60  TraceLog::GetInstance()->SetTimeOffset(time_offset);
61#endif
62
63  TraceLog::GetInstance()->SetEnabled(
64      base::debug::CategoryFilter(category_filter_str),
65      base::debug::TraceLog::RECORDING_MODE,
66      static_cast<base::debug::TraceLog::Options>(options));
67}
68
69void ChildTraceMessageFilter::OnEndTracing() {
70  TraceLog::GetInstance()->SetDisabled();
71
72  // Flush will generate one or more callbacks to OnTraceDataCollected
73  // synchronously or asynchronously. EndTracingAck will be sent in the last
74  // OnTraceDataCollected. We are already on the IO thread, so the
75  // OnTraceDataCollected calls will not be deferred.
76  TraceLog::GetInstance()->Flush(
77      base::Bind(&ChildTraceMessageFilter::OnTraceDataCollected, this));
78}
79
80void ChildTraceMessageFilter::OnEnableMonitoring(
81    const std::string& category_filter_str,
82    base::TimeTicks browser_time,
83    int options) {
84  TraceLog::GetInstance()->SetEnabled(
85      base::debug::CategoryFilter(category_filter_str),
86      base::debug::TraceLog::MONITORING_MODE,
87      static_cast<base::debug::TraceLog::Options>(options));
88}
89
90void ChildTraceMessageFilter::OnDisableMonitoring() {
91  TraceLog::GetInstance()->SetDisabled();
92}
93
94void ChildTraceMessageFilter::OnCaptureMonitoringSnapshot() {
95  // Flush will generate one or more callbacks to
96  // OnMonitoringTraceDataCollected. It's important that the last
97  // OnMonitoringTraceDataCollected gets called before
98  // CaptureMonitoringSnapshotAck below. We are already on the IO thread,
99  // so the OnMonitoringTraceDataCollected calls will not be deferred.
100  TraceLog::GetInstance()->FlushButLeaveBufferIntact(
101      base::Bind(&ChildTraceMessageFilter::OnMonitoringTraceDataCollected,
102                 this));
103}
104
105void ChildTraceMessageFilter::OnGetTraceBufferPercentFull() {
106  float bpf = TraceLog::GetInstance()->GetBufferPercentFull();
107
108  sender_->Send(new TracingHostMsg_TraceBufferPercentFullReply(bpf));
109}
110
111void ChildTraceMessageFilter::OnSetWatchEvent(const std::string& category_name,
112                                              const std::string& event_name) {
113  TraceLog::GetInstance()->SetWatchEvent(
114      category_name, event_name,
115      base::Bind(&ChildTraceMessageFilter::OnWatchEventMatched, this));
116}
117
118void ChildTraceMessageFilter::OnCancelWatchEvent() {
119  TraceLog::GetInstance()->CancelWatchEvent();
120}
121
122void ChildTraceMessageFilter::OnWatchEventMatched() {
123  if (!ipc_message_loop_->BelongsToCurrentThread()) {
124    ipc_message_loop_->PostTask(FROM_HERE,
125        base::Bind(&ChildTraceMessageFilter::OnWatchEventMatched, this));
126    return;
127  }
128  sender_->Send(new TracingHostMsg_WatchEventMatched);
129}
130
131void ChildTraceMessageFilter::OnTraceDataCollected(
132    const scoped_refptr<base::RefCountedString>& events_str_ptr,
133    bool has_more_events) {
134  if (!ipc_message_loop_->BelongsToCurrentThread()) {
135    ipc_message_loop_->PostTask(FROM_HERE,
136        base::Bind(&ChildTraceMessageFilter::OnTraceDataCollected, this,
137                   events_str_ptr, has_more_events));
138    return;
139  }
140  if (events_str_ptr->data().size()) {
141    sender_->Send(new TracingHostMsg_TraceDataCollected(
142        events_str_ptr->data()));
143  }
144  if (!has_more_events) {
145    std::vector<std::string> category_groups;
146    TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
147    sender_->Send(new TracingHostMsg_EndTracingAck(category_groups));
148  }
149}
150
151void ChildTraceMessageFilter::OnMonitoringTraceDataCollected(
152     const scoped_refptr<base::RefCountedString>& events_str_ptr,
153     bool has_more_events) {
154  if (!ipc_message_loop_->BelongsToCurrentThread()) {
155    ipc_message_loop_->PostTask(FROM_HERE,
156        base::Bind(&ChildTraceMessageFilter::
157                   OnMonitoringTraceDataCollected,
158                   this,
159                   events_str_ptr,
160                   has_more_events));
161    return;
162  }
163  sender_->Send(new TracingHostMsg_MonitoringTraceDataCollected(
164      events_str_ptr->data()));
165
166  if (!has_more_events)
167    sender_->Send(new TracingHostMsg_CaptureMonitoringSnapshotAck());
168}
169
170}  // namespace tracing
171