summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/time.cc6
-rw-r--r--base/time.h4
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc2
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--chrome/common/render_messages.h13
-rw-r--r--chrome/renderer/extensions/loadtimes_extension_bindings.cc91
-rw-r--r--chrome/renderer/extensions/loadtimes_extension_bindings.h24
-rw-r--r--chrome/renderer/render_thread.cc2
-rw-r--r--chrome/renderer/render_view.cc135
-rw-r--r--chrome/renderer/render_view.h2
-rw-r--r--chrome/renderer/renderer.vcproj16
-rw-r--r--chrome/renderer/renderer_main.cc5
-rw-r--r--webkit/glue/webdatasource.h38
-rw-r--r--webkit/glue/webdatasource_impl.cc51
-rw-r--r--webkit/glue/webdatasource_impl.h34
-rw-r--r--webkit/glue/webframe_impl.cc1
-rw-r--r--webkit/glue/webframeloaderclient_impl.cc51
-rw-r--r--webkit/glue/webframeloaderclient_impl.h3
-rw-r--r--webkit/glue/webview_delegate.h10
19 files changed, 447 insertions, 43 deletions
diff --git a/base/time.cc b/base/time.cc
index 5ce1f80..992e256 100644
--- a/base/time.cc
+++ b/base/time.cc
@@ -60,6 +60,12 @@ time_t Time::ToTimeT() const {
return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond;
}
+// static
+Time Time::FromDoubleT(double dt) {
+ return (dt * static_cast<double>(kMicrosecondsPerSecond)) +
+ kTimeTToMicrosecondsOffset;
+}
+
double Time::ToDoubleT() const {
if (us_ == 0)
return 0; // Preserve 0 so we can tell it doesn't exist.
diff --git a/base/time.h b/base/time.h
index b43aece..a2d145c 100644
--- a/base/time.h
+++ b/base/time.h
@@ -213,10 +213,12 @@ class Time {
static Time FromTimeT(time_t tt);
time_t ToTimeT() const;
- // Converts time to a double which is the number of seconds since epoch
+ // Converts time to/from a double which is the number of seconds since epoch
// (Jan 1, 1970). Webkit uses this format to represent time.
+ static Time FromDoubleT(double dt);
double ToDoubleT() const;
+
#if defined(OS_WIN)
static Time FromFileTime(FILETIME ft);
FILETIME ToFileTime() const;
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 83c55a7..76bc612 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -9,6 +9,7 @@
#include "base/gfx/native_widget_types.h"
#include "base/string_util.h"
+#include "base/time.h"
#include "base/waitable_event.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/cross_site_request_manager.h"
@@ -618,6 +619,7 @@ void RenderViewHost::MakeNavigateParams(const NavigationEntry& entry,
params->transition = entry.transition_type();
params->state = entry.content_state();
params->reload = reload;
+ params->request_time = base::Time::Now();
}
bool RenderViewHost::CanBlur() const {
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 2c6641e..f0b1161 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1392,6 +1392,8 @@
'renderer/automation/dom_automation_controller.h',
'renderer/extensions/extension_process_bindings.cc',
'renderer/extensions/extension_process_bindings.h',
+ 'renderer/extensions/loadtimes_extension_bindings.h',
+ 'renderer/extensions/loadtimes_extension_bindings.cc',
'renderer/extensions/renderer_extension_bindings.cc',
'renderer/extensions/renderer_extension_bindings.h',
'renderer/media/audio_renderer_impl.cc',
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 38af203..1c983d0 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -42,6 +42,10 @@
#include "skia/include/SkBitmap.h"
#endif
+namespace base {
+class Time;
+}
+
struct ViewHostMsg_UpdateFeedList_Params {
// The page_id for this navigation, or -1 if it is a new navigation. Back,
// Forward, and Reload navigations should have a valid page_id. If the load
@@ -78,6 +82,9 @@ struct ViewMsg_Navigate_Params {
// Specifies if the URL should be loaded using 'reload' semantics (i.e.,
// bypassing any locally cached content).
bool reload;
+
+ // The time the request was created
+ base::Time request_time;
};
// Parameters structure for ViewHostMsg_FrameNavigate, which has too many data
@@ -662,6 +669,7 @@ struct ParamTraits<ViewMsg_Navigate_Params> {
WriteParam(m, p.transition);
WriteParam(m, p.state);
WriteParam(m, p.reload);
+ WriteParam(m, p.request_time);
}
static bool Read(const Message* m, void** iter, param_type* p) {
return
@@ -670,7 +678,8 @@ struct ParamTraits<ViewMsg_Navigate_Params> {
ReadParam(m, iter, &p->referrer) &&
ReadParam(m, iter, &p->transition) &&
ReadParam(m, iter, &p->state) &&
- ReadParam(m, iter, &p->reload);
+ ReadParam(m, iter, &p->reload) &&
+ ReadParam(m, iter, &p->request_time);
}
static void Log(const param_type& p, std::wstring* l) {
l->append(L"(");
@@ -683,6 +692,8 @@ struct ParamTraits<ViewMsg_Navigate_Params> {
LogParam(p.state, l);
l->append(L", ");
LogParam(p.reload, l);
+ l->append(L", ");
+ LogParam(p.request_time, l);
l->append(L")");
}
};
diff --git a/chrome/renderer/extensions/loadtimes_extension_bindings.cc b/chrome/renderer/extensions/loadtimes_extension_bindings.cc
new file mode 100644
index 0000000..b0836036
--- /dev/null
+++ b/chrome/renderer/extensions/loadtimes_extension_bindings.cc
@@ -0,0 +1,91 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/extensions/loadtimes_extension_bindings.h"
+
+#include "base/time.h"
+#include "v8/include/v8.h"
+#include "webkit/glue/webframe.h"
+#include "webkit/glue/webdatasource.h"
+
+namespace extensions_v8 {
+
+static const char* 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 chromium;"
+ "if (!chromium)"
+ " chromium = {};"
+ "chromium.GetLoadTimes = function() {"
+ " native function GetLoadTimes();"
+ " return GetLoadTimes();"
+ "}") {}
+
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+ v8::Handle<v8::String> name) {
+ if (name->Equals(v8::String::New("GetLoadTimes"))) {
+ return v8::FunctionTemplate::New(GetLoadTimes);
+ }
+ return v8::Handle<v8::FunctionTemplate>();
+ }
+
+ static const char *GetNavigationType(WebNavigationType nav_type) {
+ switch (nav_type) {
+ case WebNavigationTypeLinkClicked: return "LinkClicked";
+ case WebNavigationTypeFormSubmitted: return "FormSubmitted";
+ case WebNavigationTypeBackForward: return "BackForward";
+ case WebNavigationTypeReload: return "Reload";
+ case WebNavigationTypeFormResubmitted: return "Resubmitted";
+ case WebNavigationTypeOther: return "Other";
+ }
+ return "";
+ }
+
+ static v8::Handle<v8::Value> GetLoadTimes(const v8::Arguments& args) {
+ WebFrame* win_frame = WebFrame::RetrieveActiveFrame();
+ if (win_frame) {
+ WebDataSource* data_source = win_frame->GetDataSource();
+ if (data_source) {
+ v8::Local<v8::Object> load_times = v8::Object::New();
+ load_times->Set(
+ v8::String::New("requestTime"),
+ v8::Number::New(data_source->GetRequestTime().ToDoubleT()));
+ load_times->Set(
+ v8::String::New("startLoadTime"),
+ v8::Number::New(data_source->GetStartLoadTime().ToDoubleT()));
+ load_times->Set(
+ v8::String::New("finishDocumentLoadTime"),
+ v8::Number::New(
+ data_source->GetFinishDocumentLoadTime().ToDoubleT()));
+ load_times->Set(
+ v8::String::New("finishLoadTime"),
+ v8::Number::New(data_source->GetFinishLoadTime().ToDoubleT()));
+ load_times->Set(
+ v8::String::New("navigationType"),
+ v8::String::New(
+ GetNavigationType(data_source->GetNavigationType())));
+ return load_times;
+ }
+ }
+ return v8::Null();
+ }
+};
+
+v8::Extension* LoadTimesExtension::Get() {
+ return new LoadTimesExtensionWrapper();
+}
+
+} // namespace extensions_v8
diff --git a/chrome/renderer/extensions/loadtimes_extension_bindings.h b/chrome/renderer/extensions/loadtimes_extension_bindings.h
new file mode 100644
index 0000000..4a6bcf5
--- /dev/null
+++ b/chrome/renderer/extensions/loadtimes_extension_bindings.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The LoadTimesExtension is a v8 extension to access the time it took
+// to load a page.
+
+#ifndef CHROME_RENDERER_EXTENSIONS_LOADTIMES_EXTENSION_BINDINGS_H_
+#define CHROME_RENDERER_EXTENSIONS_LOADTIMES_EXTENSION_BINDINGS_H_
+
+namespace v8 {
+class Extension;
+}
+
+namespace extensions_v8 {
+
+class LoadTimesExtension {
+ public:
+ static v8::Extension* Get();
+};
+
+} // namespace extensions_v8
+
+#endif // CHROME_RENDERER_EXTENSIONS_LOADTIMES_EXTENSION_BINDINGS_H_
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index e161438..8eb1c21 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -24,6 +24,7 @@
#include "webkit/glue/weburlrequest.h"
#endif
#include "chrome/renderer/extensions/extension_process_bindings.h"
+#include "chrome/renderer/extensions/loadtimes_extension_bindings.h"
#include "chrome/renderer/extensions/renderer_extension_bindings.h"
#include "chrome/renderer/net/render_dns_master.h"
#include "chrome/renderer/render_process.h"
@@ -269,6 +270,7 @@ void RenderThread::EnsureWebKitInitialized() {
WebKit::registerExtension(extensions_v8::GearsExtension::Get());
WebKit::registerExtension(extensions_v8::IntervalExtension::Get());
+ WebKit::registerExtension(extensions_v8::LoadTimesExtension::Get());
WebKit::registerExtension(
extensions_v8::RendererExtensionBindings::Get(this));
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 2feecfc..a13c74f 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -82,6 +82,7 @@
#include "skia/ext/vector_canvas.h"
#endif
+using base::Time;
using base::TimeDelta;
using webkit_glue::WebAccessibility;
using WebKit::WebConsoleMessage;
@@ -134,8 +135,10 @@ namespace {
class RenderViewExtraRequestData : public WebRequest::ExtraData {
public:
RenderViewExtraRequestData(int32 pending_page_id,
- PageTransition::Type transition)
+ PageTransition::Type transition,
+ Time request_time)
: transition_type(transition),
+ request_time(request_time),
request_committed(false),
pending_page_id_(pending_page_id) {
}
@@ -149,6 +152,7 @@ class RenderViewExtraRequestData : public WebRequest::ExtraData {
// Contains the transition type that the browser specified when it
// initiated the load.
PageTransition::Type transition_type;
+ Time request_time;
// True if we have already processed the "DidCommitLoad" event for this
// request. Used by session history.
@@ -807,7 +811,7 @@ void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {
scoped_ptr<WebRequest> request(WebRequest::Create(params.url));
request->SetCachePolicy(cache_policy);
request->SetExtraData(new RenderViewExtraRequestData(
- params.page_id, params.transition));
+ params.page_id, params.transition, params.request_time));
// If we are reloading, then WebKit will use the state of the current page.
// Otherwise, we give it the state to navigate to.
@@ -1207,6 +1211,15 @@ void RenderView::DidStartProvisionalLoadForFrame(
completed_client_redirect_src_ = GURL();
}
+ WebDataSource* ds = frame->GetProvisionalDataSource();
+ if (ds) {
+ const WebRequest& req = ds->GetRequest();
+ RenderViewExtraRequestData* extra_data =
+ static_cast<RenderViewExtraRequestData*>(req.GetExtraData());
+ if (extra_data) {
+ ds->SetRequestTime(extra_data->request_time);
+ }
+ }
Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
routing_id_, webview->GetMainFrame() == frame,
frame->GetProvisionalDataSource()->GetRequest().GetURL()));
@@ -1411,6 +1424,11 @@ void RenderView::DidReceiveTitle(WebView* webview,
}
void RenderView::DidFinishLoadForFrame(WebView* webview, WebFrame* frame) {
+ if (webview->GetMainFrame() == frame) {
+ const GURL& url = frame->GetURL();
+ if (url.SchemeIs("http") || url.SchemeIs("https"))
+ DumpLoadHistograms();
+ }
}
void RenderView::DidFailLoadWithError(WebView* webview,
@@ -2988,3 +3006,116 @@ void RenderView::OnExtensionResponse(int callback_id,
web_frame, callback_id, response);
pending_extension_callbacks_.Remove(callback_id);
}
+
+// Dump all load time histograms. We create 2 sets time based histograms,
+// one that is specific to the navigation type and one that aggregates all
+// navigation types
+//
+// Each set contains 5 histograms measuring various times.
+// The time points we keep are
+// request: time document was requested by user
+// start: time load of document started
+// finishDoc: main document loaded, before onload()
+// finish: after onload() and all resources are loaded
+// finish_document_load_time and finish_load_time.
+// The times that we histogram are
+// requestToStart,
+// startToFinishDoc,
+// finishDocToFinish,
+// startToFinish,
+// requestToFinish,
+//
+void RenderView::DumpLoadHistograms() const {
+ WebFrame* main_frame = webview()->GetMainFrame();
+ WebDataSource* ds = main_frame->GetDataSource();
+ WebNavigationType nav_type = ds->GetNavigationType();
+ Time request_time = ds->GetRequestTime();
+ Time start_load_time = ds->GetStartLoadTime();
+ Time finish_document_load_time = ds->GetFinishDocumentLoadTime();
+ Time finish_load_time = ds->GetFinishLoadTime();
+ TimeDelta request_to_start = start_load_time - request_time;
+ TimeDelta start_to_finish_doc = finish_document_load_time - start_load_time;
+ TimeDelta finish_doc_to_finish = finish_load_time - finish_document_load_time;
+ TimeDelta start_to_finish = finish_load_time - start_load_time;
+ TimeDelta request_to_finish = finish_load_time - start_load_time;
+
+ UMA_HISTOGRAM_TIMES("Renderer.All.RequestToStart", request_to_start);
+ UMA_HISTOGRAM_TIMES("Renderer.All.StartToFinishDoc", start_to_finish_doc);
+ UMA_HISTOGRAM_TIMES("Renderer.All.FinishDocToFinish", finish_doc_to_finish);
+ UMA_HISTOGRAM_TIMES("Renderer.All.StartToFinish", start_to_finish);
+ UMA_HISTOGRAM_TIMES("Renderer.All.RequestToFinish", request_to_finish);
+ switch (nav_type) {
+ case WebNavigationTypeLinkClicked:
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.LinkClicked.RequestToStart", request_to_start);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.LinkClicked.StartToFinishDoc", start_to_finish_doc);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.LinkClicked.FinishDocToFinish", finish_doc_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.LinkClicked.RequestToFinish", request_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.LinkClicked.StartToFinish", start_to_finish);
+ break;
+ case WebNavigationTypeFormSubmitted:
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.FormSubmitted.RequestToStart", request_to_start);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.FormSubmitted.StartToFinishDoc", start_to_finish_doc);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.FormSubmitted.FinishDocToFinish", finish_doc_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.FormSubmitted.RequestToFinish", request_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.FormSubmitted.StartToFinish", start_to_finish);
+ break;
+ case WebNavigationTypeBackForward:
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.BackForward.RequestToStart", request_to_start);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.BackForward.StartToFinishDoc", start_to_finish_doc);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.BackForward.FinishDocToFinish", finish_doc_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.BackForward.RequestToFinish", request_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.BackForward.StartToFinish", start_to_finish);
+ break;
+ case WebNavigationTypeReload:
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.Reload.RequestToStart", request_to_start);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.Reload.StartToFinishDoc", start_to_finish_doc);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.Reload.FinishDocToFinish", finish_doc_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.Reload.RequestToFinish", request_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.Reload.StartToFinish", start_to_finish);
+ break;
+ case WebNavigationTypeFormResubmitted:
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.FormResubmitted.RequestToStart", request_to_start);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.FormResubmitted.StartToFinishDoc", start_to_finish_doc);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.FormResubmitted.FinishDocToFinish", finish_doc_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.FormResubmitted.RequestToFinish", request_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.FormResubmitted.StartToFinish", start_to_finish);
+ break;
+ case WebNavigationTypeOther:
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.Other.RequestToStart", request_to_start);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.Other.StartToFinishDoc", start_to_finish_doc);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.Other.FinishDocToFinish", finish_doc_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.Other.RequestToFinish", request_to_finish);
+ UMA_HISTOGRAM_TIMES(
+ "Renderer.Other.StartToFinish", start_to_finish);
+ break;
+ }
+}
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index a9c8915..a272a3f 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -641,6 +641,8 @@ class RenderView : public RenderWidget,
// A helper method used by WasOpenedByUserGesture.
bool WasOpenedByUserGestureHelper() const;
+ void DumpLoadHistograms() const;
+
// Bitwise-ORed set of extra bindings that have been enabled. See
// BindingsPolicy for details.
int enabled_bindings_;
diff --git a/chrome/renderer/renderer.vcproj b/chrome/renderer/renderer.vcproj
index 3a70134..3b85de0 100644
--- a/chrome/renderer/renderer.vcproj
+++ b/chrome/renderer/renderer.vcproj
@@ -185,19 +185,27 @@
Name="extensions"
>
<File
- RelativePath=".\extensions\renderer_extension_bindings.cc"
+ RelativePath=".\extensions\extension_process_bindings.cc"
>
</File>
<File
- RelativePath=".\extensions\renderer_extension_bindings.h"
+ RelativePath=".\extensions\extension_process_bindings.h"
>
</File>
<File
- RelativePath=".\extensions\extension_process_bindings.cc"
+ RelativePath=".\extensions\loadtimes_extension_bindings.cc"
>
</File>
<File
- RelativePath=".\extensions\extension_process_bindings.h"
+ RelativePath=".\extensions\loadtimes_extension_bindings.h"
+ >
+ </File>
+ <File
+ RelativePath=".\extensions\renderer_extension_bindings.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\extensions\renderer_extension_bindings.h"
>
</File>
</Filter>
diff --git a/chrome/renderer/renderer_main.cc b/chrome/renderer/renderer_main.cc
index c9d6aa2..c6637ab 100644
--- a/chrome/renderer/renderer_main.cc
+++ b/chrome/renderer/renderer_main.cc
@@ -7,6 +7,7 @@
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/platform_thread.h"
+#include "base/process_util.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/string_util.h"
#include "base/system_monitor.h"
@@ -39,8 +40,10 @@ static void HandleRendererErrorTestParameters(const CommandLine& command_line) {
if (command_line.HasSwitch(switches::kRendererStartupDialog)) {
#if defined(OS_WIN)
std::wstring title = l10n_util::GetString(IDS_PRODUCT_NAME);
+ std::wstring message = L"renderer starting with pid: ";
+ message += IntToWString(base::GetCurrentProcId());
title += L" renderer"; // makes attaching to process easier
- ::MessageBox(NULL, L"renderer starting...", title.c_str(),
+ ::MessageBox(NULL, message.c_str(), title.c_str(),
MB_OK | MB_SETFOREGROUND);
#elif defined(OS_MACOSX)
// TODO(playmobil): In the long term, overriding this flag doesn't seem
diff --git a/webkit/glue/webdatasource.h b/webkit/glue/webdatasource.h
index 3bd29d1..70c4283 100644
--- a/webkit/glue/webdatasource.h
+++ b/webkit/glue/webdatasource.h
@@ -14,8 +14,22 @@ class SearchableFormData;
class WebFrame;
class WebRequest;
class WebResponse;
+
+namespace base {
+class Time;
+}
+
struct PasswordForm;
+enum WebNavigationType {
+ WebNavigationTypeLinkClicked,
+ WebNavigationTypeFormSubmitted,
+ WebNavigationTypeBackForward,
+ WebNavigationTypeReload,
+ WebNavigationTypeFormResubmitted,
+ WebNavigationTypeOther
+};
+
class WebDataSource {
public:
virtual ~WebDataSource() {}
@@ -81,6 +95,30 @@ class WebDataSource {
// Returns the page title.
virtual string16 GetPageTitle() const = 0;
+
+ // Returns the time the document was request by the user.
+ virtual base::Time GetRequestTime() const = 0;
+
+ // Sets the request time. This is used to override the default behavior
+ // if the client knows more about the origination of the request than the
+ // underlying mechanism could.
+ virtual void SetRequestTime(base::Time time) = 0;
+
+ // Returns the time we started loading the page. This corresponds to
+ // the DidStartProvisionalLoadForFrame delegate notification.
+ virtual base::Time GetStartLoadTime() const = 0;
+
+ // Returns the time the document itself was finished loading. This corresponds
+ // to the DidFinishDocumentLoadForFrame delegate notification.
+ virtual base::Time GetFinishDocumentLoadTime() const = 0;
+
+ // Returns the time all dependent resources have been loaded and onload()
+ // has been called. This corresponds to the DidFinishLoadForFrame delegate
+ // notification.
+ virtual base::Time GetFinishLoadTime() const = 0;
+
+ // Returns the reason the document was loaded.
+ virtual WebNavigationType GetNavigationType() const = 0;
};
#endif // #ifndef WEBKIT_GLUE_WEBDATASOURCE_H_
diff --git a/webkit/glue/webdatasource_impl.cc b/webkit/glue/webdatasource_impl.cc
index d3517d8..9d31b0f 100644
--- a/webkit/glue/webdatasource_impl.cc
+++ b/webkit/glue/webdatasource_impl.cc
@@ -5,17 +5,23 @@
#include "config.h"
#include "webkit/glue/webdatasource_impl.h"
-#include "KURL.h"
+#include "FrameLoaderTypes.h"
#include "FrameLoadRequest.h"
+#include "KURL.h"
#include "ResourceRequest.h"
#undef LOG
+#include "base/histogram.h"
#include "base/string_util.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/password_form.h"
#include "webkit/glue/webdatasource_impl.h"
#include "webkit/glue/webframe_impl.h"
#include "webkit/glue/weburlrequest_impl.h"
+#include "webkit/glue/webview_delegate.h"
+
+using base::TimeDelta;
+using base::Time;
// static
PassRefPtr<WebDataSourceImpl> WebDataSourceImpl::Create(
@@ -99,3 +105,46 @@ bool WebDataSourceImpl::IsFormSubmit() const {
string16 WebDataSourceImpl::GetPageTitle() const {
return webkit_glue::StringToString16(title());
}
+
+base::Time WebDataSourceImpl::GetRequestTime() const {
+ return request_time_;
+}
+
+void WebDataSourceImpl::SetRequestTime(base::Time time) {
+ request_time_ = time;
+}
+
+base::Time WebDataSourceImpl::GetStartLoadTime() const {
+ return start_load_time_;
+}
+
+base::Time WebDataSourceImpl::GetFinishDocumentLoadTime() const {
+ return finish_document_load_time_;
+}
+
+base::Time WebDataSourceImpl::GetFinishLoadTime() const {
+ return finish_load_time_;
+}
+
+WebNavigationType WebDataSourceImpl::GetNavigationType() const {
+ return NavigationTypeToWebNavigationType(triggeringAction().type());
+}
+
+WebNavigationType WebDataSourceImpl::NavigationTypeToWebNavigationType(
+ WebCore::NavigationType type) {
+ switch (type) {
+ case WebCore::NavigationTypeLinkClicked:
+ return WebNavigationTypeLinkClicked;
+ case WebCore::NavigationTypeFormSubmitted:
+ return WebNavigationTypeFormSubmitted;
+ case WebCore::NavigationTypeBackForward:
+ return WebNavigationTypeBackForward;
+ case WebCore::NavigationTypeReload:
+ return WebNavigationTypeReload;
+ case WebCore::NavigationTypeFormResubmitted:
+ return WebNavigationTypeFormResubmitted;
+ case WebCore::NavigationTypeOther:
+ default:
+ return WebNavigationTypeOther;
+ }
+}
diff --git a/webkit/glue/webdatasource_impl.h b/webkit/glue/webdatasource_impl.h
index 4585a65..90f8313 100644
--- a/webkit/glue/webdatasource_impl.h
+++ b/webkit/glue/webdatasource_impl.h
@@ -8,6 +8,7 @@
#include "DocumentLoader.h"
#include "base/scoped_ptr.h"
+#include "base/time.h"
#include "webkit/glue/searchable_form_data.h"
#include "webkit/glue/webdatasource.h"
#include "webkit/glue/webresponse_impl.h"
@@ -20,7 +21,7 @@ class WebDataSourceImpl : public WebCore::DocumentLoader, public WebDataSource {
public:
static PassRefPtr<WebDataSourceImpl> Create(const WebCore::ResourceRequest&,
const WebCore::SubstituteData&);
-
+
static WebDataSourceImpl* FromLoader(WebCore::DocumentLoader* loader) {
return static_cast<WebDataSourceImpl*>(loader);
}
@@ -37,6 +38,15 @@ class WebDataSourceImpl : public WebCore::DocumentLoader, public WebDataSource {
virtual const PasswordForm* GetPasswordFormData() const;
virtual bool IsFormSubmit() const;
virtual string16 GetPageTitle() const;
+ virtual base::Time GetRequestTime() const;
+ virtual void SetRequestTime(base::Time time);
+ virtual base::Time GetStartLoadTime() const;
+ virtual base::Time GetFinishDocumentLoadTime() const;
+ virtual base::Time GetFinishLoadTime() const;
+ virtual WebNavigationType GetNavigationType() const;
+
+ static WebNavigationType NavigationTypeToWebNavigationType(
+ WebCore::NavigationType type);
// Called after creating a new data source if there is request info
// available. Since we store copies of the WebRequests, the original
@@ -77,6 +87,22 @@ class WebDataSourceImpl : public WebCore::DocumentLoader, public WebDataSource {
return form_submit_;
}
+ void set_request_time(base::Time request_time) {
+ request_time_ = request_time;
+ }
+
+ void set_start_load_time(base::Time start_load_time) {
+ start_load_time_ = start_load_time;
+ }
+
+ void set_finish_document_load_time(base::Time finish_document_load_time) {
+ finish_document_load_time_ = finish_document_load_time;
+ }
+
+ void set_finish_load_time(base::Time finish_load_time) {
+ finish_load_time_ = finish_load_time;
+ }
+
private:
WebDataSourceImpl(const WebCore::ResourceRequest&,
const WebCore::SubstituteData&);
@@ -99,6 +125,12 @@ class WebDataSourceImpl : public WebCore::DocumentLoader, public WebDataSource {
bool form_submit_;
+ // See webdatasource.h for a description of these time stamps.
+ base::Time request_time_;
+ base::Time start_load_time_;
+ base::Time finish_document_load_time_;
+ base::Time finish_load_time_;
+
DISALLOW_COPY_AND_ASSIGN(WebDataSourceImpl);
};
diff --git a/webkit/glue/webframe_impl.cc b/webkit/glue/webframe_impl.cc
index 6a29ded..f647a72 100644
--- a/webkit/glue/webframe_impl.cc
+++ b/webkit/glue/webframe_impl.cc
@@ -131,7 +131,6 @@ MSVC_POP_WARNING();
#include "base/message_loop.h"
#include "base/stats_counters.h"
#include "base/string_util.h"
-#include "base/time.h"
#include "net/base/net_errors.h"
#include "skia/ext/bitmap_platform_device.h"
#include "skia/ext/platform_canvas.h"
diff --git a/webkit/glue/webframeloaderclient_impl.cc b/webkit/glue/webframeloaderclient_impl.cc
index 469fb02..e66157d 100644
--- a/webkit/glue/webframeloaderclient_impl.cc
+++ b/webkit/glue/webframeloaderclient_impl.cc
@@ -29,6 +29,7 @@ MSVC_PUSH_WARNING_LEVEL(0);
#include "PlatformString.h"
#include "PluginData.h"
#include "RefPtr.h"
+#include "StringExtras.h"
#include "WindowFeatures.h"
MSVC_POP_WARNING();
@@ -60,8 +61,11 @@ MSVC_POP_WARNING();
#include "webkit/glue/webview_delegate.h"
#include "webkit/glue/webview_impl.h"
#include "webkit/glue/weburlrequest.h"
+#include "webkit/glue/weburlrequest_impl.h"
using namespace WebCore;
+using base::Time;
+using base::TimeDelta;
// Domain for internal error codes.
static const char kInternalErrorDomain[] = "webkit_glue";
@@ -383,6 +387,10 @@ void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader,
void WebFrameLoaderClient::dispatchDidFinishDocumentLoad() {
WebViewImpl* webview = webframe_->webview_impl();
WebViewDelegate* d = webview->delegate();
+ DocumentLoader* documentLoader =
+ webframe_->frame()->loader()->activeDocumentLoader();
+ WebDataSourceImpl* data_source =
+ WebDataSourceImpl::FromLoader(documentLoader);
// A frame may be reused. This call ensures we don't hold on to our password
// listeners and their associated HTMLInputElements.
@@ -419,6 +427,7 @@ void WebFrameLoaderClient::dispatchDidFinishDocumentLoad() {
d->OnPasswordFormsSeen(webview, passwordForms);
if (d)
d->DidFinishDocumentLoadForFrame(webview, webframe_);
+ data_source->set_finish_document_load_time(base::Time::Now());
}
bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(
@@ -731,6 +740,21 @@ void WebFrameLoaderClient::dispatchDidStartProvisionalLoad() {
// about the client redirect the load is responsible for completing.
d->DidStartProvisionalLoadForFrame(webview, webframe_,
NavigationGestureForLastLoad());
+ DocumentLoader* documentLoader =
+ webframe_->frame()->loader()->activeDocumentLoader();
+ WebDataSourceImpl* dataSource =
+ WebDataSourceImpl::FromLoader(documentLoader);
+ if (dataSource->GetRequestTime().ToInternalValue() == 0) {
+ const Event *event = documentLoader->triggeringAction().event();
+ if (event) {
+ // If the request was generated by a click, we have to use the time
+ // from the event. Unfortunately this isn't tracked all the way from
+ // the platform event, but it will have to do
+ double eventTime = event->timeStamp() / 1000.0;
+ dataSource->set_request_time(Time::FromDoubleT(eventTime));
+ }
+ }
+ dataSource->set_start_load_time(base::Time::Now());
if (completing_client_redirect)
d->DidCompleteClientRedirect(webview, webframe_,
expected_client_redirect_src_);
@@ -803,8 +827,13 @@ void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error) {
}
void WebFrameLoaderClient::dispatchDidFinishLoad() {
+ DocumentLoader* documentLoader =
+ webframe_->frame()->loader()->activeDocumentLoader();
+ WebDataSourceImpl* dataSource =
+ WebDataSourceImpl::FromLoader(documentLoader);
WebViewImpl* webview = webframe_->webview_impl();
WebViewDelegate* d = webview->delegate();
+ dataSource->set_finish_load_time(base::Time::Now());
if (d)
d->DidFinishLoadForFrame(webview, webframe_);
WebPluginDelegate* plg_delegate = webframe_->plugin_delegate();
@@ -939,26 +968,6 @@ void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(
(webframe_->frame()->loader()->*function)(policy_action);
}
-// Conversion.
-static WebNavigationType NavigationTypeToWebNavigationType(
- WebCore::NavigationType t) {
- switch (t) {
- case WebCore::NavigationTypeLinkClicked:
- return WebNavigationTypeLinkClicked;
- case WebCore::NavigationTypeFormSubmitted:
- return WebNavigationTypeFormSubmitted;
- case WebCore::NavigationTypeBackForward:
- return WebNavigationTypeBackForward;
- case WebCore::NavigationTypeReload:
- return WebNavigationTypeReload;
- case WebCore::NavigationTypeFormResubmitted:
- return WebNavigationTypeFormResubmitted;
- default:
- case WebCore::NavigationTypeOther:
- return WebNavigationTypeOther;
- }
-}
-
void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(
WebCore::FramePolicyFunction function,
const WebCore::NavigationAction& action,
@@ -985,7 +994,7 @@ void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(
bool is_redirect = !ds->GetRedirectChain().empty();
WebNavigationType webnav_type =
- NavigationTypeToWebNavigationType(action.type());
+ WebDataSourceImpl::NavigationTypeToWebNavigationType(action.type());
disposition = d->DispositionForNavigationAction(
wv, webframe_, &ds->GetRequest(), webnav_type, disposition, is_redirect);
diff --git a/webkit/glue/webframeloaderclient_impl.h b/webkit/glue/webframeloaderclient_impl.h
index f712980..c15bfb1 100644
--- a/webkit/glue/webframeloaderclient_impl.h
+++ b/webkit/glue/webframeloaderclient_impl.h
@@ -15,10 +15,10 @@ MSVC_POP_WARNING();
#include "build/build_config.h"
#include "base/scoped_ptr.h"
+#include "base/time.h"
#include "googleurl/src/gurl.h"
#include "webkit/glue/webview_delegate.h"
#include "webkit/glue/window_open_disposition.h"
-
namespace WebCore {
class Frame;
class HTMLFormElement;
@@ -30,6 +30,7 @@ class NetAgentImpl;
class WebFrameImpl;
class WebPluginContainer;
+
class WebFrameLoaderClient : public WebCore::FrameLoaderClient {
public:
WebFrameLoaderClient(WebFrameImpl* webframe);
diff --git a/webkit/glue/webview_delegate.h b/webkit/glue/webview_delegate.h
index cf6abaf0..482a24b 100644
--- a/webkit/glue/webview_delegate.h
+++ b/webkit/glue/webview_delegate.h
@@ -29,6 +29,7 @@
#include <vector>
#include "webkit/glue/context_menu.h"
+#include "webkit/glue/webdatasource.h"
#include "webkit/glue/webwidget_delegate.h"
namespace gfx {
@@ -58,15 +59,6 @@ class WebWidget;
class WebWorker;
class WebWorkerClient;
-enum WebNavigationType {
- WebNavigationTypeLinkClicked,
- WebNavigationTypeFormSubmitted,
- WebNavigationTypeBackForward,
- WebNavigationTypeReload,
- WebNavigationTypeFormResubmitted,
- WebNavigationTypeOther
-};
-
enum NavigationGesture {
NavigationGestureUser, // User initiated navigation/load. This is not
// currently used due to the untrustworthy nature