blob: ed3fc2e039f2075317d8a71ee85c24b68424a35a [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"
jdoerriee067999a2017-04-07 06:39:008#include "base/memory/ptr_util.h"
Tarun Bansal89684a72017-11-29 14:44:129#include "base/metrics/histogram_base.h"
asvitkine8d51e9d2016-09-02 23:55:4310#include "base/metrics/histogram_macros.h"
[email protected]27c521a2013-05-29 20:44:3211#include "base/metrics/statistics_recorder.h"
[email protected]21aa99682013-06-11 07:17:0112#include "base/strings/string_util.h"
Nicholas Verne2ba2b8fe2017-10-20 04:00:3113#include "content/common/renderer_host.mojom.h"
14#include "content/public/common/service_names.mojom.h"
15#include "content/renderer/render_thread_impl.h"
[email protected]27c521a2013-05-29 20:44:3216#include "content/renderer/render_view_impl.h"
[email protected]a79712f2013-12-13 21:33:2517#include "gin/handle.h"
18#include "gin/object_template_builder.h"
Nicholas Verne2ba2b8fe2017-10-20 04:00:3119#include "services/service_manager/public/cpp/connector.h"
[email protected]a79712f2013-12-13 21:33:2520#include "third_party/WebKit/public/web/WebKit.h"
[email protected]d3576942014-04-10 18:45:3721#include "third_party/WebKit/public/web/WebLocalFrame.h"
[email protected]2255a9332013-06-17 05:12:3122#include "third_party/WebKit/public/web/WebView.h"
[email protected]27c521a2013-05-29 20:44:3223
[email protected]27c521a2013-05-29 20:44:3224namespace content {
25
26namespace {
27
28bool CurrentRenderViewImpl(RenderViewImpl** out) {
[email protected]d3576942014-04-10 18:45:3729 blink::WebLocalFrame* web_frame =
Blink Reformat1c4d759e2017-04-09 16:34:5430 blink::WebLocalFrame::FrameForCurrentContext();
[email protected]27c521a2013-05-29 20:44:3231 if (!web_frame)
32 return false;
33
Blink Reformat1c4d759e2017-04-09 16:34:5434 blink::WebView* web_view = web_frame->View();
[email protected]27c521a2013-05-29 20:44:3235 if (!web_view)
36 return false;
37
38 RenderViewImpl* render_view_impl =
39 RenderViewImpl::FromWebView(web_view);
40 if (!render_view_impl)
41 return false;
42
43 *out = render_view_impl;
44 return true;
45}
46
47// Encodes a WebContentsLoadTime as JSON.
48// Input:
49// - |load_start_time| - time at which page load started.
50// - |load_stop_time| - time at which page load stopped.
51// - |result| - returned JSON.
52// Example return value:
53// {'load_start_ms': 1, 'load_duration_ms': 2.5}
54// either value may be null if a web contents hasn't fully loaded.
azarchs8cc4ec72014-09-16 19:23:0355// load_start_ms is represented as milliseconds since the unix epoch.
[email protected]27c521a2013-05-29 20:44:3256void ConvertLoadTimeToJSON(
[email protected]538dde872013-11-19 16:44:1757 const base::Time& load_start_time,
58 const base::Time& load_stop_time,
[email protected]27c521a2013-05-29 20:44:3259 std::string *result) {
[email protected]716775252013-06-14 17:58:0060 base::DictionaryValue item;
[email protected]27c521a2013-05-29 20:44:3261
62 if (load_start_time.is_null()) {
Jeremy Roman04f27c372017-10-27 15:20:5563 item.Set("load_start_ms", std::make_unique<base::Value>());
[email protected]27c521a2013-05-29 20:44:3264 } else {
azarchs8cc4ec72014-09-16 19:23:0365 item.SetDouble("load_start_ms", (load_start_time - base::Time::UnixEpoch())
66 .InMillisecondsF());
[email protected]27c521a2013-05-29 20:44:3267 }
[email protected]c81e3fd2013-08-05 16:30:2268 if (load_start_time.is_null() || load_stop_time.is_null()) {
Jeremy Roman04f27c372017-10-27 15:20:5569 item.Set("load_duration_ms", std::make_unique<base::Value>());
[email protected]27c521a2013-05-29 20:44:3270 } else {
71 item.SetDouble("load_duration_ms",
[email protected]538dde872013-11-19 16:44:1772 (load_stop_time - load_start_time).InMillisecondsF());
[email protected]27c521a2013-05-29 20:44:3273 }
estade8d046462015-05-16 01:02:3474 base::JSONWriter::Write(item, result);
[email protected]27c521a2013-05-29 20:44:3275}
76
77} // namespace
78
[email protected]a79712f2013-12-13 21:33:2579// static
80gin::WrapperInfo StatsCollectionController::kWrapperInfo = {
81 gin::kEmbedderNativeGin
82};
83
84// static
lukaszadf18ba762017-06-09 22:24:3085void StatsCollectionController::Install(blink::WebLocalFrame* frame) {
Blink Reformat1c4d759e2017-04-09 16:34:5486 v8::Isolate* isolate = blink::MainThreadIsolate();
[email protected]a79712f2013-12-13 21:33:2587 v8::HandleScope handle_scope(isolate);
Blink Reformat1c4d759e2017-04-09 16:34:5488 v8::Local<v8::Context> context = frame->MainWorldScriptContext();
[email protected]a79712f2013-12-13 21:33:2589 if (context.IsEmpty())
90 return;
91
92 v8::Context::Scope context_scope(context);
93
[email protected]a79712f2013-12-13 21:33:2594 gin::Handle<StatsCollectionController> controller =
95 gin::CreateHandle(isolate, new StatsCollectionController());
[email protected]ad4d2032014-04-28 13:50:5996 if (controller.IsEmpty())
97 return;
deepak.s750d68f2015-04-30 07:32:4198 v8::Local<v8::Object> global = context->Global();
[email protected]a79712f2013-12-13 21:33:2599 global->Set(gin::StringToV8(isolate, "statsCollectionController"),
100 controller.ToV8());
[email protected]27c521a2013-05-29 20:44:32101}
102
[email protected]a79712f2013-12-13 21:33:25103StatsCollectionController::StatsCollectionController() {}
104
105StatsCollectionController::~StatsCollectionController() {}
106
[email protected]13c977e62013-12-19 00:52:44107gin::ObjectTemplateBuilder StatsCollectionController::GetObjectTemplateBuilder(
108 v8::Isolate* isolate) {
109 return gin::Wrappable<StatsCollectionController>::GetObjectTemplateBuilder(
110 isolate)
111 .SetMethod("getHistogram", &StatsCollectionController::GetHistogram)
112 .SetMethod("getBrowserHistogram",
113 &StatsCollectionController::GetBrowserHistogram)
114 .SetMethod("tabLoadTiming", &StatsCollectionController::GetTabLoadTiming);
115}
116
[email protected]a79712f2013-12-13 21:33:25117std::string StatsCollectionController::GetHistogram(
118 const std::string& histogram_name) {
[email protected]27c521a2013-05-29 20:44:32119 base::HistogramBase* histogram =
[email protected]a79712f2013-12-13 21:33:25120 base::StatisticsRecorder::FindHistogram(histogram_name);
[email protected]27c521a2013-05-29 20:44:32121 std::string output;
122 if (!histogram) {
123 output = "{}";
124 } else {
Tarun Bansal89684a72017-11-29 14:44:12125 histogram->WriteJSON(&output, base::JSON_VERBOSITY_LEVEL_FULL);
[email protected]27c521a2013-05-29 20:44:32126 }
[email protected]a79712f2013-12-13 21:33:25127 return output;
[email protected]27c521a2013-05-29 20:44:32128}
129
[email protected]a79712f2013-12-13 21:33:25130std::string StatsCollectionController::GetBrowserHistogram(
131 const std::string& histogram_name) {
[email protected]a79712f2013-12-13 21:33:25132 std::string histogram_json;
Nicholas Verne2ba2b8fe2017-10-20 04:00:31133 RenderThreadImpl::current()->GetRendererHost()->GetBrowserHistogram(
134 histogram_name, &histogram_json);
135
[email protected]a79712f2013-12-13 21:33:25136 return histogram_json;
137}
138
139std::string StatsCollectionController::GetTabLoadTiming() {
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28140 RenderViewImpl* render_view_impl = nullptr;
Nicholas Verne2ba2b8fe2017-10-20 04:00:31141 bool result = CurrentRenderViewImpl(&render_view_impl);
142 DCHECK(result);
[email protected]27c521a2013-05-29 20:44:32143
144 StatsCollectionObserver* observer =
145 render_view_impl->GetStatsCollectionObserver();
Nicholas Verne2ba2b8fe2017-10-20 04:00:31146 DCHECK(observer);
[email protected]27c521a2013-05-29 20:44:32147
148 std::string tab_timing_json;
149 ConvertLoadTimeToJSON(
150 observer->load_start_time(), observer->load_stop_time(),
151 &tab_timing_json);
[email protected]a79712f2013-12-13 21:33:25152 return tab_timing_json;
[email protected]27c521a2013-05-29 20:44:32153}
154
155} // namespace content