blob: d528f49e513b63947fb70077740e35bd4b796dbb [file] [log] [blame]
[email protected]27c521a2013-05-29 20:44:321// 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
[email protected]27c521a2013-05-29 20:44:327#include "base/json/json_writer.h"
Tarun Bansal89684a72017-11-29 14:44:128#include "base/metrics/histogram_base.h"
asvitkine8d51e9d2016-09-02 23:55:439#include "base/metrics/histogram_macros.h"
[email protected]27c521a2013-05-29 20:44:3210#include "base/metrics/statistics_recorder.h"
[email protected]21aa99682013-06-11 07:17:0111#include "base/strings/string_util.h"
Nicholas Verne2ba2b8fe2017-10-20 04:00:3112#include "content/common/renderer_host.mojom.h"
13#include "content/public/common/service_names.mojom.h"
14#include "content/renderer/render_thread_impl.h"
[email protected]27c521a2013-05-29 20:44:3215#include "content/renderer/render_view_impl.h"
[email protected]a79712f2013-12-13 21:33:2516#include "gin/handle.h"
17#include "gin/object_template_builder.h"
Nicholas Verne2ba2b8fe2017-10-20 04:00:3118#include "services/service_manager/public/cpp/connector.h"
Blink Reformata30d4232018-04-07 15:31:0619#include "third_party/blink/public/web/blink.h"
20#include "third_party/blink/public/web/web_local_frame.h"
21#include "third_party/blink/public/web/web_view.h"
[email protected]27c521a2013-05-29 20:44:3222
[email protected]27c521a2013-05-29 20:44:3223namespace content {
24
25namespace {
26
27bool CurrentRenderViewImpl(RenderViewImpl** out) {
[email protected]d3576942014-04-10 18:45:3728 blink::WebLocalFrame* web_frame =
Blink Reformat1c4d759e2017-04-09 16:34:5429 blink::WebLocalFrame::FrameForCurrentContext();
[email protected]27c521a2013-05-29 20:44:3230 if (!web_frame)
31 return false;
32
Blink Reformat1c4d759e2017-04-09 16:34:5433 blink::WebView* web_view = web_frame->View();
[email protected]27c521a2013-05-29 20:44:3234 if (!web_view)
35 return false;
36
37 RenderViewImpl* render_view_impl =
38 RenderViewImpl::FromWebView(web_view);
39 if (!render_view_impl)
40 return false;
41
42 *out = render_view_impl;
43 return true;
44}
45
46// Encodes a WebContentsLoadTime as JSON.
47// Input:
48// - |load_start_time| - time at which page load started.
49// - |load_stop_time| - time at which page load stopped.
50// - |result| - returned JSON.
51// Example return value:
52// {'load_start_ms': 1, 'load_duration_ms': 2.5}
53// either value may be null if a web contents hasn't fully loaded.
azarchs8cc4ec72014-09-16 19:23:0354// load_start_ms is represented as milliseconds since the unix epoch.
[email protected]27c521a2013-05-29 20:44:3255void ConvertLoadTimeToJSON(
[email protected]538dde872013-11-19 16:44:1756 const base::Time& load_start_time,
57 const base::Time& load_stop_time,
[email protected]27c521a2013-05-29 20:44:3258 std::string *result) {
[email protected]716775252013-06-14 17:58:0059 base::DictionaryValue item;
[email protected]27c521a2013-05-29 20:44:3260
61 if (load_start_time.is_null()) {
Jeremy Roman04f27c372017-10-27 15:20:5562 item.Set("load_start_ms", std::make_unique<base::Value>());
[email protected]27c521a2013-05-29 20:44:3263 } else {
azarchs8cc4ec72014-09-16 19:23:0364 item.SetDouble("load_start_ms", (load_start_time - base::Time::UnixEpoch())
65 .InMillisecondsF());
[email protected]27c521a2013-05-29 20:44:3266 }
[email protected]c81e3fd2013-08-05 16:30:2267 if (load_start_time.is_null() || load_stop_time.is_null()) {
Jeremy Roman04f27c372017-10-27 15:20:5568 item.Set("load_duration_ms", std::make_unique<base::Value>());
[email protected]27c521a2013-05-29 20:44:3269 } else {
70 item.SetDouble("load_duration_ms",
[email protected]538dde872013-11-19 16:44:1771 (load_stop_time - load_start_time).InMillisecondsF());
[email protected]27c521a2013-05-29 20:44:3272 }
estade8d046462015-05-16 01:02:3473 base::JSONWriter::Write(item, result);
[email protected]27c521a2013-05-29 20:44:3274}
75
76} // namespace
77
[email protected]a79712f2013-12-13 21:33:2578// static
79gin::WrapperInfo StatsCollectionController::kWrapperInfo = {
80 gin::kEmbedderNativeGin
81};
82
83// static
lukaszadf18ba762017-06-09 22:24:3084void StatsCollectionController::Install(blink::WebLocalFrame* frame) {
Blink Reformat1c4d759e2017-04-09 16:34:5485 v8::Isolate* isolate = blink::MainThreadIsolate();
[email protected]a79712f2013-12-13 21:33:2586 v8::HandleScope handle_scope(isolate);
Blink Reformat1c4d759e2017-04-09 16:34:5487 v8::Local<v8::Context> context = frame->MainWorldScriptContext();
[email protected]a79712f2013-12-13 21:33:2588 if (context.IsEmpty())
89 return;
90
91 v8::Context::Scope context_scope(context);
92
[email protected]a79712f2013-12-13 21:33:2593 gin::Handle<StatsCollectionController> controller =
94 gin::CreateHandle(isolate, new StatsCollectionController());
[email protected]ad4d2032014-04-28 13:50:5995 if (controller.IsEmpty())
96 return;
deepak.s750d68f2015-04-30 07:32:4197 v8::Local<v8::Object> global = context->Global();
[email protected]a79712f2013-12-13 21:33:2598 global->Set(gin::StringToV8(isolate, "statsCollectionController"),
99 controller.ToV8());
[email protected]27c521a2013-05-29 20:44:32100}
101
[email protected]a79712f2013-12-13 21:33:25102StatsCollectionController::StatsCollectionController() {}
103
104StatsCollectionController::~StatsCollectionController() {}
105
[email protected]13c977e62013-12-19 00:52:44106gin::ObjectTemplateBuilder StatsCollectionController::GetObjectTemplateBuilder(
107 v8::Isolate* isolate) {
108 return gin::Wrappable<StatsCollectionController>::GetObjectTemplateBuilder(
109 isolate)
110 .SetMethod("getHistogram", &StatsCollectionController::GetHistogram)
111 .SetMethod("getBrowserHistogram",
112 &StatsCollectionController::GetBrowserHistogram)
113 .SetMethod("tabLoadTiming", &StatsCollectionController::GetTabLoadTiming);
114}
115
[email protected]a79712f2013-12-13 21:33:25116std::string StatsCollectionController::GetHistogram(
117 const std::string& histogram_name) {
[email protected]27c521a2013-05-29 20:44:32118 base::HistogramBase* histogram =
[email protected]a79712f2013-12-13 21:33:25119 base::StatisticsRecorder::FindHistogram(histogram_name);
[email protected]27c521a2013-05-29 20:44:32120 std::string output;
121 if (!histogram) {
122 output = "{}";
123 } else {
Tarun Bansal89684a72017-11-29 14:44:12124 histogram->WriteJSON(&output, base::JSON_VERBOSITY_LEVEL_FULL);
[email protected]27c521a2013-05-29 20:44:32125 }
[email protected]a79712f2013-12-13 21:33:25126 return output;
[email protected]27c521a2013-05-29 20:44:32127}
128
[email protected]a79712f2013-12-13 21:33:25129std::string StatsCollectionController::GetBrowserHistogram(
130 const std::string& histogram_name) {
[email protected]a79712f2013-12-13 21:33:25131 std::string histogram_json;
Nicholas Verne2ba2b8fe2017-10-20 04:00:31132 RenderThreadImpl::current()->GetRendererHost()->GetBrowserHistogram(
133 histogram_name, &histogram_json);
134
[email protected]a79712f2013-12-13 21:33:25135 return histogram_json;
136}
137
138std::string StatsCollectionController::GetTabLoadTiming() {
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28139 RenderViewImpl* render_view_impl = nullptr;
Nicholas Verne2ba2b8fe2017-10-20 04:00:31140 bool result = CurrentRenderViewImpl(&render_view_impl);
141 DCHECK(result);
[email protected]27c521a2013-05-29 20:44:32142
143 StatsCollectionObserver* observer =
144 render_view_impl->GetStatsCollectionObserver();
Nicholas Verne2ba2b8fe2017-10-20 04:00:31145 DCHECK(observer);
[email protected]27c521a2013-05-29 20:44:32146
147 std::string tab_timing_json;
148 ConvertLoadTimeToJSON(
149 observer->load_start_time(), observer->load_stop_time(),
150 &tab_timing_json);
[email protected]a79712f2013-12-13 21:33:25151 return tab_timing_json;
[email protected]27c521a2013-05-29 20:44:32152}
153
154} // namespace content