// Copyright 2013 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 "content/renderer/stats_collection_controller.h" #include "base/json/json_writer.h" #include "base/metrics/histogram.h" #include "base/metrics/statistics_recorder.h" #include "base/strings/string_util.h" #include "content/common/child_process_messages.h" #include "content/renderer/render_view_impl.h" #include "gin/handle.h" #include "gin/object_template_builder.h" #include "gin/per_isolate_data.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebView.h" namespace content { namespace { bool CurrentRenderViewImpl(RenderViewImpl** out) { blink::WebFrame* web_frame = blink::WebFrame::frameForCurrentContext(); if (!web_frame) return false; blink::WebView* web_view = web_frame->view(); if (!web_view) return false; RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view); if (!render_view_impl) return false; *out = render_view_impl; return true; } // Encodes a WebContentsLoadTime as JSON. // Input: // - |load_start_time| - time at which page load started. // - |load_stop_time| - time at which page load stopped. // - |result| - returned JSON. // Example return value: // {'load_start_ms': 1, 'load_duration_ms': 2.5} // either value may be null if a web contents hasn't fully loaded. // load_start_ms is represented as milliseconds since system boot. void ConvertLoadTimeToJSON( const base::Time& load_start_time, const base::Time& load_stop_time, std::string *result) { base::DictionaryValue item; if (load_start_time.is_null()) { item.Set("load_start_ms", base::Value::CreateNullValue()); } else { item.SetDouble("load_start_ms", load_start_time.ToInternalValue() / 1000); } if (load_start_time.is_null() || load_stop_time.is_null()) { item.Set("load_duration_ms", base::Value::CreateNullValue()); } else { item.SetDouble("load_duration_ms", (load_stop_time - load_start_time).InMillisecondsF()); } base::JSONWriter::Write(&item, result); } } // namespace // static gin::WrapperInfo StatsCollectionController::kWrapperInfo = { gin::kEmbedderNativeGin }; // static void StatsCollectionController::Install(blink::WebFrame* frame) { v8::Isolate* isolate = blink::mainThreadIsolate(); v8::HandleScope handle_scope(isolate); v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); if (context.IsEmpty()) return; v8::Context::Scope context_scope(context); gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); if (data->GetObjectTemplate(&StatsCollectionController::kWrapperInfo) .IsEmpty()) { v8::Handle<v8::ObjectTemplate> templ = gin::ObjectTemplateBuilder(isolate) .SetMethod("getHistogram", &StatsCollectionController::GetHistogram) .SetMethod("getBrowserHistogram", &StatsCollectionController::GetBrowserHistogram) .SetMethod("tabLoadTiming", &StatsCollectionController::GetTabLoadTiming) .Build(); templ->SetInternalFieldCount(gin::kNumberOfInternalFields); data->SetObjectTemplate(&StatsCollectionController::kWrapperInfo, templ); } gin::Handle<StatsCollectionController> controller = gin::CreateHandle(isolate, new StatsCollectionController()); v8::Handle<v8::Object> global = context->Global(); global->Set(gin::StringToV8(isolate, "statsCollectionController"), controller.ToV8()); } StatsCollectionController::StatsCollectionController() {} StatsCollectionController::~StatsCollectionController() {} std::string StatsCollectionController::GetHistogram( const std::string& histogram_name) { base::HistogramBase* histogram = base::StatisticsRecorder::FindHistogram(histogram_name); std::string output; if (!histogram) { output = "{}"; } else { histogram->WriteJSON(&output); } return output; } std::string StatsCollectionController::GetBrowserHistogram( const std::string& histogram_name) { RenderViewImpl *render_view_impl = NULL; if (!CurrentRenderViewImpl(&render_view_impl)) { NOTREACHED(); return std::string(); } std::string histogram_json; render_view_impl->Send(new ChildProcessHostMsg_GetBrowserHistogram( histogram_name, &histogram_json)); return histogram_json; } std::string StatsCollectionController::GetTabLoadTiming() { RenderViewImpl *render_view_impl = NULL; if (!CurrentRenderViewImpl(&render_view_impl)) { NOTREACHED(); return std::string(); } StatsCollectionObserver* observer = render_view_impl->GetStatsCollectionObserver(); if (!observer) { NOTREACHED(); return std::string(); } std::string tab_timing_json; ConvertLoadTimeToJSON( observer->load_start_time(), observer->load_stop_time(), &tab_timing_json); return tab_timing_json; } } // namespace content