summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-29 20:44:32 +0000
committerjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-29 20:44:32 +0000
commit27c521a7610b9e49d1de4895f54813131b452ebc (patch)
treef65c605aafe47ed7272406f1a62449973de4a933 /content
parent97e47956aca7291f0861707ef4d1bc0c2940efd9 (diff)
downloadchromium_src-27c521a7610b9e49d1de4895f54813131b452ebc.zip
chromium_src-27c521a7610b9e49d1de4895f54813131b452ebc.tar.gz
chromium_src-27c521a7610b9e49d1de4895f54813131b452ebc.tar.bz2
Collect tab timing information for use in telementry-based startup tests
Motivation: Data collection exposed in this CL is needed by upcoming startup tests we're writing using Telemtry. Expose a new window.statsCollectionController object to JS and move existing histogram reading code into it since that seemed misplaced in DOMAutomationController. Add a new --enable-stats-collection-bindings to activate said object. Example usage in telemtry: with browser.Create() as b: b.tabs[0].Navigate("http://www.google.com") b.tabs[0].WaitForDocumentReadyStateToBeComplete() print b.tabs[0].EvaluateJavaScript('statsCollectionController.tabLoadTiming()') BUG=None Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=202620 Review URL: https://chromiumcodereview.appspot.com/12389073 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202955 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/histogram_message_filter.cc12
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc1
-rw-r--r--content/content_renderer.gypi4
-rw-r--r--content/public/common/bindings_policy.h5
-rw-r--r--content/public/common/content_switches.cc11
-rw-r--r--content/public/common/content_switches.h3
-rw-r--r--content/renderer/dom_automation_controller.cc42
-rw-r--r--content/renderer/dom_automation_controller.h9
-rw-r--r--content/renderer/render_view_impl.cc16
-rw-r--r--content/renderer/render_view_impl.h18
-rw-r--r--content/renderer/stats_collection_controller.cc159
-rw-r--r--content/renderer/stats_collection_controller.h43
-rw-r--r--content/renderer/stats_collection_observer.cc33
-rw-r--r--content/renderer/stats_collection_observer.h40
14 files changed, 334 insertions, 62 deletions
diff --git a/content/browser/histogram_message_filter.cc b/content/browser/histogram_message_filter.cc
index ac08af3..be6f85fc 100644
--- a/content/browser/histogram_message_filter.cc
+++ b/content/browser/histogram_message_filter.cc
@@ -49,17 +49,17 @@ void HistogramMessageFilter::OnGetBrowserHistogram(
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
// Security: Only allow access to browser histograms when running in the
// context of a test.
- bool using_dom_controller =
+ bool using_stats_collection_controller =
CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDomAutomationController);
+ switches::kStatsCollectionController);
bool reduced_security =
CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kReduceSecurityForDomAutomationTests);
+ switches::kReduceSecurityForStatsCollectionTests);
- if (!using_dom_controller || !reduced_security) {
+ if (!using_stats_collection_controller || !reduced_security) {
LOG(ERROR) << "Attempt at reading browser histogram without specifying "
- << "--" << switches::kDomAutomationController << " and "
- << "--" << switches::kReduceSecurityForDomAutomationTests
+ << "--" << switches::kStatsCollectionController << " and "
+ << "--" << switches::kReduceSecurityForStatsCollectionTests
<< " switches.";
return;
}
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 499f161..e341a4a 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -941,6 +941,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kRendererStartupDialog,
switches::kShowPaintRects,
switches::kSitePerProcess,
+ switches::kStatsCollectionController,
switches::kTestSandbox,
switches::kTouchEvents,
switches::kTraceStartup,
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index b064a01..6ea4c3f 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -313,6 +313,10 @@
'renderer/skia_benchmarking_extension.h',
'renderer/speech_recognition_dispatcher.cc',
'renderer/speech_recognition_dispatcher.h',
+ 'renderer/stats_collection_controller.cc',
+ 'renderer/stats_collection_controller.h',
+ 'renderer/stats_collection_observer.cc',
+ 'renderer/stats_collection_observer.h',
'renderer/text_input_client_observer.cc',
'renderer/text_input_client_observer.h',
'renderer/v8_value_converter_impl.cc',
diff --git a/content/public/common/bindings_policy.h b/content/public/common/bindings_policy.h
index 140cef3..8c8a743 100644
--- a/content/public/common/bindings_policy.h
+++ b/content/public/common/bindings_policy.h
@@ -20,6 +20,11 @@ enum BindingsPolicy {
BINDINGS_POLICY_DOM_AUTOMATION = 1 << 1,
// Bindings that allow access to the external host (through automation).
BINDINGS_POLICY_EXTERNAL_HOST = 1 << 2,
+ // Bindings that allows the JS content to retrieve a variety of internal
+ // metrics. (By default this isn't allowed unless the app has been started up
+ // with the --enable-stats-collection-bindings switch.)
+ BINDINGS_POLICY_STATS_COLLECTION = 1 << 3,
+
};
}
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 664b87f..d153e2e 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -247,8 +247,15 @@ const char kDomAutomationController[] = "dom-automation";
// Loosen security. Needed for tests using some of the functionality of
// |DOMAutomationController|.
-const char kReduceSecurityForDomAutomationTests[] =
- "reduce-security-for-dom-automation-tests";
+const char kReduceSecurityForStatsCollectionTests[] =
+ "reduce-security-for-stats-collection-tests";
+
+// Specifies if the |StatsCollectionController| needs to be bound in the
+// renderer. This binding happens on per-frame basis and hence can potentially
+// be a performance bottleneck. One should only enable it when running a test
+// that needs to access the provided statistics.
+const char kStatsCollectionController[] =
+ "enable-stats-collection-bindings";
// Enable gpu-accelerated SVG/W3C filters.
const char kEnableAcceleratedFilters[] = "enable-accelerated-filters";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 2356f0c..8e76c71 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -92,7 +92,8 @@ extern const char kDisableWebSecurity[];
extern const char kEnableExperimentalWebSocket[];
extern const char kDisableXSSAuditor[];
CONTENT_EXPORT extern const char kDomAutomationController[];
-CONTENT_EXPORT extern const char kReduceSecurityForDomAutomationTests[];
+CONTENT_EXPORT extern const char kReduceSecurityForStatsCollectionTests[];
+CONTENT_EXPORT extern const char kStatsCollectionController[];
CONTENT_EXPORT extern const char kEnableAcceleratedFilters[];
extern const char kEnableAccessibilityLogging[];
extern const char kEnableAudibleNotifications[];
diff --git a/content/renderer/dom_automation_controller.cc b/content/renderer/dom_automation_controller.cc
index 1718d64..27120c1 100644
--- a/content/renderer/dom_automation_controller.cc
+++ b/content/renderer/dom_automation_controller.cc
@@ -31,12 +31,6 @@ DomAutomationController::DomAutomationController()
base::Unretained(this)));
BindCallback("sendWithId", base::Bind(&DomAutomationController::SendWithId,
base::Unretained(this)));
- BindCallback("getHistogram",
- base::Bind(&DomAutomationController::GetHistogram,
- base::Unretained(this)));
- BindCallback("getBrowserHistogram",
- base::Bind(&DomAutomationController::GetBrowserHistogram,
- base::Unretained(this)));
}
void DomAutomationController::Send(const CppArgumentList& args,
@@ -177,40 +171,4 @@ void DomAutomationController::SetAutomationId(
result->Set(true);
}
-void DomAutomationController::GetHistogram(const CppArgumentList& args,
- CppVariant* result) {
- if (args.size() != 1) {
- result->SetNull();
- return;
- }
- base::HistogramBase* histogram =
- base::StatisticsRecorder::FindHistogram(args[0].ToString());
- std::string output;
- if (!histogram) {
- output = "{}";
- } else {
- histogram->WriteJSON(&output);
- }
- result->Set(output);
-}
-
-void DomAutomationController::GetBrowserHistogram(const CppArgumentList& args,
- CppVariant* result) {
- if (args.size() != 1) {
- result->SetNull();
- return;
- }
-
- if (!sender_) {
- NOTREACHED();
- result->SetNull();
- return;
- }
-
- std::string histogram_json;
- sender_->Send(new ChildProcessHostMsg_GetBrowserHistogram(
- args[0].ToString(), &histogram_json));
- result->Set(histogram_json);
-}
-
} // namespace content
diff --git a/content/renderer/dom_automation_controller.h b/content/renderer/dom_automation_controller.h
index b4fe4c0..1516eea 100644
--- a/content/renderer/dom_automation_controller.h
+++ b/content/renderer/dom_automation_controller.h
@@ -115,15 +115,6 @@ class DomAutomationController : public webkit_glue::CppBoundClass {
sender_ = sender;
}
- // Retrieves a histogram and returns a JSON representation of it.
- void GetHistogram(const webkit_glue::CppArgumentList& args,
- webkit_glue::CppVariant* result);
-
- // Retrieves a histogram from the browser process and returns a JSON
- // representation of it.
- void GetBrowserHistogram(const webkit_glue::CppArgumentList& args,
- webkit_glue::CppVariant* result);
-
private:
IPC::Sender* sender_;
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 3efa0f5..7bce363 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -111,6 +111,8 @@
#include "content/renderer/renderer_webcolorchooser_impl.h"
#include "content/renderer/savable_resources.h"
#include "content/renderer/speech_recognition_dispatcher.h"
+#include "content/renderer/stats_collection_controller.h"
+#include "content/renderer/stats_collection_observer.h"
#include "content/renderer/text_input_client_observer.h"
#include "content/renderer/v8_value_converter_impl.h"
#include "content/renderer/web_ui_extension.h"
@@ -713,6 +715,9 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kStatsCollectionController))
+ stats_collection_observer_.reset(new StatsCollectionObserver(this));
+
#if defined(OS_ANDROID)
content::DeviceTelephonyInfo device_info;
@@ -802,6 +807,8 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
if (command_line.HasSwitch(switches::kDomAutomationController))
enabled_bindings_ |= BINDINGS_POLICY_DOM_AUTOMATION;
+ if (command_line.HasSwitch(switches::kStatsCollectionController))
+ enabled_bindings_ |= BINDINGS_POLICY_STATS_COLLECTION;
ProcessViewLayoutFlags(command_line);
@@ -3654,6 +3661,15 @@ void RenderViewImpl::didClearWindowObject(WebFrame* frame) {
dom_automation_controller_->BindToJavascript(frame,
"domAutomationController");
}
+
+ if (enabled_bindings_ & BINDINGS_POLICY_STATS_COLLECTION) {
+ if (!stats_collection_controller_.get())
+ stats_collection_controller_.reset(new StatsCollectionController());
+ stats_collection_controller_->set_message_sender(
+ static_cast<RenderView*>(this));
+ stats_collection_controller_->BindToJavascript(frame,
+ "statsCollectionController");
+ }
}
void RenderViewImpl::didCreateDocumentElement(WebFrame* frame) {
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 28fec34..292cb30 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -38,6 +38,7 @@
#include "content/renderer/render_view_pepper_helper.h"
#include "content/renderer/render_widget.h"
#include "content/renderer/renderer_webcookiejar_impl.h"
+#include "content/renderer/stats_collection_observer.h"
#include "ipc/ipc_platform_file.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebFileSystem.h"
#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
@@ -164,6 +165,7 @@ class RendererPpapiHost;
class RendererWebColorChooserImpl;
class RenderWidgetFullscreenPepper;
class SpeechRecognitionDispatcher;
+class StatsCollectionController;
class WebPluginDelegateProxy;
struct CustomContextMenuContext;
struct FaviconURL;
@@ -267,6 +269,12 @@ class CONTENT_EXPORT RenderViewImpl
void AddObserver(RenderViewObserver* observer);
void RemoveObserver(RenderViewObserver* observer);
+ // Returns the StatsCollectionObserver associated with this view, or NULL
+ // if one wasn't created;
+ StatsCollectionObserver* GetStatsCollectionObserver() {
+ return stats_collection_observer_.get();
+ }
+
// Adds the given file chooser request to the file_chooser_completion_ queue
// (see that var for more) and requests the chooser be displayed if there are
// no other waiting items in the queue.
@@ -1518,14 +1526,20 @@ class CONTENT_EXPORT RenderViewImpl
// DOM automation bindings are enabled.
scoped_ptr<DomAutomationController> dom_automation_controller_;
+ // Allows JS to read out a variety of internal various metrics. The JS object
+ // is only exposed when the stats collection bindings are enabled.
+ scoped_ptr<StatsCollectionController> stats_collection_controller_;
+
// This field stores drag/drop related info for the event that is currently
// being handled. If the current event results in starting a drag/drop
// session, this info is sent to the browser along with other drag/drop info.
DragEventSourceInfo possible_drag_event_info_;
- // NOTE: pepper_helper_ should be last member because its constructor calls
- // AddObservers method of RenderViewImpl from c-tor.
+ // NOTE: pepper_helper_ and stats_collection_observer_ should be the last
+ // members because their constructors call the AddObservers method of
+ // RenderViewImpl.
scoped_ptr<RenderViewPepperHelper> pepper_helper_;
+ scoped_ptr<StatsCollectionObserver> stats_collection_observer_;
// ---------------------------------------------------------------------------
// ADDING NEW DATA? Please see if it fits appropriately in one of the above
diff --git a/content/renderer/stats_collection_controller.cc b/content/renderer/stats_collection_controller.cc
new file mode 100644
index 0000000..9826eef
--- /dev/null
+++ b/content/renderer/stats_collection_controller.cc
@@ -0,0 +1,159 @@
+// Copyright 2013 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 "content/renderer/stats_collection_controller.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/json/json_writer.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/statistics_recorder.h"
+#include "base/string_util.h"
+#include "content/common/child_process_messages.h"
+#include "content/renderer/render_view_impl.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+
+using webkit_glue::CppArgumentList;
+using webkit_glue::CppVariant;
+
+namespace content {
+
+namespace {
+
+bool CurrentRenderViewImpl(RenderViewImpl** out) {
+ WebKit::WebFrame* web_frame = WebKit::WebFrame::frameForCurrentContext();
+ if (!web_frame)
+ return false;
+
+ WebKit::WebView* web_view = web_frame->view();
+ if (!web_view)
+ return false;
+
+ RenderViewImpl* render_view_impl =
+ RenderViewImpl::FromWebView(web_view);
+ if (!render_view_impl)
+ return false;
+
+ *out = render_view_impl;
+ return true;
+}
+
+// Encodes a WebContentsLoadTime as JSON.
+// Input:
+// - |load_start_time| - time at which page load started.
+// - |load_stop_time| - time at which page load stopped.
+// - |result| - returned JSON.
+// Example return value:
+// {'load_start_ms': 1, 'load_duration_ms': 2.5}
+// either value may be null if a web contents hasn't fully loaded.
+// load_start_ms is represented as milliseconds since system boot.
+void ConvertLoadTimeToJSON(
+ const base::TimeTicks& load_start_time,
+ const base::TimeTicks& load_stop_time,
+ std::string *result) {
+ DictionaryValue item;
+
+ if (load_start_time.is_null()) {
+ item.Set("load_start_ms", Value::CreateNullValue());
+ } else {
+ // This code relies on an implementation detail of TimeTicks::Now() - that
+ // its return value happens to coincide with the system uptime value in
+ // microseconds, on Win/Mac/iOS/Linux/ChromeOS and Android. See comments
+ // in base::SysInfo::Uptime().
+ item.SetDouble("load_start_ms", load_start_time.ToInternalValue() / 1000);
+ }
+ if (load_stop_time.is_null() || load_stop_time.is_null()) {
+ item.Set("load_duration_ms", Value::CreateNullValue());
+ } else {
+ item.SetDouble("load_duration_ms",
+ (load_stop_time - load_start_time).InMilliseconds());
+ }
+ base::JSONWriter::Write(&item, result);
+}
+
+} // namespace
+
+StatsCollectionController::StatsCollectionController()
+ : sender_(NULL) {
+ BindCallback("getHistogram",
+ base::Bind(&StatsCollectionController::GetHistogram,
+ base::Unretained(this)));
+ BindCallback("getBrowserHistogram",
+ base::Bind(&StatsCollectionController::GetBrowserHistogram,
+ base::Unretained(this)));
+ BindCallback("tabLoadTiming",
+ base::Bind(
+ &StatsCollectionController::GetTabLoadTiming,
+ base::Unretained(this)));
+}
+
+void StatsCollectionController::GetHistogram(const CppArgumentList& args,
+ CppVariant* result) {
+ if (args.size() != 1) {
+ result->SetNull();
+ return;
+ }
+ base::HistogramBase* histogram =
+ base::StatisticsRecorder::FindHistogram(args[0].ToString());
+ std::string output;
+ if (!histogram) {
+ output = "{}";
+ } else {
+ histogram->WriteJSON(&output);
+ }
+ result->Set(output);
+}
+
+void StatsCollectionController::GetBrowserHistogram(const CppArgumentList& args,
+ CppVariant* result) {
+ if (args.size() != 1) {
+ result->SetNull();
+ return;
+ }
+
+ if (!sender_) {
+ NOTREACHED();
+ result->SetNull();
+ return;
+ }
+
+ std::string histogram_json;
+ sender_->Send(new ChildProcessHostMsg_GetBrowserHistogram(
+ args[0].ToString(), &histogram_json));
+ result->Set(histogram_json);
+}
+
+void StatsCollectionController::GetTabLoadTiming(
+ const CppArgumentList& args,
+ CppVariant* result) {
+ if (!sender_) {
+ NOTREACHED();
+ result->SetNull();
+ return;
+ }
+
+ RenderViewImpl *render_view_impl = NULL;
+ if (!CurrentRenderViewImpl(&render_view_impl)) {
+ NOTREACHED();
+ result->SetNull();
+ return;
+ }
+
+ StatsCollectionObserver* observer =
+ render_view_impl->GetStatsCollectionObserver();
+ if (!observer) {
+ NOTREACHED();
+ result->SetNull();
+ return;
+ }
+
+ std::string tab_timing_json;
+ ConvertLoadTimeToJSON(
+ observer->load_start_time(), observer->load_stop_time(),
+ &tab_timing_json);
+ result->Set(tab_timing_json);
+}
+
+} // namespace content
diff --git a/content/renderer/stats_collection_controller.h b/content/renderer/stats_collection_controller.h
new file mode 100644
index 0000000..eb1ccb0
--- /dev/null
+++ b/content/renderer/stats_collection_controller.h
@@ -0,0 +1,43 @@
+// Copyright 2013 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.
+
+#ifndef CONTENT_RENDERER_STATS_COLLECTION_CONTROLLER_H_
+#define CONTENT_RENDERER_STATS_COLLECTION_CONTROLLER_H_
+
+#include "ipc/ipc_sender.h"
+#include "webkit/glue/cpp_bound_class.h"
+
+namespace content {
+
+// This class is exposed in JS as window.statsCollectionController and provides
+// functionality to read out statistics from the browser.
+// Its use must be enabled specifically via the
+// --enable-stats-collection-bindings command line flag.
+class StatsCollectionController : public webkit_glue::CppBoundClass {
+ public:
+ StatsCollectionController();
+
+ void set_message_sender(IPC::Sender* sender) {
+ sender_ = sender;
+ }
+
+ // Retrieves a histogram and returns a JSON representation of it.
+ void GetHistogram(const webkit_glue::CppArgumentList& args,
+ webkit_glue::CppVariant* result);
+
+ // Retrieves a histogram from the browser process and returns a JSON
+ // representation of it.
+ void GetBrowserHistogram(const webkit_glue::CppArgumentList& args,
+ webkit_glue::CppVariant* result);
+
+ // Returns JSON representation of tab timing information for the current tab.
+ void GetTabLoadTiming(const webkit_glue::CppArgumentList& args,
+ webkit_glue::CppVariant* result);
+ private:
+ IPC::Sender* sender_;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_STATS_COLLECTION_CONTROLLER_H_
diff --git a/content/renderer/stats_collection_observer.cc b/content/renderer/stats_collection_observer.cc
new file mode 100644
index 0000000..4192ec0
--- /dev/null
+++ b/content/renderer/stats_collection_observer.cc
@@ -0,0 +1,33 @@
+// Copyright 2013 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 "content/renderer/stats_collection_observer.h"
+
+#include "base/time.h"
+#include "content/renderer/render_view_impl.h"
+
+namespace content {
+
+StatsCollectionObserver::StatsCollectionObserver(RenderViewImpl* render_view)
+ : RenderViewObserver(render_view) {
+}
+
+StatsCollectionObserver::~StatsCollectionObserver() {
+}
+
+void StatsCollectionObserver::DidStartLoading() {
+ DCHECK(start_time_.is_null());
+ start_time_ = base::TimeTicks::Now();
+}
+
+void StatsCollectionObserver::DidStopLoading() {
+ DCHECK(stop_time_.is_null());
+ stop_time_ = base::TimeTicks::Now();
+
+ // Stop observing so we don't get called again.
+ RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view());
+ impl->RemoveObserver(this);
+}
+
+} // namespace content
diff --git a/content/renderer/stats_collection_observer.h b/content/renderer/stats_collection_observer.h
new file mode 100644
index 0000000..52d67b8
--- /dev/null
+++ b/content/renderer/stats_collection_observer.h
@@ -0,0 +1,40 @@
+// Copyright 2013 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.
+
+#ifndef CONTENT_RENDERER_STATS_COLLECTION_OBSERVER_H_
+#define CONTENT_RENDERER_STATS_COLLECTION_OBSERVER_H_
+
+#include "base/time.h"
+#include "content/public/renderer/render_view_observer.h"
+
+namespace content {
+
+class RenderViewImpl;
+
+// Collect timing information for page loads.
+// If a Renderview performs multiple loads, only the first one is recorded.
+class StatsCollectionObserver : public RenderViewObserver {
+ public:
+ explicit StatsCollectionObserver(RenderViewImpl* render_view);
+ virtual ~StatsCollectionObserver();
+
+ // RenderViewObserver implementation
+ virtual void DidStartLoading() OVERRIDE;
+ virtual void DidStopLoading() OVERRIDE;
+
+ // Timing for the page load start and stop. These functions may return
+ // a null time value under various circumstances.
+ const base::TimeTicks& load_start_time() { return start_time_; }
+ const base::TimeTicks& load_stop_time() { return stop_time_; }
+
+ private:
+ base::TimeTicks start_time_;
+ base::TimeTicks stop_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(StatsCollectionObserver);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_STATS_COLLECTION_OBSERVER_H_