summaryrefslogtreecommitdiffstats
path: root/content/renderer
diff options
context:
space:
mode:
authorjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-28 19:11:40 +0000
committerjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-28 19:11:40 +0000
commit83b4f00b11ab81f02bbb6688efecdb0509cc418a (patch)
tree34a6e0521b1398087df9858e37b653c524dc7d85 /content/renderer
parent8dcb6974c52af339c67e5a02ab1764b0378e72aa (diff)
downloadchromium_src-83b4f00b11ab81f02bbb6688efecdb0509cc418a.zip
chromium_src-83b4f00b11ab81f02bbb6688efecdb0509cc418a.tar.gz
chromium_src-83b4f00b11ab81f02bbb6688efecdb0509cc418a.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 Review URL: https://chromiumcodereview.appspot.com/12389073 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202620 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer')
-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
8 files changed, 307 insertions, 53 deletions
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 47d804f..729637a 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -110,6 +110,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);
@@ -3655,6 +3662,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 3bef002..39734b4 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.
@@ -1522,14 +1530,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_