1// Copyright 2013 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 "content/renderer/stats_collection_controller.h" 6 7#include "base/json/json_writer.h" 8#include "base/metrics/histogram.h" 9#include "base/metrics/statistics_recorder.h" 10#include "base/strings/string_util.h" 11#include "content/common/child_process_messages.h" 12#include "content/renderer/render_view_impl.h" 13#include "gin/handle.h" 14#include "gin/object_template_builder.h" 15#include "third_party/WebKit/public/web/WebKit.h" 16#include "third_party/WebKit/public/web/WebLocalFrame.h" 17#include "third_party/WebKit/public/web/WebView.h" 18 19namespace content { 20 21namespace { 22 23bool CurrentRenderViewImpl(RenderViewImpl** out) { 24 blink::WebLocalFrame* web_frame = 25 blink::WebLocalFrame::frameForCurrentContext(); 26 if (!web_frame) 27 return false; 28 29 blink::WebView* web_view = web_frame->view(); 30 if (!web_view) 31 return false; 32 33 RenderViewImpl* render_view_impl = 34 RenderViewImpl::FromWebView(web_view); 35 if (!render_view_impl) 36 return false; 37 38 *out = render_view_impl; 39 return true; 40} 41 42// Encodes a WebContentsLoadTime as JSON. 43// Input: 44// - |load_start_time| - time at which page load started. 45// - |load_stop_time| - time at which page load stopped. 46// - |result| - returned JSON. 47// Example return value: 48// {'load_start_ms': 1, 'load_duration_ms': 2.5} 49// either value may be null if a web contents hasn't fully loaded. 50// load_start_ms is represented as milliseconds since the unix epoch. 51void ConvertLoadTimeToJSON( 52 const base::Time& load_start_time, 53 const base::Time& load_stop_time, 54 std::string *result) { 55 base::DictionaryValue item; 56 57 if (load_start_time.is_null()) { 58 item.Set("load_start_ms", base::Value::CreateNullValue()); 59 } else { 60 item.SetDouble("load_start_ms", (load_start_time - base::Time::UnixEpoch()) 61 .InMillisecondsF()); 62 } 63 if (load_start_time.is_null() || load_stop_time.is_null()) { 64 item.Set("load_duration_ms", base::Value::CreateNullValue()); 65 } else { 66 item.SetDouble("load_duration_ms", 67 (load_stop_time - load_start_time).InMillisecondsF()); 68 } 69 base::JSONWriter::Write(&item, result); 70} 71 72} // namespace 73 74// static 75gin::WrapperInfo StatsCollectionController::kWrapperInfo = { 76 gin::kEmbedderNativeGin 77}; 78 79// static 80void StatsCollectionController::Install(blink::WebFrame* frame) { 81 v8::Isolate* isolate = blink::mainThreadIsolate(); 82 v8::HandleScope handle_scope(isolate); 83 v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); 84 if (context.IsEmpty()) 85 return; 86 87 v8::Context::Scope context_scope(context); 88 89 gin::Handle<StatsCollectionController> controller = 90 gin::CreateHandle(isolate, new StatsCollectionController()); 91 if (controller.IsEmpty()) 92 return; 93 v8::Handle<v8::Object> global = context->Global(); 94 global->Set(gin::StringToV8(isolate, "statsCollectionController"), 95 controller.ToV8()); 96} 97 98StatsCollectionController::StatsCollectionController() {} 99 100StatsCollectionController::~StatsCollectionController() {} 101 102gin::ObjectTemplateBuilder StatsCollectionController::GetObjectTemplateBuilder( 103 v8::Isolate* isolate) { 104 return gin::Wrappable<StatsCollectionController>::GetObjectTemplateBuilder( 105 isolate) 106 .SetMethod("getHistogram", &StatsCollectionController::GetHistogram) 107 .SetMethod("getBrowserHistogram", 108 &StatsCollectionController::GetBrowserHistogram) 109 .SetMethod("tabLoadTiming", &StatsCollectionController::GetTabLoadTiming); 110} 111 112std::string StatsCollectionController::GetHistogram( 113 const std::string& histogram_name) { 114 base::HistogramBase* histogram = 115 base::StatisticsRecorder::FindHistogram(histogram_name); 116 std::string output; 117 if (!histogram) { 118 output = "{}"; 119 } else { 120 histogram->WriteJSON(&output); 121 } 122 return output; 123} 124 125std::string StatsCollectionController::GetBrowserHistogram( 126 const std::string& histogram_name) { 127 RenderViewImpl *render_view_impl = NULL; 128 if (!CurrentRenderViewImpl(&render_view_impl)) { 129 NOTREACHED(); 130 return std::string(); 131 } 132 133 std::string histogram_json; 134 render_view_impl->Send(new ChildProcessHostMsg_GetBrowserHistogram( 135 histogram_name, &histogram_json)); 136 return histogram_json; 137} 138 139std::string StatsCollectionController::GetTabLoadTiming() { 140 RenderViewImpl *render_view_impl = NULL; 141 if (!CurrentRenderViewImpl(&render_view_impl)) { 142 NOTREACHED(); 143 return std::string(); 144 } 145 146 StatsCollectionObserver* observer = 147 render_view_impl->GetStatsCollectionObserver(); 148 if (!observer) { 149 NOTREACHED(); 150 return std::string(); 151 } 152 153 std::string tab_timing_json; 154 ConvertLoadTimeToJSON( 155 observer->load_start_time(), observer->load_stop_time(), 156 &tab_timing_json); 157 return tab_timing_json; 158} 159 160} // namespace content 161