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/tracing/trace_message_filter.h"
6
7#include "components/tracing/tracing_messages.h"
8#include "content/browser/tracing/tracing_controller_impl.h"
9
10namespace content {
11
12TraceMessageFilter::TraceMessageFilter()
13    : BrowserMessageFilter(TracingMsgStart),
14      has_child_(false),
15      is_awaiting_end_ack_(false),
16      is_awaiting_capture_monitoring_snapshot_ack_(false),
17      is_awaiting_buffer_percent_full_ack_(false) {
18}
19
20TraceMessageFilter::~TraceMessageFilter() {}
21
22void TraceMessageFilter::OnChannelClosing() {
23  if (has_child_) {
24    if (is_awaiting_end_ack_)
25      OnEndTracingAck(std::vector<std::string>());
26
27    if (is_awaiting_capture_monitoring_snapshot_ack_)
28      OnCaptureMonitoringSnapshotAcked();
29
30    if (is_awaiting_buffer_percent_full_ack_)
31      OnTraceBufferPercentFullReply(0.0f);
32
33    TracingControllerImpl::GetInstance()->RemoveTraceMessageFilter(this);
34  }
35}
36
37bool TraceMessageFilter::OnMessageReceived(const IPC::Message& message) {
38  // Always on IO thread (BrowserMessageFilter guarantee).
39  bool handled = true;
40  IPC_BEGIN_MESSAGE_MAP(TraceMessageFilter, message)
41    IPC_MESSAGE_HANDLER(TracingHostMsg_ChildSupportsTracing,
42                        OnChildSupportsTracing)
43    IPC_MESSAGE_HANDLER(TracingHostMsg_EndTracingAck, OnEndTracingAck)
44    IPC_MESSAGE_HANDLER(TracingHostMsg_CaptureMonitoringSnapshotAck,
45                        OnCaptureMonitoringSnapshotAcked)
46    IPC_MESSAGE_HANDLER(TracingHostMsg_TraceDataCollected,
47                        OnTraceDataCollected)
48    IPC_MESSAGE_HANDLER(TracingHostMsg_MonitoringTraceDataCollected,
49                        OnMonitoringTraceDataCollected)
50    IPC_MESSAGE_HANDLER(TracingHostMsg_WatchEventMatched,
51                        OnWatchEventMatched)
52    IPC_MESSAGE_HANDLER(TracingHostMsg_TraceBufferPercentFullReply,
53                        OnTraceBufferPercentFullReply)
54    IPC_MESSAGE_UNHANDLED(handled = false)
55  IPC_END_MESSAGE_MAP()
56  return handled;
57}
58
59void TraceMessageFilter::SendBeginTracing(
60    const base::debug::CategoryFilter& category_filter,
61    const base::debug::TraceOptions& options) {
62  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
63  Send(new TracingMsg_BeginTracing(category_filter.ToString(),
64                                   base::TimeTicks::NowFromSystemTraceTime(),
65                                   options.ToString()));
66}
67
68void TraceMessageFilter::SendEndTracing() {
69  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
70  DCHECK(!is_awaiting_end_ack_);
71  is_awaiting_end_ack_ = true;
72  Send(new TracingMsg_EndTracing);
73}
74
75void TraceMessageFilter::SendEnableMonitoring(
76    const base::debug::CategoryFilter& category_filter,
77    const base::debug::TraceOptions& options) {
78  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
79  Send(new TracingMsg_EnableMonitoring(category_filter.ToString(),
80      base::TimeTicks::NowFromSystemTraceTime(),
81      options.ToString()));
82}
83
84void TraceMessageFilter::SendDisableMonitoring() {
85  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
86  Send(new TracingMsg_DisableMonitoring);
87}
88
89void TraceMessageFilter::SendCaptureMonitoringSnapshot() {
90  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
91  DCHECK(!is_awaiting_capture_monitoring_snapshot_ack_);
92  is_awaiting_capture_monitoring_snapshot_ack_ = true;
93  Send(new TracingMsg_CaptureMonitoringSnapshot);
94}
95
96void TraceMessageFilter::SendGetTraceBufferPercentFull() {
97  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
98  DCHECK(!is_awaiting_buffer_percent_full_ack_);
99  is_awaiting_buffer_percent_full_ack_ = true;
100  Send(new TracingMsg_GetTraceBufferPercentFull);
101}
102
103void TraceMessageFilter::SendSetWatchEvent(const std::string& category_name,
104                                           const std::string& event_name) {
105  Send(new TracingMsg_SetWatchEvent(category_name, event_name));
106}
107
108void TraceMessageFilter::SendCancelWatchEvent() {
109  Send(new TracingMsg_CancelWatchEvent);
110}
111
112void TraceMessageFilter::OnChildSupportsTracing() {
113  has_child_ = true;
114  TracingControllerImpl::GetInstance()->AddTraceMessageFilter(this);
115}
116
117void TraceMessageFilter::OnEndTracingAck(
118    const std::vector<std::string>& known_categories) {
119  // is_awaiting_end_ack_ should always be true here, but check in case the
120  // child process is compromised.
121  if (is_awaiting_end_ack_) {
122    is_awaiting_end_ack_ = false;
123    TracingControllerImpl::GetInstance()->OnDisableRecordingAcked(
124        this, known_categories);
125  } else {
126    NOTREACHED();
127  }
128}
129
130void TraceMessageFilter::OnCaptureMonitoringSnapshotAcked() {
131  // is_awaiting_capture_monitoring_snapshot_ack_ should always be true here,
132  // but check in case the child process is compromised.
133  if (is_awaiting_capture_monitoring_snapshot_ack_) {
134    is_awaiting_capture_monitoring_snapshot_ack_ = false;
135    TracingControllerImpl::GetInstance()->OnCaptureMonitoringSnapshotAcked(
136        this);
137  } else {
138    NOTREACHED();
139  }
140}
141
142void TraceMessageFilter::OnTraceDataCollected(const std::string& data) {
143  scoped_refptr<base::RefCountedString> data_ptr(new base::RefCountedString());
144  data_ptr->data() = data;
145  TracingControllerImpl::GetInstance()->OnTraceDataCollected(data_ptr);
146}
147
148void TraceMessageFilter::OnMonitoringTraceDataCollected(
149    const std::string& data) {
150  scoped_refptr<base::RefCountedString> data_ptr(new base::RefCountedString());
151  data_ptr->data() = data;
152  TracingControllerImpl::GetInstance()->OnMonitoringTraceDataCollected(
153      data_ptr);
154}
155
156void TraceMessageFilter::OnWatchEventMatched() {
157  TracingControllerImpl::GetInstance()->OnWatchEventMatched();
158}
159
160void TraceMessageFilter::OnTraceBufferPercentFullReply(float percent_full) {
161  if (is_awaiting_buffer_percent_full_ack_) {
162    is_awaiting_buffer_percent_full_ack_ = false;
163    TracingControllerImpl::GetInstance()->OnTraceBufferPercentFullReply(
164        this, percent_full);
165  } else {
166    NOTREACHED();
167  }
168}
169
170}  // namespace content
171