blob: 62b77d8b0e3760bae49985101fd7b5853200850c [file] [log] [blame]
ergb9210582015-05-09 03:52:16 +09001// Copyright 2015 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 "mojo/services/tracing/tracing_app.h"
6
7#include "base/bind.h"
8#include "base/message_loop/message_loop.h"
jam8bb27ff2015-05-15 07:56:10 +09009#include "mojo/application/public/cpp/application_connection.h"
ergb9210582015-05-09 03:52:16 +090010#include "mojo/services/tracing/trace_data_sink.h"
ergb9210582015-05-09 03:52:16 +090011
12namespace tracing {
13
14class CollectorImpl : public TraceDataCollector {
15 public:
16 CollectorImpl(mojo::InterfaceRequest<TraceDataCollector> request,
17 TraceDataSink* sink)
18 : sink_(sink), binding_(this, request.Pass()) {}
19
20 ~CollectorImpl() override {}
21
22 // tracing::TraceDataCollector implementation.
23 void DataCollected(const mojo::String& json) override {
24 sink_->AddChunk(json.To<std::string>());
25 }
26
27 private:
28 TraceDataSink* sink_;
29 mojo::Binding<TraceDataCollector> binding_;
30
31 DISALLOW_COPY_AND_ASSIGN(CollectorImpl);
32};
33
34TracingApp::TracingApp() {}
35
36TracingApp::~TracingApp() {}
37
38bool TracingApp::ConfigureIncomingConnection(
39 mojo::ApplicationConnection* connection) {
40 connection->AddService<TraceCoordinator>(this);
msw339a3c42015-08-19 03:55:31 +090041 connection->AddService<StartupPerformanceDataCollector>(this);
ergb9210582015-05-09 03:52:16 +090042
43 // If someone connects to us they may want to use the TraceCoordinator
44 // interface and/or they may want to expose themselves to be traced. Attempt
45 // to connect to the TraceController interface to see if the application
46 // connecting to us wants to be traced. They can refuse the connection or
47 // close the pipe if not.
48 TraceControllerPtr controller_ptr;
49 connection->ConnectToService(&controller_ptr);
msw339a3c42015-08-19 03:55:31 +090050 if (controller_ptr)
51 controller_ptrs_.AddInterfacePtr(controller_ptr.Pass());
ergb9210582015-05-09 03:52:16 +090052 return true;
53}
54
55void TracingApp::Create(
56 mojo::ApplicationConnection* connection,
57 mojo::InterfaceRequest<TraceCoordinator> request) {
58 coordinator_bindings_.AddBinding(this, request.Pass());
59}
60
msw339a3c42015-08-19 03:55:31 +090061void TracingApp::Create(
62 mojo::ApplicationConnection* connection,
63 mojo::InterfaceRequest<StartupPerformanceDataCollector> request) {
64 startup_performance_data_collector_bindings_.AddBinding(this, request.Pass());
65}
66
ergb9210582015-05-09 03:52:16 +090067void TracingApp::Start(mojo::ScopedDataPipeProducerHandle stream,
68 const mojo::String& categories) {
69 sink_.reset(new TraceDataSink(stream.Pass()));
70 controller_ptrs_.ForAllPtrs(
71 [categories, this](TraceController* controller) {
72 TraceDataCollectorPtr ptr;
73 collector_impls_.push_back(
74 new CollectorImpl(GetProxy(&ptr), sink_.get()));
75 controller->StartTracing(categories, ptr.Pass());
76 });
77}
78
79void TracingApp::StopAndFlush() {
80 controller_ptrs_.ForAllPtrs(
81 [](TraceController* controller) { controller->StopTracing(); });
82
83 // TODO: We really should keep track of how many connections we have here
84 // and flush + reset the sink after we receive a EndTracing or a detect a
85 // pipe closure on all pipes.
86 base::MessageLoop::current()->PostDelayedTask(
87 FROM_HERE,
88 base::Bind(&TracingApp::AllDataCollected, base::Unretained(this)),
89 base::TimeDelta::FromSeconds(1));
90}
91
msw339a3c42015-08-19 03:55:31 +090092void TracingApp::SetShellProcessCreationTime(int64 time) {
93 if (startup_performance_times_.shell_process_creation_time == 0)
94 startup_performance_times_.shell_process_creation_time = time;
95}
96
97void TracingApp::SetBrowserMessageLoopStartTime(int64 time) {
98 if (startup_performance_times_.browser_message_loop_start_time == 0)
99 startup_performance_times_.browser_message_loop_start_time = time;
100}
101
102void TracingApp::SetBrowserWindowDisplayTime(int64 time) {
103 if (startup_performance_times_.browser_window_display_time == 0)
104 startup_performance_times_.browser_window_display_time = time;
105}
106
107void TracingApp::SetBrowserOpenTabsTime(int64 time) {
108 if (startup_performance_times_.browser_open_tabs_time == 0)
109 startup_performance_times_.browser_open_tabs_time = time;
110}
111
112void TracingApp::SetFirstWebContentsMainFrameLoadTime(int64 time) {
113 if (startup_performance_times_.first_web_contents_main_frame_load_time == 0)
114 startup_performance_times_.first_web_contents_main_frame_load_time = time;
115}
116
117void TracingApp::SetFirstVisuallyNonEmptyLayoutTime(int64 time) {
118 if (startup_performance_times_.first_visually_non_empty_layout_time == 0)
119 startup_performance_times_.first_visually_non_empty_layout_time = time;
120}
121
122void TracingApp::GetStartupPerformanceTimes(
123 const GetStartupPerformanceTimesCallback& callback) {
124 callback.Run(startup_performance_times_.Clone());
125}
126
ergb9210582015-05-09 03:52:16 +0900127void TracingApp::AllDataCollected() {
128 collector_impls_.clear();
129 sink_->Flush();
130}
131
132} // namespace tracing