diff options
author | jeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-29 20:44:32 +0000 |
---|---|---|
committer | jeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-29 20:44:32 +0000 |
commit | 27c521a7610b9e49d1de4895f54813131b452ebc (patch) | |
tree | f65c605aafe47ed7272406f1a62449973de4a933 /content | |
parent | 97e47956aca7291f0861707ef4d1bc0c2940efd9 (diff) | |
download | chromium_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.cc | 12 | ||||
-rw-r--r-- | content/browser/renderer_host/render_process_host_impl.cc | 1 | ||||
-rw-r--r-- | content/content_renderer.gypi | 4 | ||||
-rw-r--r-- | content/public/common/bindings_policy.h | 5 | ||||
-rw-r--r-- | content/public/common/content_switches.cc | 11 | ||||
-rw-r--r-- | content/public/common/content_switches.h | 3 | ||||
-rw-r--r-- | content/renderer/dom_automation_controller.cc | 42 | ||||
-rw-r--r-- | content/renderer/dom_automation_controller.h | 9 | ||||
-rw-r--r-- | content/renderer/render_view_impl.cc | 16 | ||||
-rw-r--r-- | content/renderer/render_view_impl.h | 18 | ||||
-rw-r--r-- | content/renderer/stats_collection_controller.cc | 159 | ||||
-rw-r--r-- | content/renderer/stats_collection_controller.h | 43 | ||||
-rw-r--r-- | content/renderer/stats_collection_observer.cc | 33 | ||||
-rw-r--r-- | content/renderer/stats_collection_observer.h | 40 |
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_ |