| Index: chrome/renderer/loadtimes_extension_bindings.cc
|
| diff --git a/chrome/renderer/loadtimes_extension_bindings.cc b/chrome/renderer/loadtimes_extension_bindings.cc
|
| index ba88e2b86a262b920c6e21b8e12c876093c5058b..746ec27749a82936a4e30aa8e77eabf38ed94a16 100644
|
| --- a/chrome/renderer/loadtimes_extension_bindings.cc
|
| +++ b/chrome/renderer/loadtimes_extension_bindings.cc
|
| @@ -8,7 +8,12 @@
|
|
|
| #include "base/time/time.h"
|
| #include "content/public/renderer/document_state.h"
|
| +#include "content/public/renderer/render_frame.h"
|
| +#include "gin/arguments.h"
|
| +#include "gin/handle.h"
|
| +#include "gin/object_template_builder.h"
|
| #include "net/http/http_response_info.h"
|
| +#include "third_party/WebKit/public/web/WebKit.h"
|
| #include "third_party/WebKit/public/web/WebLocalFrame.h"
|
| #include "v8/include/v8.h"
|
|
|
| @@ -17,199 +22,194 @@ using blink::WebLocalFrame;
|
| using blink::WebNavigationType;
|
| using content::DocumentState;
|
|
|
| +namespace {
|
| +
|
| // Values for CSI "tran" property
|
| const int kTransitionLink = 0;
|
| const int kTransitionForwardBack = 6;
|
| const int kTransitionOther = 15;
|
| const int kTransitionReload = 16;
|
|
|
| -namespace extensions_v8 {
|
| -
|
| -static const char* const kLoadTimesExtensionName = "v8/LoadTimes";
|
| -
|
| -class LoadTimesExtensionWrapper : public v8::Extension {
|
| - public:
|
| - // Creates an extension which adds a new function, chromium.GetLoadTimes()
|
| - // This function returns an object containing the following members:
|
| - // requestTime: The time the request to load the page was received
|
| - // loadTime: The time the renderer started the load process
|
| - // finishDocumentLoadTime: The time the document itself was loaded
|
| - // (this is before the onload() method is fired)
|
| - // finishLoadTime: The time all loading is done, after the onload()
|
| - // method and all resources
|
| - // navigationType: A string describing what user action initiated the load
|
| - LoadTimesExtensionWrapper() :
|
| - v8::Extension(kLoadTimesExtensionName,
|
| - "var chrome;"
|
| - "if (!chrome)"
|
| - " chrome = {};"
|
| - "chrome.loadTimes = function() {"
|
| - " native function GetLoadTimes();"
|
| - " return GetLoadTimes();"
|
| - "};"
|
| - "chrome.csi = function() {"
|
| - " native function GetCSI();"
|
| - " return GetCSI();"
|
| - "}") {}
|
| -
|
| - v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
|
| - v8::Isolate* isolate,
|
| - v8::Local<v8::String> name) override {
|
| - if (name->Equals(v8::String::NewFromUtf8(isolate, "GetLoadTimes"))) {
|
| - return v8::FunctionTemplate::New(isolate, GetLoadTimes);
|
| - } else if (name->Equals(v8::String::NewFromUtf8(isolate, "GetCSI"))) {
|
| - return v8::FunctionTemplate::New(isolate, GetCSI);
|
| - }
|
| - return v8::Local<v8::FunctionTemplate>();
|
| +const char* GetNavigationType(WebNavigationType nav_type) {
|
| + switch (nav_type) {
|
| + case blink::WebNavigationTypeLinkClicked:
|
| + return "LinkClicked";
|
| + case blink::WebNavigationTypeFormSubmitted:
|
| + return "FormSubmitted";
|
| + case blink::WebNavigationTypeBackForward:
|
| + return "BackForward";
|
| + case blink::WebNavigationTypeReload:
|
| + return "Reload";
|
| + case blink::WebNavigationTypeFormResubmitted:
|
| + return "Resubmitted";
|
| + case blink::WebNavigationTypeOther:
|
| + return "Other";
|
| }
|
| + return "";
|
| +}
|
|
|
| - static const char* GetNavigationType(WebNavigationType nav_type) {
|
| - switch (nav_type) {
|
| - case blink::WebNavigationTypeLinkClicked:
|
| - return "LinkClicked";
|
| - case blink::WebNavigationTypeFormSubmitted:
|
| - return "FormSubmitted";
|
| - case blink::WebNavigationTypeBackForward:
|
| - return "BackForward";
|
| - case blink::WebNavigationTypeReload:
|
| - return "Reload";
|
| - case blink::WebNavigationTypeFormResubmitted:
|
| - return "Resubmitted";
|
| - case blink::WebNavigationTypeOther:
|
| - return "Other";
|
| - }
|
| - return "";
|
| +int GetCSITransitionType(WebNavigationType nav_type) {
|
| + switch (nav_type) {
|
| + case blink::WebNavigationTypeLinkClicked:
|
| + case blink::WebNavigationTypeFormSubmitted:
|
| + case blink::WebNavigationTypeFormResubmitted:
|
| + return kTransitionLink;
|
| + case blink::WebNavigationTypeBackForward:
|
| + return kTransitionForwardBack;
|
| + case blink::WebNavigationTypeReload:
|
| + return kTransitionReload;
|
| + case blink::WebNavigationTypeOther:
|
| + return kTransitionOther;
|
| }
|
| + return kTransitionOther;
|
| +}
|
|
|
| - static int GetCSITransitionType(WebNavigationType nav_type) {
|
| - switch (nav_type) {
|
| - case blink::WebNavigationTypeLinkClicked:
|
| - case blink::WebNavigationTypeFormSubmitted:
|
| - case blink::WebNavigationTypeFormResubmitted:
|
| - return kTransitionLink;
|
| - case blink::WebNavigationTypeBackForward:
|
| - return kTransitionForwardBack;
|
| - case blink::WebNavigationTypeReload:
|
| - return kTransitionReload;
|
| - case blink::WebNavigationTypeOther:
|
| - return kTransitionOther;
|
| - }
|
| - return kTransitionOther;
|
| - }
|
| +} // namespace
|
| +
|
| +namespace extensions_v8 {
|
| +
|
| +gin::WrapperInfo LoadTimesExtension::kWrapperInfo = {gin::kEmbedderNativeGin};
|
| +
|
| +LoadTimesExtensionHelper::LoadTimesExtensionHelper(
|
| + content::RenderFrame* render_frame)
|
| + : RenderFrameObserver(render_frame) {}
|
| +
|
| +void LoadTimesExtensionHelper::DidFinishLoad() {
|
| + LoadTimesExtension::Install(render_frame()->GetWebFrame());
|
| +}
|
|
|
| - static void GetLoadTimes(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| - WebLocalFrame* frame = WebLocalFrame::frameForCurrentContext();
|
| - if (!frame) {
|
| - args.GetReturnValue().SetNull();
|
| - return;
|
| - }
|
| - WebDataSource* data_source = frame->dataSource();
|
| - if (!data_source) {
|
| - args.GetReturnValue().SetNull();
|
| - return;
|
| - }
|
| - DocumentState* document_state = DocumentState::FromDataSource(data_source);
|
| - if (!document_state) {
|
| - args.GetReturnValue().SetNull();
|
| - return;
|
| - }
|
| - double request_time = document_state->request_time().ToDoubleT();
|
| - double start_load_time = document_state->start_load_time().ToDoubleT();
|
| - double commit_load_time = document_state->commit_load_time().ToDoubleT();
|
| - double finish_document_load_time =
|
| - document_state->finish_document_load_time().ToDoubleT();
|
| - double finish_load_time = document_state->finish_load_time().ToDoubleT();
|
| - double first_paint_time = document_state->first_paint_time().ToDoubleT();
|
| - double first_paint_after_load_time =
|
| - document_state->first_paint_after_load_time().ToDoubleT();
|
| - std::string navigation_type =
|
| - GetNavigationType(data_source->navigationType());
|
| - bool was_fetched_via_spdy = document_state->was_fetched_via_spdy();
|
| - bool was_npn_negotiated = document_state->was_npn_negotiated();
|
| - std::string npn_negotiated_protocol =
|
| - document_state->npn_negotiated_protocol();
|
| - bool was_alternate_protocol_available =
|
| - document_state->was_alternate_protocol_available();
|
| - std::string connection_info = net::HttpResponseInfo::ConnectionInfoToString(
|
| - document_state->connection_info());
|
| - // Important: |frame|, |data_source| and |document_state| should not be
|
| - // referred to below this line, as JS setters below can invalidate these
|
| - // pointers.
|
| - v8::Isolate* isolate = args.GetIsolate();
|
| - v8::Local<v8::Object> load_times = v8::Object::New(isolate);
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "requestTime"),
|
| - v8::Number::New(isolate, request_time));
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "startLoadTime"),
|
| - v8::Number::New(isolate, start_load_time));
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "commitLoadTime"),
|
| - v8::Number::New(isolate, commit_load_time));
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "finishDocumentLoadTime"),
|
| - v8::Number::New(isolate, finish_document_load_time));
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "finishLoadTime"),
|
| - v8::Number::New(isolate, finish_load_time));
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "firstPaintTime"),
|
| - v8::Number::New(isolate, first_paint_time));
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "firstPaintAfterLoadTime"),
|
| - v8::Number::New(isolate, first_paint_after_load_time));
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "navigationType"),
|
| - v8::String::NewFromUtf8(isolate, navigation_type.c_str()));
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "wasFetchedViaSpdy"),
|
| - v8::Boolean::New(isolate, was_fetched_via_spdy));
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "wasNpnNegotiated"),
|
| - v8::Boolean::New(isolate, was_npn_negotiated));
|
| - load_times->Set(
|
| - v8::String::NewFromUtf8(isolate, "npnNegotiatedProtocol"),
|
| - v8::String::NewFromUtf8(isolate, npn_negotiated_protocol.c_str()));
|
| - load_times->Set(
|
| - v8::String::NewFromUtf8(isolate, "wasAlternateProtocolAvailable"),
|
| - v8::Boolean::New(isolate, was_alternate_protocol_available));
|
| - load_times->Set(v8::String::NewFromUtf8(isolate, "connectionInfo"),
|
| - v8::String::NewFromUtf8(isolate, connection_info.c_str()));
|
| - args.GetReturnValue().Set(load_times);
|
| +// static
|
| +void LoadTimesExtension::Install(blink::WebFrame* frame) {
|
| + v8::Isolate* isolate = blink::mainThreadIsolate();
|
| + v8::HandleScope handle_scope(isolate);
|
| + v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
|
| + if (context.IsEmpty()) return;
|
| +
|
| + v8::Context::Scope context_scope(context);
|
| +
|
| + gin::Handle<LoadTimesExtension> controller =
|
| + gin::CreateHandle(isolate, new LoadTimesExtension());
|
| + v8::Handle<v8::Object> global = context->Global();
|
| + v8::Handle<v8::Object> chrome =
|
| + global->Get(gin::StringToV8(isolate, "chrome"))->ToObject();
|
| + if (chrome.IsEmpty()) {
|
| + chrome = v8::Object::New(isolate);
|
| + global->Set(gin::StringToV8(isolate, "chrome"), chrome);
|
| }
|
| + chrome->Set(gin::StringToV8(isolate, "loadTimesController"),
|
| + controller.ToV8());
|
| +}
|
|
|
| - static void GetCSI(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| - WebLocalFrame* frame = WebLocalFrame::frameForCurrentContext();
|
| - if (!frame) {
|
| - args.GetReturnValue().SetNull();
|
| - return;
|
| - }
|
| - WebDataSource* data_source = frame->dataSource();
|
| - if (!data_source) {
|
| - args.GetReturnValue().SetNull();
|
| - return;
|
| - }
|
| - DocumentState* document_state = DocumentState::FromDataSource(data_source);
|
| - if (!document_state) {
|
| - args.GetReturnValue().SetNull();
|
| - return;
|
| - }
|
| - base::Time now = base::Time::Now();
|
| - base::Time start = document_state->request_time().is_null()
|
| - ? document_state->start_load_time()
|
| - : document_state->request_time();
|
| - base::Time onload = document_state->finish_document_load_time();
|
| - base::TimeDelta page = now - start;
|
| - int navigation_type = GetCSITransitionType(data_source->navigationType());
|
| - // Important: |frame|, |data_source| and |document_state| should not be
|
| - // referred to below this line, as JS setters below can invalidate these
|
| - // pointers.
|
| - v8::Isolate* isolate = args.GetIsolate();
|
| - v8::Local<v8::Object> csi = v8::Object::New(isolate);
|
| - csi->Set(v8::String::NewFromUtf8(isolate, "startE"),
|
| - v8::Number::New(isolate, floor(start.ToDoubleT() * 1000)));
|
| - csi->Set(v8::String::NewFromUtf8(isolate, "onloadT"),
|
| - v8::Number::New(isolate, floor(onload.ToDoubleT() * 1000)));
|
| - csi->Set(v8::String::NewFromUtf8(isolate, "pageT"),
|
| - v8::Number::New(isolate, page.InMillisecondsF()));
|
| - csi->Set(v8::String::NewFromUtf8(isolate, "tran"),
|
| - v8::Number::New(isolate, navigation_type));
|
| - args.GetReturnValue().Set(csi);
|
| +gin::ObjectTemplateBuilder LoadTimesExtension::GetObjectTemplateBuilder(
|
| + v8::Isolate* isolate) {
|
| + return gin::Wrappable<LoadTimesExtension>::GetObjectTemplateBuilder(isolate)
|
| + .SetProperty("loadTimes", &LoadTimesExtension::LoadTimes)
|
| + .SetProperty("csi", &LoadTimesExtension::CSI);
|
| +}
|
| +
|
| +v8::Local<v8::Object> LoadTimesExtension::LoadTimes() {
|
| + WebLocalFrame* frame = WebLocalFrame::frameForCurrentContext();
|
| + if (!frame) {
|
| + return v8::Local<v8::Object>();
|
| + }
|
| + WebDataSource* data_source = frame->dataSource();
|
| + if (!data_source) {
|
| + return v8::Local<v8::Object>();
|
| }
|
| -};
|
| + DocumentState* document_state = DocumentState::FromDataSource(data_source);
|
| + if (!document_state) {
|
| + return v8::Local<v8::Object>();
|
| + }
|
| + double request_time = document_state->request_time().ToDoubleT();
|
| + double start_load_time = document_state->start_load_time().ToDoubleT();
|
| + double commit_load_time = document_state->commit_load_time().ToDoubleT();
|
| + double finish_document_load_time =
|
| + document_state->finish_document_load_time().ToDoubleT();
|
| + double finish_load_time = document_state->finish_load_time().ToDoubleT();
|
| + double first_paint_time = document_state->first_paint_time().ToDoubleT();
|
| + double first_paint_after_load_time =
|
| + document_state->first_paint_after_load_time().ToDoubleT();
|
| + std::string navigation_type =
|
| + GetNavigationType(data_source->navigationType());
|
| + bool was_fetched_via_spdy = document_state->was_fetched_via_spdy();
|
| + bool was_npn_negotiated = document_state->was_npn_negotiated();
|
| + std::string npn_negotiated_protocol =
|
| + document_state->npn_negotiated_protocol();
|
| + bool was_alternate_protocol_available =
|
| + document_state->was_alternate_protocol_available();
|
| + std::string connection_info = net::HttpResponseInfo::ConnectionInfoToString(
|
| + document_state->connection_info());
|
| + // Important: |frame|, |data_source| and |document_state| should not be
|
| + // referred to below this line, as JS setters below can invalidate these
|
| + // pointers.
|
| + // v8::Isolate* isolate = args->isolate();
|
| + v8::Isolate* isolate = blink::mainThreadIsolate();
|
| + v8::Local<v8::Object> load_times = v8::Object::New(isolate);
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "requestTime"),
|
| + v8::Number::New(isolate, request_time));
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "startLoadTime"),
|
| + v8::Number::New(isolate, start_load_time));
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "commitLoadTime"),
|
| + v8::Number::New(isolate, commit_load_time));
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "finishDocumentLoadTime"),
|
| + v8::Number::New(isolate, finish_document_load_time));
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "finishLoadTime"),
|
| + v8::Number::New(isolate, finish_load_time));
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "firstPaintTime"),
|
| + v8::Number::New(isolate, first_paint_time));
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "firstPaintAfterLoadTime"),
|
| + v8::Number::New(isolate, first_paint_after_load_time));
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "navigationType"),
|
| + v8::String::NewFromUtf8(isolate, navigation_type.c_str()));
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "wasFetchedViaSpdy"),
|
| + v8::Boolean::New(isolate, was_fetched_via_spdy));
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "wasNpnNegotiated"),
|
| + v8::Boolean::New(isolate, was_npn_negotiated));
|
| + load_times->Set(
|
| + v8::String::NewFromUtf8(isolate, "npnNegotiatedProtocol"),
|
| + v8::String::NewFromUtf8(isolate, npn_negotiated_protocol.c_str()));
|
| + load_times->Set(
|
| + v8::String::NewFromUtf8(isolate, "wasAlternateProtocolAvailable"),
|
| + v8::Boolean::New(isolate, was_alternate_protocol_available));
|
| + load_times->Set(v8::String::NewFromUtf8(isolate, "connectionInfo"),
|
| + v8::String::NewFromUtf8(isolate, connection_info.c_str()));
|
| + return load_times;
|
| +}
|
|
|
| -v8::Extension* LoadTimesExtension::Get() {
|
| - return new LoadTimesExtensionWrapper();
|
| +v8::Local<v8::Object> LoadTimesExtension::CSI() {
|
| + WebLocalFrame* frame = WebLocalFrame::frameForCurrentContext();
|
| + if (!frame) {
|
| + return v8::Local<v8::Object>();
|
| + }
|
| + WebDataSource* data_source = frame->dataSource();
|
| + if (!data_source) {
|
| + return v8::Local<v8::Object>();
|
| + }
|
| + DocumentState* document_state = DocumentState::FromDataSource(data_source);
|
| + if (!document_state) {
|
| + return v8::Local<v8::Object>();
|
| + }
|
| + base::Time now = base::Time::Now();
|
| + base::Time start = document_state->request_time().is_null()
|
| + ? document_state->start_load_time()
|
| + : document_state->request_time();
|
| + base::Time onload = document_state->finish_document_load_time();
|
| + base::TimeDelta page = now - start;
|
| + int navigation_type = GetCSITransitionType(data_source->navigationType());
|
| + // Important: |frame|, |data_source| and |document_state| should not be
|
| + // referred to below this line, as JS setters below can invalidate these
|
| + // pointers.
|
| + v8::Isolate* isolate = blink::mainThreadIsolate();
|
| + v8::Local<v8::Object> csi = v8::Object::New(isolate);
|
| + csi->Set(v8::String::NewFromUtf8(isolate, "startE"),
|
| + v8::Number::New(isolate, floor(start.ToDoubleT() * 1000)));
|
| + csi->Set(v8::String::NewFromUtf8(isolate, "onloadT"),
|
| + v8::Number::New(isolate, floor(onload.ToDoubleT() * 1000)));
|
| + csi->Set(v8::String::NewFromUtf8(isolate, "pageT"),
|
| + v8::Number::New(isolate, page.InMillisecondsF()));
|
| + csi->Set(v8::String::NewFromUtf8(isolate, "tran"),
|
| + v8::Number::New(isolate, navigation_type));
|
| + return csi;
|
| }
|
|
|
| } // namespace extensions_v8
|
|
|