| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/html_viewer/stats_collection_controller.h" |
| |
| #include "base/command_line.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/metrics/histogram.h" |
| #include "base/metrics/statistics_recorder.h" |
| #include "base/time/time.h" |
| #include "components/startup_metric_utils/startup_metric_utils.h" |
| #include "gin/handle.h" |
| #include "gin/object_template_builder.h" |
| #include "mojo/application/public/cpp/application_impl.h" |
| #include "mojo/services/tracing/public/cpp/switches.h" |
| #include "third_party/WebKit/public/web/WebKit.h" |
| #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| |
| namespace html_viewer { |
| |
| namespace { |
| |
| // Initialize the histogram data using the given startup performance times. |
| // TODO(msw): Use TimeTicks to avoid system clock changes: crbug.com/521164 |
| void GetStartupPerformanceTimesCallbackImpl( |
| tracing::StartupPerformanceTimesPtr times) { |
| base::StatisticsRecorder::Initialize(); |
| |
| startup_metric_utils::RecordStartupProcessCreationTime( |
| base::Time::FromInternalValue(times->shell_process_creation_time)); |
| |
| // TODO(msw): Record the MojoMain() entry point time of mojo:browser instead? |
| startup_metric_utils::RecordMainEntryPointTime( |
| base::Time::FromInternalValue(times->shell_main_entry_point_time)); |
| |
| // TODO(msw): Determine if this is the first run. |
| startup_metric_utils::RecordBrowserMainMessageLoopStart( |
| base::Time::FromInternalValue(times->browser_message_loop_start_time), |
| false); |
| |
| startup_metric_utils::RecordBrowserWindowDisplay( |
| base::Time::FromInternalValue(times->browser_window_display_time)); |
| |
| startup_metric_utils::RecordBrowserOpenTabsDelta( |
| base::TimeDelta::FromInternalValue(times->browser_open_tabs_time_delta)); |
| |
| startup_metric_utils::RecordFirstWebContentsMainFrameLoad( |
| base::Time::FromInternalValue( |
| times->first_web_contents_main_frame_load_time)); |
| |
| startup_metric_utils::RecordFirstWebContentsNonEmptyPaint( |
| base::Time::FromInternalValue( |
| times->first_visually_non_empty_layout_time)); |
| } |
| |
| } // namespace |
| |
| // static |
| gin::WrapperInfo StatsCollectionController::kWrapperInfo = { |
| gin::kEmbedderNativeGin}; |
| |
| // static |
| tracing::StartupPerformanceDataCollectorPtr StatsCollectionController::Install( |
| blink::WebFrame* frame, |
| mojo::ApplicationImpl* app) { |
| // Only make startup tracing available when running in the context of a test. |
| if (!app || |
| !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| tracing::kEnableStatsCollectionBindings)) { |
| return nullptr; |
| } |
| |
| v8::Isolate* isolate = blink::mainThreadIsolate(); |
| v8::HandleScope handle_scope(isolate); |
| v8::Local<v8::Context> context = frame->mainWorldScriptContext(); |
| if (context.IsEmpty()) |
| return nullptr; |
| |
| v8::Context::Scope context_scope(context); |
| |
| mojo::URLRequestPtr request(mojo::URLRequest::New()); |
| request->url = mojo::String::From("mojo:tracing"); |
| scoped_ptr<mojo::ApplicationConnection> connection = |
| app->ConnectToApplication(request.Pass()); |
| if (!connection) |
| return nullptr; |
| tracing::StartupPerformanceDataCollectorPtr collector_for_controller; |
| tracing::StartupPerformanceDataCollectorPtr collector_for_caller; |
| connection->ConnectToService(&collector_for_controller); |
| connection->ConnectToService(&collector_for_caller); |
| |
| gin::Handle<StatsCollectionController> controller = gin::CreateHandle( |
| isolate, new StatsCollectionController(collector_for_controller.Pass())); |
| DCHECK(!controller.IsEmpty()); |
| v8::Local<v8::Object> global = context->Global(); |
| global->Set(gin::StringToV8(isolate, "statsCollectionController"), |
| controller.ToV8()); |
| return collector_for_caller.Pass(); |
| } |
| |
| // static |
| tracing::StartupPerformanceDataCollectorPtr |
| StatsCollectionController::ConnectToDataCollector(mojo::ApplicationImpl* app) { |
| // Only make startup tracing available when running in the context of a test. |
| if (!app || |
| !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| tracing::kEnableStatsCollectionBindings)) { |
| return nullptr; |
| } |
| |
| mojo::URLRequestPtr request(mojo::URLRequest::New()); |
| request->url = mojo::String::From("mojo:tracing"); |
| tracing::StartupPerformanceDataCollectorPtr collector; |
| app->ConnectToService(request.Pass(), &collector); |
| return collector.Pass(); |
| } |
| |
| StatsCollectionController::StatsCollectionController( |
| tracing::StartupPerformanceDataCollectorPtr collector) |
| : startup_performance_data_collector_(collector.Pass()) {} |
| |
| StatsCollectionController::~StatsCollectionController() {} |
| |
| gin::ObjectTemplateBuilder StatsCollectionController::GetObjectTemplateBuilder( |
| v8::Isolate* isolate) { |
| return gin::Wrappable<StatsCollectionController>::GetObjectTemplateBuilder( |
| isolate) |
| .SetMethod("getHistogram", &StatsCollectionController::GetHistogram) |
| .SetMethod("getBrowserHistogram", |
| &StatsCollectionController::GetBrowserHistogram); |
| } |
| |
| std::string StatsCollectionController::GetHistogram( |
| const std::string& histogram_name) { |
| DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( |
| tracing::kEnableStatsCollectionBindings)); |
| |
| static bool startup_histogram_initialized = false; |
| if (!startup_histogram_initialized) { |
| // Get the startup performance times from the tracing service. |
| auto callback = base::Bind(&GetStartupPerformanceTimesCallbackImpl); |
| startup_performance_data_collector_->GetStartupPerformanceTimes(callback); |
| startup_performance_data_collector_.WaitForIncomingResponse(); |
| DCHECK(base::StatisticsRecorder::IsActive()); |
| startup_histogram_initialized = true; |
| } |
| |
| std::string histogram_json = "{}"; |
| base::HistogramBase* histogram = |
| base::StatisticsRecorder::FindHistogram(histogram_name); |
| if (histogram) |
| histogram->WriteJSON(&histogram_json); |
| return histogram_json; |
| } |
| |
| std::string StatsCollectionController::GetBrowserHistogram( |
| const std::string& histogram_name) { |
| return GetHistogram(histogram_name); |
| } |
| |
| } // namespace html_viewer |