1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/renderer/stats_collection_controller.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/json/json_writer.h" 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/metrics/histogram.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/metrics/statistics_recorder.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/child_process_messages.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/renderer/render_view_impl.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/handle.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/object_template_builder.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/web/WebKit.h" 16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "third_party/WebKit/public/web/WebLocalFrame.h" 177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebView.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content { 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace { 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool CurrentRenderViewImpl(RenderViewImpl** out) { 24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch blink::WebLocalFrame* web_frame = 25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch blink::WebLocalFrame::frameForCurrentContext(); 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!web_frame) 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebView* web_view = web_frame->view(); 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!web_view) 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RenderViewImpl* render_view_impl = 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RenderViewImpl::FromWebView(web_view); 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!render_view_impl) 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *out = render_view_impl; 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return true; 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Encodes a WebContentsLoadTime as JSON. 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Input: 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// - |load_start_time| - time at which page load started. 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// - |load_stop_time| - time at which page load stopped. 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// - |result| - returned JSON. 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Example return value: 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// {'load_start_ms': 1, 'load_duration_ms': 2.5} 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// either value may be null if a web contents hasn't fully loaded. 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// load_start_ms is represented as milliseconds since the unix epoch. 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ConvertLoadTimeToJSON( 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::Time& load_start_time, 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::Time& load_stop_time, 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string *result) { 557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue item; 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (load_start_time.is_null()) { 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) item.Set("load_start_ms", base::Value::CreateNullValue()); 59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci item.SetDouble("load_start_ms", (load_start_time - base::Time::UnixEpoch()) 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci .InMillisecondsF()); 62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (load_start_time.is_null() || load_stop_time.is_null()) { 647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) item.Set("load_duration_ms", base::Value::CreateNullValue()); 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) item.SetDouble("load_duration_ms", 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) (load_stop_time - load_start_time).InMillisecondsF()); 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::JSONWriter::Write(&item, result); 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gin::WrapperInfo StatsCollectionController::kWrapperInfo = { 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gin::kEmbedderNativeGin 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void StatsCollectionController::Install(blink::WebFrame* frame) { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Isolate* isolate = blink::mainThreadIsolate(); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::HandleScope handle_scope(isolate); 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (context.IsEmpty()) 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Context::Scope context_scope(context); 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gin::Handle<StatsCollectionController> controller = 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gin::CreateHandle(isolate, new StatsCollectionController()); 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (controller.IsEmpty()) 925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Object> global = context->Global(); 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) global->Set(gin::StringToV8(isolate, "statsCollectionController"), 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller.ToV8()); 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)StatsCollectionController::StatsCollectionController() {} 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)StatsCollectionController::~StatsCollectionController() {} 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gin::ObjectTemplateBuilder StatsCollectionController::GetObjectTemplateBuilder( 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Isolate* isolate) { 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return gin::Wrappable<StatsCollectionController>::GetObjectTemplateBuilder( 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) isolate) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .SetMethod("getHistogram", &StatsCollectionController::GetHistogram) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .SetMethod("getBrowserHistogram", 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &StatsCollectionController::GetBrowserHistogram) 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .SetMethod("tabLoadTiming", &StatsCollectionController::GetTabLoadTiming); 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string StatsCollectionController::GetHistogram( 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& histogram_name) { 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::HistogramBase* histogram = 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::StatisticsRecorder::FindHistogram(histogram_name); 116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string output; 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!histogram) { 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) output = "{}"; 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) histogram->WriteJSON(&output); 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return output; 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string StatsCollectionController::GetBrowserHistogram( 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& histogram_name) { 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RenderViewImpl *render_view_impl = NULL; 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!CurrentRenderViewImpl(&render_view_impl)) { 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NOTREACHED(); 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return std::string(); 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string histogram_json; 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) render_view_impl->Send(new ChildProcessHostMsg_GetBrowserHistogram( 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) histogram_name, &histogram_json)); 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return histogram_json; 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string StatsCollectionController::GetTabLoadTiming() { 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RenderViewImpl *render_view_impl = NULL; 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!CurrentRenderViewImpl(&render_view_impl)) { 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NOTREACHED(); 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return std::string(); 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) StatsCollectionObserver* observer = 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) render_view_impl->GetStatsCollectionObserver(); 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!observer) { 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NOTREACHED(); 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return std::string(); 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string tab_timing_json; 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ConvertLoadTimeToJSON( 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) observer->load_start_time(), observer->load_stop_time(), 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &tab_timing_json); 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return tab_timing_json; 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace content 161