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.
5 #include "chrome/renderer/loadtimes_extension_bindings.h"
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"
15 using blink::WebDataSource
;
16 using blink::WebFrame
;
17 using blink::WebNavigationType
;
18 using content::DocumentState
;
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;
26 namespace extensions_v8
{
28 static const char* const kLoadTimesExtensionName
= "v8/LoadTimes";
30 class LoadTimesExtensionWrapper
: public v8::Extension
{
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
,
46 "chrome.loadTimes = function() {"
47 " native function GetLoadTimes();"
48 " return GetLoadTimes();"
50 "chrome.csi = function() {"
51 " native function GetCSI();"
55 virtual v8::Handle
<v8::FunctionTemplate
> GetNativeFunctionTemplate(
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
);
63 return v8::Handle
<v8::FunctionTemplate
>();
66 static const char* GetNavigationType(WebNavigationType nav_type
) {
68 case blink::WebNavigationTypeLinkClicked
:
70 case blink::WebNavigationTypeFormSubmitted
:
71 return "FormSubmitted";
72 case blink::WebNavigationTypeBackForward
:
74 case blink::WebNavigationTypeReload
:
76 case blink::WebNavigationTypeFormResubmitted
:
78 case blink::WebNavigationTypeOther
:
84 static int GetCSITransitionType(WebNavigationType 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
;
97 return kTransitionOther
;
100 static void GetLoadTimes(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
101 WebFrame
* frame
= WebFrame::frameForCurrentContext();
103 WebDataSource
* data_source
= frame
->dataSource();
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
);
110 v8::String::NewFromUtf8(isolate
, "requestTime"),
111 v8::Number::New(isolate
,
112 document_state
->request_time().ToDoubleT()));
114 v8::String::NewFromUtf8(isolate
, "startLoadTime"),
115 v8::Number::New(isolate
,
116 document_state
->start_load_time().ToDoubleT()));
118 v8::String::NewFromUtf8(isolate
, "commitLoadTime"),
119 v8::Number::New(isolate
,
120 document_state
->commit_load_time().ToDoubleT()));
122 v8::String::NewFromUtf8(isolate
, "finishDocumentLoadTime"),
125 document_state
->finish_document_load_time().ToDoubleT()));
127 v8::String::NewFromUtf8(isolate
, "finishLoadTime"),
128 v8::Number::New(isolate
,
129 document_state
->finish_load_time().ToDoubleT()));
131 v8::String::NewFromUtf8(isolate
, "firstPaintTime"),
132 v8::Number::New(isolate
,
133 document_state
->first_paint_time().ToDoubleT()));
135 v8::String::NewFromUtf8(isolate
, "firstPaintAfterLoadTime"),
138 document_state
->first_paint_after_load_time().ToDoubleT()));
140 v8::String::NewFromUtf8(isolate
, "navigationType"),
141 v8::String::NewFromUtf8(
142 isolate
, GetNavigationType(data_source
->navigationType())));
144 v8::String::NewFromUtf8(isolate
, "wasFetchedViaSpdy"),
145 v8::Boolean::New(isolate
, document_state
->was_fetched_via_spdy()));
147 v8::String::NewFromUtf8(isolate
, "wasNpnNegotiated"),
148 v8::Boolean::New(isolate
, document_state
->was_npn_negotiated()));
150 v8::String::NewFromUtf8(isolate
, "npnNegotiatedProtocol"),
151 v8::String::NewFromUtf8(
152 isolate
, document_state
->npn_negotiated_protocol().c_str()));
154 v8::String::NewFromUtf8(isolate
, "wasAlternateProtocolAvailable"),
156 isolate
, document_state
->was_alternate_protocol_available()));
157 load_times
->Set(v8::String::NewFromUtf8(isolate
, "connectionInfo"),
158 v8::String::NewFromUtf8(
160 net::HttpResponseInfo::ConnectionInfoToString(
161 document_state
->connection_info()).c_str()));
162 args
.GetReturnValue().Set(load_times
);
166 args
.GetReturnValue().SetNull();
169 static void GetCSI(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
170 WebFrame
* frame
= WebFrame::frameForCurrentContext();
172 WebDataSource
* data_source
= frame
->dataSource();
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()));
191 v8::String::NewFromUtf8(isolate
, "tran"),
193 isolate
, GetCSITransitionType(data_source
->navigationType())));
195 args
.GetReturnValue().Set(csi
);
199 args
.GetReturnValue().SetNull();
204 v8::Extension
* LoadTimesExtension::Get() {
205 return new LoadTimesExtensionWrapper();
208 } // namespace extensions_v8