1 // 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.
5 #include "components/html_viewer/stats_collection_controller.h"
7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/metrics/histogram.h"
10 #include "base/metrics/statistics_recorder.h"
11 #include "base/time/time.h"
12 #include "components/startup_metric_utils/startup_metric_utils.h"
13 #include "gin/handle.h"
14 #include "gin/object_template_builder.h"
15 #include "mojo/application/public/cpp/application_impl.h"
16 #include "mojo/services/tracing/public/cpp/switches.h"
17 #include "third_party/WebKit/public/web/WebKit.h"
18 #include "third_party/WebKit/public/web/WebLocalFrame.h"
20 namespace html_viewer
{
24 // Initialize the histogram data using the given startup performance times.
25 // TODO(msw): Use TimeTicks to avoid system clock changes: crbug.com/521164
26 void GetStartupPerformanceTimesCallbackImpl(
27 tracing::StartupPerformanceTimesPtr times
) {
28 base::StatisticsRecorder::Initialize();
30 startup_metric_utils::RecordStartupProcessCreationTime(
31 base::Time::FromInternalValue(times
->shell_process_creation_time
));
33 // TODO(msw): Record the MojoMain() entry point time of mojo:browser instead?
34 startup_metric_utils::RecordMainEntryPointTime(
35 base::Time::FromInternalValue(times
->shell_main_entry_point_time
));
37 // TODO(msw): Determine if this is the first run.
38 startup_metric_utils::RecordBrowserMainMessageLoopStart(
39 base::Time::FromInternalValue(times
->browser_message_loop_start_time
),
42 startup_metric_utils::RecordBrowserWindowDisplay(
43 base::Time::FromInternalValue(times
->browser_window_display_time
));
45 // TODO(msw): Consolidate with chrome's PreMainMessageLoopRunImpl()...
46 // TODO(msw): Need to measure the "browser_open_start" time for this delta...
47 const base::Time browser_open_start
=
48 base::Time::FromInternalValue(times
->shell_process_creation_time
);
49 const base::Time browser_open_tabs_time
=
50 base::Time::FromInternalValue(times
->browser_open_tabs_time
);
51 base::TimeDelta delta
= browser_open_tabs_time
- browser_open_start
;
52 UMA_HISTOGRAM_LONG_TIMES_100("Startup.BrowserOpenTabs", delta
);
54 startup_metric_utils::RecordFirstWebContentsMainFrameLoad(
55 base::Time::FromInternalValue(
56 times
->first_web_contents_main_frame_load_time
));
58 startup_metric_utils::RecordFirstWebContentsNonEmptyPaint(
59 base::Time::FromInternalValue(
60 times
->first_visually_non_empty_layout_time
));
66 gin::WrapperInfo
StatsCollectionController::kWrapperInfo
= {
67 gin::kEmbedderNativeGin
};
70 tracing::StartupPerformanceDataCollectorPtr
StatsCollectionController::Install(
71 blink::WebFrame
* frame
,
72 mojo::ApplicationImpl
* app
) {
73 // Only make startup tracing available when running in the context of a test.
75 !base::CommandLine::ForCurrentProcess()->HasSwitch(
76 tracing::kEnableStatsCollectionBindings
)) {
80 v8::Isolate
* isolate
= blink::mainThreadIsolate();
81 v8::HandleScope
handle_scope(isolate
);
82 v8::Local
<v8::Context
> context
= frame
->mainWorldScriptContext();
83 if (context
.IsEmpty())
86 v8::Context::Scope
context_scope(context
);
88 mojo::URLRequestPtr
request(mojo::URLRequest::New());
89 request
->url
= mojo::String::From("mojo:tracing");
90 scoped_ptr
<mojo::ApplicationConnection
> connection
=
91 app
->ConnectToApplication(request
.Pass());
94 tracing::StartupPerformanceDataCollectorPtr collector_for_controller
;
95 tracing::StartupPerformanceDataCollectorPtr collector_for_caller
;
96 connection
->ConnectToService(&collector_for_controller
);
97 connection
->ConnectToService(&collector_for_caller
);
99 gin::Handle
<StatsCollectionController
> controller
= gin::CreateHandle(
100 isolate
, new StatsCollectionController(collector_for_controller
.Pass()));
101 DCHECK(!controller
.IsEmpty());
102 v8::Local
<v8::Object
> global
= context
->Global();
103 global
->Set(gin::StringToV8(isolate
, "statsCollectionController"),
105 return collector_for_caller
.Pass();
108 StatsCollectionController::StatsCollectionController(
109 tracing::StartupPerformanceDataCollectorPtr collector
)
110 : startup_performance_data_collector_(collector
.Pass()) {}
112 StatsCollectionController::~StatsCollectionController() {}
114 gin::ObjectTemplateBuilder
StatsCollectionController::GetObjectTemplateBuilder(
115 v8::Isolate
* isolate
) {
116 return gin::Wrappable
<StatsCollectionController
>::GetObjectTemplateBuilder(
118 .SetMethod("getHistogram", &StatsCollectionController::GetHistogram
)
119 .SetMethod("getBrowserHistogram",
120 &StatsCollectionController::GetBrowserHistogram
);
123 std::string
StatsCollectionController::GetHistogram(
124 const std::string
& histogram_name
) {
125 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
126 tracing::kEnableStatsCollectionBindings
));
128 static bool startup_histogram_initialized
= false;
129 if (!startup_histogram_initialized
) {
130 // Get the startup performance times from the tracing service.
131 auto callback
= base::Bind(&GetStartupPerformanceTimesCallbackImpl
);
132 startup_performance_data_collector_
->GetStartupPerformanceTimes(callback
);
133 startup_performance_data_collector_
.WaitForIncomingResponse();
134 DCHECK(base::StatisticsRecorder::IsActive());
135 startup_histogram_initialized
= true;
138 std::string histogram_json
= "{}";
139 base::HistogramBase
* histogram
=
140 base::StatisticsRecorder::FindHistogram(histogram_name
);
142 histogram
->WriteJSON(&histogram_json
);
143 return histogram_json
;
146 std::string
StatsCollectionController::GetBrowserHistogram(
147 const std::string
& histogram_name
) {
148 return GetHistogram(histogram_name
);
151 } // namespace html_viewer