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/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/json/json_writer.h"
     10 #include "base/metrics/histogram.h"
     11 #include "base/metrics/statistics_recorder.h"
     12 #include "base/strings/string_util.h"
     13 #include "content/common/child_process_messages.h"
     14 #include "content/renderer/render_view_impl.h"
     15 #include "third_party/WebKit/public/web/WebFrame.h"
     16 #include "third_party/WebKit/public/web/WebView.h"
     17 
     18 using webkit_glue::CppArgumentList;
     19 using webkit_glue::CppVariant;
     20 
     21 namespace content {
     22 
     23 namespace {
     24 
     25 bool CurrentRenderViewImpl(RenderViewImpl** out) {
     26   WebKit::WebFrame* web_frame = WebKit::WebFrame::frameForCurrentContext();
     27   if (!web_frame)
     28     return false;
     29 
     30   WebKit::WebView* web_view = web_frame->view();
     31   if (!web_view)
     32     return false;
     33 
     34   RenderViewImpl* render_view_impl =
     35       RenderViewImpl::FromWebView(web_view);
     36   if (!render_view_impl)
     37     return false;
     38 
     39   *out = render_view_impl;
     40   return true;
     41 }
     42 
     43 // Encodes a WebContentsLoadTime as JSON.
     44 // Input:
     45 // - |load_start_time| - time at which page load started.
     46 // - |load_stop_time| - time at which page load stopped.
     47 // - |result| - returned JSON.
     48 // Example return value:
     49 // {'load_start_ms': 1, 'load_duration_ms': 2.5}
     50 // either value may be null if a web contents hasn't fully loaded.
     51 // load_start_ms is represented as milliseconds since system boot.
     52 void ConvertLoadTimeToJSON(
     53     const base::TimeTicks& load_start_time,
     54     const base::TimeTicks& load_stop_time,
     55     std::string *result) {
     56   base::DictionaryValue item;
     57 
     58   if (load_start_time.is_null()) {
     59      item.Set("load_start_ms", base::Value::CreateNullValue());
     60   } else {
     61     // This code relies on an implementation detail of TimeTicks::Now() - that
     62     // its return value happens to coincide with the system uptime value in
     63     // microseconds, on Win/Mac/iOS/Linux/ChromeOS and Android.  See comments
     64     // in base::SysInfo::Uptime().
     65     item.SetDouble("load_start_ms", load_start_time.ToInternalValue() / 1000);
     66   }
     67   if (load_start_time.is_null() || load_stop_time.is_null()) {
     68     item.Set("load_duration_ms", base::Value::CreateNullValue());
     69   } else {
     70     item.SetDouble("load_duration_ms",
     71         (load_stop_time - load_start_time).InMilliseconds());
     72   }
     73   base::JSONWriter::Write(&item, result);
     74 }
     75 
     76 }  // namespace
     77 
     78 StatsCollectionController::StatsCollectionController()
     79     : sender_(NULL) {
     80   BindCallback("getHistogram",
     81                base::Bind(&StatsCollectionController::GetHistogram,
     82                           base::Unretained(this)));
     83   BindCallback("getBrowserHistogram",
     84                base::Bind(&StatsCollectionController::GetBrowserHistogram,
     85                           base::Unretained(this)));
     86   BindCallback("tabLoadTiming",
     87                base::Bind(
     88                   &StatsCollectionController::GetTabLoadTiming,
     89                   base::Unretained(this)));
     90 }
     91 
     92 void StatsCollectionController::GetHistogram(const CppArgumentList& args,
     93                                             CppVariant* result) {
     94   if (args.size() != 1) {
     95     result->SetNull();
     96     return;
     97   }
     98   base::HistogramBase* histogram =
     99       base::StatisticsRecorder::FindHistogram(args[0].ToString());
    100   std::string output;
    101   if (!histogram) {
    102     output = "{}";
    103   } else {
    104     histogram->WriteJSON(&output);
    105   }
    106   result->Set(output);
    107 }
    108 
    109 void StatsCollectionController::GetBrowserHistogram(const CppArgumentList& args,
    110                                                    CppVariant* result) {
    111   if (args.size() != 1) {
    112     result->SetNull();
    113     return;
    114   }
    115 
    116   if (!sender_) {
    117     NOTREACHED();
    118     result->SetNull();
    119     return;
    120   }
    121 
    122   std::string histogram_json;
    123   sender_->Send(new ChildProcessHostMsg_GetBrowserHistogram(
    124       args[0].ToString(), &histogram_json));
    125   result->Set(histogram_json);
    126 }
    127 
    128 void StatsCollectionController::GetTabLoadTiming(
    129     const CppArgumentList& args,
    130     CppVariant* result) {
    131   if (!sender_) {
    132     NOTREACHED();
    133     result->SetNull();
    134     return;
    135   }
    136 
    137   RenderViewImpl *render_view_impl = NULL;
    138   if (!CurrentRenderViewImpl(&render_view_impl)) {
    139     NOTREACHED();
    140     result->SetNull();
    141     return;
    142   }
    143 
    144   StatsCollectionObserver* observer =
    145       render_view_impl->GetStatsCollectionObserver();
    146   if (!observer) {
    147     NOTREACHED();
    148     result->SetNull();
    149     return;
    150   }
    151 
    152   std::string tab_timing_json;
    153   ConvertLoadTimeToJSON(
    154       observer->load_start_time(), observer->load_stop_time(),
    155       &tab_timing_json);
    156   result->Set(tab_timing_json);
    157 }
    158 
    159 }  // namespace content
    160