loadtimes_extension_bindings.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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/WebFrame.h" 13#include "v8/include/v8.h" 14 15using WebKit::WebDataSource; 16using WebKit::WebFrame; 17using WebKit::WebNavigationType; 18using content::DocumentState; 19 20// Values for CSI "tran" property 21const int kTransitionLink = 0; 22const int kTransitionForwardBack = 6; 23const int kTransitionOther = 15; 24const int kTransitionReload = 16; 25 26namespace extensions_v8 { 27 28static const char* const kLoadTimesExtensionName = "v8/LoadTimes"; 29 30class 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> GetNativeFunction( 56 v8::Handle<v8::String> name) OVERRIDE { 57 if (name->Equals(v8::String::New("GetLoadTimes"))) { 58 return v8::FunctionTemplate::New(GetLoadTimes); 59 } else if (name->Equals(v8::String::New("GetCSI"))) { 60 return v8::FunctionTemplate::New(GetCSI); 61 } 62 return v8::Handle<v8::FunctionTemplate>(); 63 } 64 65 static const char* GetNavigationType(WebNavigationType nav_type) { 66 switch (nav_type) { 67 case WebKit::WebNavigationTypeLinkClicked: 68 return "LinkClicked"; 69 case WebKit::WebNavigationTypeFormSubmitted: 70 return "FormSubmitted"; 71 case WebKit::WebNavigationTypeBackForward: 72 return "BackForward"; 73 case WebKit::WebNavigationTypeReload: 74 return "Reload"; 75 case WebKit::WebNavigationTypeFormResubmitted: 76 return "Resubmitted"; 77 case WebKit::WebNavigationTypeOther: 78 return "Other"; 79 } 80 return ""; 81 } 82 83 static int GetCSITransitionType(WebNavigationType nav_type) { 84 switch (nav_type) { 85 case WebKit::WebNavigationTypeLinkClicked: 86 case WebKit::WebNavigationTypeFormSubmitted: 87 case WebKit::WebNavigationTypeFormResubmitted: 88 return kTransitionLink; 89 case WebKit::WebNavigationTypeBackForward: 90 return kTransitionForwardBack; 91 case WebKit::WebNavigationTypeReload: 92 return kTransitionReload; 93 case WebKit::WebNavigationTypeOther: 94 return kTransitionOther; 95 } 96 return kTransitionOther; 97 } 98 99 static void GetLoadTimes(const v8::FunctionCallbackInfo<v8::Value>& args) { 100 WebFrame* frame = WebFrame::frameForCurrentContext(); 101 if (frame) { 102 WebDataSource* data_source = frame->dataSource(); 103 if (data_source) { 104 DocumentState* document_state = 105 DocumentState::FromDataSource(data_source); 106 v8::Local<v8::Object> load_times = v8::Object::New(); 107 load_times->Set( 108 v8::String::New("requestTime"), 109 v8::Number::New(document_state->request_time().ToDoubleT())); 110 load_times->Set( 111 v8::String::New("startLoadTime"), 112 v8::Number::New(document_state->start_load_time().ToDoubleT())); 113 load_times->Set( 114 v8::String::New("commitLoadTime"), 115 v8::Number::New(document_state->commit_load_time().ToDoubleT())); 116 load_times->Set( 117 v8::String::New("finishDocumentLoadTime"), 118 v8::Number::New( 119 document_state->finish_document_load_time().ToDoubleT())); 120 load_times->Set( 121 v8::String::New("finishLoadTime"), 122 v8::Number::New(document_state->finish_load_time().ToDoubleT())); 123 load_times->Set( 124 v8::String::New("firstPaintTime"), 125 v8::Number::New(document_state->first_paint_time().ToDoubleT())); 126 load_times->Set( 127 v8::String::New("firstPaintAfterLoadTime"), 128 v8::Number::New( 129 document_state->first_paint_after_load_time().ToDoubleT())); 130 load_times->Set( 131 v8::String::New("navigationType"), 132 v8::String::New(GetNavigationType(data_source->navigationType()))); 133 load_times->Set( 134 v8::String::New("wasFetchedViaSpdy"), 135 v8::Boolean::New(document_state->was_fetched_via_spdy())); 136 load_times->Set( 137 v8::String::New("wasNpnNegotiated"), 138 v8::Boolean::New(document_state->was_npn_negotiated())); 139 load_times->Set( 140 v8::String::New("npnNegotiatedProtocol"), 141 v8::String::New(document_state->npn_negotiated_protocol().c_str())); 142 load_times->Set( 143 v8::String::New("wasAlternateProtocolAvailable"), 144 v8::Boolean::New( 145 document_state->was_alternate_protocol_available())); 146 load_times->Set( 147 v8::String::New("connectionInfo"), 148 v8::String::New( 149 net::HttpResponseInfo::ConnectionInfoToString( 150 document_state->connection_info()).c_str())); 151 args.GetReturnValue().Set(load_times); 152 return; 153 } 154 } 155 args.GetReturnValue().SetNull(); 156 } 157 158 static void GetCSI(const v8::FunctionCallbackInfo<v8::Value>& args) { 159 WebFrame* frame = WebFrame::frameForCurrentContext(); 160 if (frame) { 161 WebDataSource* data_source = frame->dataSource(); 162 if (data_source) { 163 DocumentState* document_state = 164 DocumentState::FromDataSource(data_source); 165 v8::Local<v8::Object> csi = v8::Object::New(); 166 base::Time now = base::Time::Now(); 167 base::Time start = document_state->request_time().is_null() ? 168 document_state->start_load_time() : 169 document_state->request_time(); 170 base::Time onload = document_state->finish_document_load_time(); 171 base::TimeDelta page = now - start; 172 csi->Set( 173 v8::String::New("startE"), 174 v8::Number::New(floor(start.ToDoubleT() * 1000))); 175 csi->Set( 176 v8::String::New("onloadT"), 177 v8::Number::New(floor(onload.ToDoubleT() * 1000))); 178 csi->Set( 179 v8::String::New("pageT"), 180 v8::Number::New(page.InMillisecondsF())); 181 csi->Set( 182 v8::String::New("tran"), 183 v8::Number::New( 184 GetCSITransitionType(data_source->navigationType()))); 185 186 args.GetReturnValue().Set(csi); 187 return; 188 } 189 } 190 args.GetReturnValue().SetNull(); 191 return; 192 } 193}; 194 195v8::Extension* LoadTimesExtension::Get() { 196 return new LoadTimesExtensionWrapper(); 197} 198 199} // namespace extensions_v8 200