OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "components/html_viewer/stats_collection_controller.h" | |
6 | |
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" | |
19 | |
20 namespace html_viewer { | |
21 | |
22 namespace { | |
23 | |
24 // Initialize the histogram data using the given startup performance times. | |
25 // TODO(msw): Have mojo:tracing record the histograms and serve their JSON? | |
26 // TODO(msw): Use TimeTicks to avoid system clock changes: crbug.com/521164 | |
27 void GetStartupPerformanceTimesCallbackImpl( | |
28 tracing::StartupPerformanceTimesPtr times) { | |
29 base::StatisticsRecorder::Initialize(); | |
30 | |
31 const base::Time shell_process_creation_time = | |
32 base::Time::FromInternalValue(times->shell_process_creation_time); | |
33 startup_metric_utils::RecordSavedMainEntryPointTime( | |
34 shell_process_creation_time); | |
35 // TODO(msw): Use |browser_message_loop_start_time|, instead of letting | |
36 // OnBrowserStartupComplete incorrectly call base::Time::Now()... | |
37 startup_metric_utils::OnBrowserStartupComplete(false); | |
38 | |
39 // TODO(msw): Consolidate with chrome's Browser::OnWindowDidShow()... | |
40 const base::Time browser_window_display_time = | |
41 base::Time::FromInternalValue(times->browser_window_display_time); | |
42 base::TimeDelta browser_window_display_delta = | |
43 browser_window_display_time - shell_process_creation_time; | |
44 UMA_HISTOGRAM_LONG_TIMES("Startup.BrowserWindowDisplay", | |
45 browser_window_display_delta); | |
46 | |
47 // TODO(msw): Consolidate with chrome's PreMainMessageLoopRunImpl()... | |
48 // TODO(msw): Need to measure the "browser_open_start" time for this delta... | |
49 const base::Time browser_open_tabs_time = | |
50 base::Time::FromInternalValue(times->browser_open_tabs_time); | |
51 base::TimeDelta browser_open_tabs_delta = | |
52 browser_open_tabs_time - shell_process_creation_time; | |
53 UMA_HISTOGRAM_LONG_TIMES_100("Startup.BrowserOpenTabs", | |
54 browser_open_tabs_delta); | |
55 | |
56 // TODO(msw): Consolidate with chrome's first_web_contents_profiler.cc... | |
57 const base::Time first_web_contents_main_frame_load_time = | |
58 base::Time::FromInternalValue( | |
59 times->first_web_contents_main_frame_load_time); | |
60 base::TimeDelta first_web_contents_main_frame_load_delta = | |
61 first_web_contents_main_frame_load_time - shell_process_creation_time; | |
62 UMA_HISTOGRAM_LONG_TIMES_100("Startup.FirstWebContents.MainFrameLoad", | |
63 first_web_contents_main_frame_load_delta); | |
64 | |
65 // TODO(msw): Consolidate with chrome's first_web_contents_profiler.cc... | |
66 const base::Time first_visually_non_empty_layout_time = | |
67 base::Time::FromInternalValue( | |
68 times->first_visually_non_empty_layout_time); | |
69 base::TimeDelta first_web_contents_non_empty_paint_delta = | |
70 first_visually_non_empty_layout_time - shell_process_creation_time; | |
71 UMA_HISTOGRAM_LONG_TIMES_100("Startup.FirstWebContents.NonEmptyPaint", | |
72 first_web_contents_non_empty_paint_delta); | |
73 } | |
74 | |
75 } // namespace | |
76 | |
77 // static | |
78 gin::WrapperInfo StatsCollectionController::kWrapperInfo = { | |
79 gin::kEmbedderNativeGin}; | |
80 | |
81 // static | |
82 tracing::StartupPerformanceDataCollectorPtr StatsCollectionController::Install( | |
83 blink::WebFrame* frame, | |
84 mojo::ApplicationImpl* app) { | |
85 // Only make startup tracing available when running in the context of a test. | |
86 if (!app || | |
87 !base::CommandLine::ForCurrentProcess()->HasSwitch( | |
88 tracing::kEnableStatsCollectionBindings)) { | |
89 return tracing::StartupPerformanceDataCollectorPtr(); | |
yzshen1
2015/08/17 05:46:38
nit, optional: it is still compilable to return nu
msw
2015/08/17 21:25:50
Done; thanks for the tip!
| |
90 } | |
91 | |
92 v8::Isolate* isolate = blink::mainThreadIsolate(); | |
93 v8::HandleScope handle_scope(isolate); | |
94 v8::Local<v8::Context> context = frame->mainWorldScriptContext(); | |
95 if (context.IsEmpty()) | |
96 return tracing::StartupPerformanceDataCollectorPtr(); | |
97 | |
98 v8::Context::Scope context_scope(context); | |
99 | |
100 mojo::URLRequestPtr request(mojo::URLRequest::New()); | |
101 request->url = mojo::String::From("mojo:tracing"); | |
102 scoped_ptr<mojo::ApplicationConnection> connection = | |
103 app->ConnectToApplication(request.Pass()); | |
104 if (!connection.get()) | |
105 return tracing::StartupPerformanceDataCollectorPtr(); | |
106 tracing::StartupPerformanceDataCollectorPtr collector_for_controller; | |
107 tracing::StartupPerformanceDataCollectorPtr collector_for_caller; | |
108 connection->ConnectToService(&collector_for_controller); | |
109 connection->ConnectToService(&collector_for_caller); | |
110 | |
111 StatsCollectionController* stats_collection_controller = | |
yzshen1
2015/08/17 05:46:38
(Out of curiosity) When is this instance destructe
msw
2015/08/17 21:25:50
gin's Handle/Wrappable code and documentation isn'
| |
112 new StatsCollectionController(collector_for_controller.Pass()); | |
113 gin::Handle<StatsCollectionController> controller = | |
114 gin::CreateHandle(isolate, stats_collection_controller); | |
115 if (!controller.IsEmpty()) { | |
116 v8::Local<v8::Object> global = context->Global(); | |
117 global->Set(gin::StringToV8(isolate, "statsCollectionController"), | |
118 controller.ToV8()); | |
119 } | |
120 return collector_for_caller.Pass(); | |
121 } | |
122 | |
123 StatsCollectionController::StatsCollectionController( | |
124 tracing::StartupPerformanceDataCollectorPtr collector) | |
125 : startup_performance_data_collector_(collector.Pass()) {} | |
126 | |
127 StatsCollectionController::~StatsCollectionController() {} | |
128 | |
129 gin::ObjectTemplateBuilder StatsCollectionController::GetObjectTemplateBuilder( | |
130 v8::Isolate* isolate) { | |
131 return gin::Wrappable<StatsCollectionController>::GetObjectTemplateBuilder( | |
132 isolate) | |
133 .SetMethod("getHistogram", &StatsCollectionController::GetHistogram) | |
sky
2015/08/17 20:09:30
What are the life of these bindings? The same as t
msw
2015/08/17 21:25:50
See my comment above, I'd guess that the lifetime
| |
134 .SetMethod("getBrowserHistogram", | |
135 &StatsCollectionController::GetBrowserHistogram); | |
136 } | |
137 | |
138 std::string StatsCollectionController::GetHistogram( | |
139 const std::string& histogram_name) { | |
140 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( | |
141 tracing::kEnableStatsCollectionBindings)); | |
142 | |
143 // TODO(msw): Use a more robust check for startup histogram init. | |
144 if (!base::StatisticsRecorder::IsActive()) { | |
145 // Get the startup performance times from the tracing service. | |
146 // TODO(msw): Have mojo:tracing provide the histogram JSON? | |
147 auto callback = base::Bind(&GetStartupPerformanceTimesCallbackImpl); | |
148 startup_performance_data_collector_->GetStartupPerformanceTimes(callback); | |
149 startup_performance_data_collector_.WaitForIncomingResponse(); | |
150 DCHECK(base::StatisticsRecorder::IsActive()); | |
151 } | |
152 | |
153 std::string histogram_json = "{}"; | |
154 base::HistogramBase* histogram = | |
155 base::StatisticsRecorder::FindHistogram(histogram_name); | |
156 if (histogram) | |
157 histogram->WriteJSON(&histogram_json); | |
158 // TODO(msw): Remove debug printing... | |
159 LOG(ERROR) << "MSW Histogram [" << histogram_name << "]: " << histogram_json; | |
160 return histogram_json; | |
161 } | |
162 | |
163 std::string StatsCollectionController::GetBrowserHistogram( | |
164 const std::string& histogram_name) { | |
165 // TODO(msw): Should GetHistogram/GetBrowserHistogram return distinct values? | |
166 return GetHistogram(histogram_name); | |
167 } | |
168 | |
169 } // namespace html_viewer | |
OLD | NEW |