Home | History | Annotate | Download | only in renderer
      1 // Copyright (c) 2012 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 "chrome/renderer/loadtimes_extension_bindings.h"
      6 
      7 #include <math.h>
      8 
      9 #include "base/time/time.h"
     10 #include "content/public/renderer/document_state.h"
     11 #include "net/http/http_response_info.h"
     12 #include "third_party/WebKit/public/web/WebLocalFrame.h"
     13 #include "v8/include/v8.h"
     14 
     15 using blink::WebDataSource;
     16 using blink::WebLocalFrame;
     17 using blink::WebNavigationType;
     18 using content::DocumentState;
     19 
     20 // Values for CSI "tran" property
     21 const int kTransitionLink = 0;
     22 const int kTransitionForwardBack = 6;
     23 const int kTransitionOther = 15;
     24 const int kTransitionReload = 16;
     25 
     26 namespace extensions_v8 {
     27 
     28 static const char* const kLoadTimesExtensionName = "v8/LoadTimes";
     29 
     30 class LoadTimesExtensionWrapper : public v8::Extension {
     31  public:
     32   // Creates an extension which adds a new function, chromium.GetLoadTimes()
     33   // This function returns an object containing the following members:
     34   // requestTime: The time the request to load the page was received
     35   // loadTime: The time the renderer started the load process
     36   // finishDocumentLoadTime: The time the document itself was loaded
     37   //                         (this is before the onload() method is fired)
     38   // finishLoadTime: The time all loading is done, after the onload()
     39   //                 method and all resources
     40   // navigationType: A string describing what user action initiated the load
     41   LoadTimesExtensionWrapper() :
     42     v8::Extension(kLoadTimesExtensionName,
     43       "var chrome;"
     44       "if (!chrome)"
     45       "  chrome = {};"
     46       "chrome.loadTimes = function() {"
     47       "  native function GetLoadTimes();"
     48       "  return GetLoadTimes();"
     49       "};"
     50       "chrome.csi = function() {"
     51       "  native function GetCSI();"
     52       "  return GetCSI();"
     53       "}") {}
     54 
     55   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
     56       v8::Isolate* isolate,
     57       v8::Handle<v8::String> name) OVERRIDE {
     58     if (name->Equals(v8::String::NewFromUtf8(isolate, "GetLoadTimes"))) {
     59       return v8::FunctionTemplate::New(isolate, GetLoadTimes);
     60     } else if (name->Equals(v8::String::NewFromUtf8(isolate, "GetCSI"))) {
     61       return v8::FunctionTemplate::New(isolate, GetCSI);
     62     }
     63     return v8::Handle<v8::FunctionTemplate>();
     64   }
     65 
     66   static const char* GetNavigationType(WebNavigationType nav_type) {
     67     switch (nav_type) {
     68       case blink::WebNavigationTypeLinkClicked:
     69         return "LinkClicked";
     70       case blink::WebNavigationTypeFormSubmitted:
     71         return "FormSubmitted";
     72       case blink::WebNavigationTypeBackForward:
     73         return "BackForward";
     74       case blink::WebNavigationTypeReload:
     75         return "Reload";
     76       case blink::WebNavigationTypeFormResubmitted:
     77         return "Resubmitted";
     78       case blink::WebNavigationTypeOther:
     79         return "Other";
     80     }
     81     return "";
     82   }
     83 
     84   static int GetCSITransitionType(WebNavigationType nav_type) {
     85     switch (nav_type) {
     86       case blink::WebNavigationTypeLinkClicked:
     87       case blink::WebNavigationTypeFormSubmitted:
     88       case blink::WebNavigationTypeFormResubmitted:
     89         return kTransitionLink;
     90       case blink::WebNavigationTypeBackForward:
     91         return kTransitionForwardBack;
     92       case blink::WebNavigationTypeReload:
     93         return kTransitionReload;
     94       case blink::WebNavigationTypeOther:
     95         return kTransitionOther;
     96     }
     97     return kTransitionOther;
     98   }
     99 
    100   static void GetLoadTimes(const v8::FunctionCallbackInfo<v8::Value>& args) {
    101     WebLocalFrame* frame = WebLocalFrame::frameForCurrentContext();
    102     if (frame) {
    103       WebDataSource* data_source = frame->dataSource();
    104       if (data_source) {
    105         DocumentState* document_state =
    106             DocumentState::FromDataSource(data_source);
    107         v8::Isolate* isolate = args.GetIsolate();
    108         v8::Local<v8::Object> load_times = v8::Object::New(isolate);
    109         load_times->Set(
    110             v8::String::NewFromUtf8(isolate, "requestTime"),
    111             v8::Number::New(isolate,
    112                             document_state->request_time().ToDoubleT()));
    113         load_times->Set(
    114             v8::String::NewFromUtf8(isolate, "startLoadTime"),
    115             v8::Number::New(isolate,
    116                             document_state->start_load_time().ToDoubleT()));
    117         load_times->Set(
    118             v8::String::NewFromUtf8(isolate, "commitLoadTime"),
    119             v8::Number::New(isolate,
    120                             document_state->commit_load_time().ToDoubleT()));
    121         load_times->Set(
    122             v8::String::NewFromUtf8(isolate, "finishDocumentLoadTime"),
    123             v8::Number::New(
    124                 isolate,
    125                 document_state->finish_document_load_time().ToDoubleT()));
    126         load_times->Set(
    127             v8::String::NewFromUtf8(isolate, "finishLoadTime"),
    128             v8::Number::New(isolate,
    129                             document_state->finish_load_time().ToDoubleT()));
    130         load_times->Set(
    131             v8::String::NewFromUtf8(isolate, "firstPaintTime"),
    132             v8::Number::New(isolate,
    133                             document_state->first_paint_time().ToDoubleT()));
    134         load_times->Set(
    135             v8::String::NewFromUtf8(isolate, "firstPaintAfterLoadTime"),
    136             v8::Number::New(
    137                 isolate,
    138                 document_state->first_paint_after_load_time().ToDoubleT()));
    139         load_times->Set(
    140             v8::String::NewFromUtf8(isolate, "navigationType"),
    141             v8::String::NewFromUtf8(
    142                 isolate, GetNavigationType(data_source->navigationType())));
    143         load_times->Set(
    144             v8::String::NewFromUtf8(isolate, "wasFetchedViaSpdy"),
    145             v8::Boolean::New(isolate, document_state->was_fetched_via_spdy()));
    146         load_times->Set(
    147             v8::String::NewFromUtf8(isolate, "wasNpnNegotiated"),
    148             v8::Boolean::New(isolate, document_state->was_npn_negotiated()));
    149         load_times->Set(
    150             v8::String::NewFromUtf8(isolate, "npnNegotiatedProtocol"),
    151             v8::String::NewFromUtf8(
    152                 isolate, document_state->npn_negotiated_protocol().c_str()));
    153         load_times->Set(
    154             v8::String::NewFromUtf8(isolate, "wasAlternateProtocolAvailable"),
    155             v8::Boolean::New(
    156                 isolate, document_state->was_alternate_protocol_available()));
    157         load_times->Set(v8::String::NewFromUtf8(isolate, "connectionInfo"),
    158                         v8::String::NewFromUtf8(
    159                             isolate,
    160                             net::HttpResponseInfo::ConnectionInfoToString(
    161                                 document_state->connection_info()).c_str()));
    162         args.GetReturnValue().Set(load_times);
    163         return;
    164       }
    165     }
    166     args.GetReturnValue().SetNull();
    167   }
    168 
    169   static void GetCSI(const v8::FunctionCallbackInfo<v8::Value>& args) {
    170     WebLocalFrame* frame = WebLocalFrame::frameForCurrentContext();
    171     if (frame) {
    172       WebDataSource* data_source = frame->dataSource();
    173       if (data_source) {
    174         DocumentState* document_state =
    175             DocumentState::FromDataSource(data_source);
    176         v8::Isolate* isolate = args.GetIsolate();
    177         v8::Local<v8::Object> csi = v8::Object::New(isolate);
    178         base::Time now = base::Time::Now();
    179         base::Time start = document_state->request_time().is_null() ?
    180             document_state->start_load_time() :
    181             document_state->request_time();
    182         base::Time onload = document_state->finish_document_load_time();
    183         base::TimeDelta page = now - start;
    184         csi->Set(v8::String::NewFromUtf8(isolate, "startE"),
    185                  v8::Number::New(isolate, floor(start.ToDoubleT() * 1000)));
    186         csi->Set(v8::String::NewFromUtf8(isolate, "onloadT"),
    187                  v8::Number::New(isolate, floor(onload.ToDoubleT() * 1000)));
    188         csi->Set(v8::String::NewFromUtf8(isolate, "pageT"),
    189                  v8::Number::New(isolate, page.InMillisecondsF()));
    190         csi->Set(
    191             v8::String::NewFromUtf8(isolate, "tran"),
    192             v8::Number::New(
    193                 isolate, GetCSITransitionType(data_source->navigationType())));
    194 
    195         args.GetReturnValue().Set(csi);
    196         return;
    197       }
    198     }
    199     args.GetReturnValue().SetNull();
    200     return;
    201   }
    202 };
    203 
    204 v8::Extension* LoadTimesExtension::Get() {
    205   return new LoadTimesExtensionWrapper();
    206 }
    207 
    208 }  // namespace extensions_v8
    209