Home | History | Annotate | Download | only in renderer
      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 "gin/per_isolate_data.h"
     16 #include "third_party/WebKit/public/web/WebFrame.h"
     17 #include "third_party/WebKit/public/web/WebKit.h"
     18 #include "third_party/WebKit/public/web/WebView.h"
     19 
     20 namespace content {
     21 
     22 namespace {
     23 
     24 bool CurrentRenderViewImpl(RenderViewImpl** out) {
     25   blink::WebFrame* web_frame = blink::WebFrame::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 system boot.
     51 void 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.ToInternalValue() / 1000);
     61   }
     62   if (load_start_time.is_null() || load_stop_time.is_null()) {
     63     item.Set("load_duration_ms", base::Value::CreateNullValue());
     64   } else {
     65     item.SetDouble("load_duration_ms",
     66         (load_stop_time - load_start_time).InMillisecondsF());
     67   }
     68   base::JSONWriter::Write(&item, result);
     69 }
     70 
     71 }  // namespace
     72 
     73 // static
     74 gin::WrapperInfo StatsCollectionController::kWrapperInfo = {
     75     gin::kEmbedderNativeGin
     76 };
     77 
     78 // static
     79 void StatsCollectionController::Install(blink::WebFrame* frame) {
     80   v8::Isolate* isolate = blink::mainThreadIsolate();
     81   v8::HandleScope handle_scope(isolate);
     82   v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
     83   if (context.IsEmpty())
     84     return;
     85 
     86   v8::Context::Scope context_scope(context);
     87 
     88   gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
     89   if (data->GetObjectTemplate(&StatsCollectionController::kWrapperInfo)
     90           .IsEmpty()) {
     91     v8::Handle<v8::ObjectTemplate> templ =
     92         gin::ObjectTemplateBuilder(isolate)
     93             .SetMethod("getHistogram", &StatsCollectionController::GetHistogram)
     94             .SetMethod("getBrowserHistogram",
     95                        &StatsCollectionController::GetBrowserHistogram)
     96             .SetMethod("tabLoadTiming",
     97                        &StatsCollectionController::GetTabLoadTiming)
     98             .Build();
     99     templ->SetInternalFieldCount(gin::kNumberOfInternalFields);
    100     data->SetObjectTemplate(&StatsCollectionController::kWrapperInfo, templ);
    101   }
    102 
    103   gin::Handle<StatsCollectionController> controller =
    104       gin::CreateHandle(isolate, new StatsCollectionController());
    105   v8::Handle<v8::Object> global = context->Global();
    106   global->Set(gin::StringToV8(isolate, "statsCollectionController"),
    107               controller.ToV8());
    108 }
    109 
    110 StatsCollectionController::StatsCollectionController() {}
    111 
    112 StatsCollectionController::~StatsCollectionController() {}
    113 
    114 std::string StatsCollectionController::GetHistogram(
    115     const std::string& histogram_name) {
    116   base::HistogramBase* histogram =
    117       base::StatisticsRecorder::FindHistogram(histogram_name);
    118   std::string output;
    119   if (!histogram) {
    120     output = "{}";
    121   } else {
    122     histogram->WriteJSON(&output);
    123   }
    124   return output;
    125 }
    126 
    127 std::string StatsCollectionController::GetBrowserHistogram(
    128     const std::string& histogram_name) {
    129   RenderViewImpl *render_view_impl = NULL;
    130   if (!CurrentRenderViewImpl(&render_view_impl)) {
    131     NOTREACHED();
    132     return std::string();
    133   }
    134 
    135   std::string histogram_json;
    136   render_view_impl->Send(new ChildProcessHostMsg_GetBrowserHistogram(
    137       histogram_name, &histogram_json));
    138   return histogram_json;
    139 }
    140 
    141 std::string StatsCollectionController::GetTabLoadTiming() {
    142   RenderViewImpl *render_view_impl = NULL;
    143   if (!CurrentRenderViewImpl(&render_view_impl)) {
    144     NOTREACHED();
    145     return std::string();
    146   }
    147 
    148   StatsCollectionObserver* observer =
    149       render_view_impl->GetStatsCollectionObserver();
    150   if (!observer) {
    151     NOTREACHED();
    152     return std::string();
    153   }
    154 
    155   std::string tab_timing_json;
    156   ConvertLoadTimeToJSON(
    157       observer->load_start_time(), observer->load_stop_time(),
    158       &tab_timing_json);
    159   return tab_timing_json;
    160 }
    161 
    162 }  // namespace content
    163