Chromium Code Reviews| 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 |