| Index: content/browser/renderer_host/input/mouse_latency_browsertest.cc
|
| diff --git a/content/browser/renderer_host/input/mouse_latency_browsertest.cc b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..78c7b0cb81ac617aedba70c9d322913be2af72d0
|
| --- /dev/null
|
| +++ b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
|
| @@ -0,0 +1,189 @@
|
| +// Copyright 2017 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 <vector>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/json/json_reader.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/run_loop.h"
|
| +#include "content/browser/renderer_host/input/synthetic_gesture.h"
|
| +#include "content/browser/renderer_host/input/synthetic_gesture_controller.h"
|
| +#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
|
| +#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
|
| +#include "content/browser/renderer_host/render_widget_host_impl.h"
|
| +#include "content/browser/web_contents/web_contents_impl.h"
|
| +#include "content/common/input/synthetic_gesture_params.h"
|
| +#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
|
| +#include "content/public/browser/render_view_host.h"
|
| +#include "content/public/browser/render_widget_host_view.h"
|
| +#include "content/public/browser/tracing_controller.h"
|
| +#include "content/public/test/content_browser_test.h"
|
| +#include "content/public/test/content_browser_test_utils.h"
|
| +#include "content/shell/browser/shell.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +
|
| +namespace {
|
| +
|
| +const char kMouseUpDownDataURL[] =
|
| + "data:text/html;charset=utf-8,"
|
| + "<!DOCTYPE html>"
|
| + "<html>"
|
| + "<head>"
|
| + "<title>Mouse event trace events reported.</title>"
|
| + "<script src=\"../../resources/testharness.js\"></script>"
|
| + "<script src=\"../../resources/testharnessreport.js\"></script>"
|
| + "<style>"
|
| + "body {"
|
| + " height:3000px;"
|
| + "}"
|
| + "</style>"
|
| + "</head>"
|
| + "<body>"
|
| + "</body>"
|
| + "</html>";
|
| +
|
| +} // namespace
|
| +
|
| +namespace content {
|
| +
|
| +class MouseLatencyBrowserTest : public ContentBrowserTest {
|
| + public:
|
| + MouseLatencyBrowserTest() : loop_(base::MessageLoop::TYPE_UI) {}
|
| + ~MouseLatencyBrowserTest() override {}
|
| +
|
| + RenderWidgetHostImpl* GetWidgetHost() {
|
| + return RenderWidgetHostImpl::From(
|
| + shell()->web_contents()->GetRenderViewHost()->GetWidget());
|
| + }
|
| +
|
| + void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
|
| + EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
|
| + runner_->Quit();
|
| + }
|
| +
|
| + void OnTraceDataCollected(
|
| + std::unique_ptr<const base::DictionaryValue> metadata,
|
| + base::RefCountedString* trace_data_string) {
|
| + std::unique_ptr<base::Value> trace_data =
|
| + base::JSONReader::Read(trace_data_string->data());
|
| + ASSERT_TRUE(trace_data);
|
| + trace_data_ = *trace_data;
|
| + runner_->Quit();
|
| + }
|
| +
|
| + protected:
|
| + void LoadURL() {
|
| + const GURL data_url(kMouseUpDownDataURL);
|
| + NavigateToURL(shell(), data_url);
|
| +
|
| + RenderWidgetHostImpl* host = GetWidgetHost();
|
| + host->GetView()->SetSize(gfx::Size(400, 400));
|
| + }
|
| +
|
| + // Generate mouse events for a synthetic click at |point|.
|
| + void DoSyncClick(const gfx::PointF& position) {
|
| + SyntheticTapGestureParams params;
|
| + params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
|
| + params.position = position;
|
| + params.duration_ms = 100;
|
| + std::unique_ptr<SyntheticTapGesture> gesture(
|
| + new SyntheticTapGesture(params));
|
| +
|
| + GetWidgetHost()->QueueSyntheticGesture(
|
| + std::move(gesture),
|
| + base::Bind(&MouseLatencyBrowserTest::OnSyntheticGestureCompleted,
|
| + base::Unretained(this)));
|
| +
|
| + // Runs until we get the OnSyntheticGestureCompleted callback
|
| + runner_ = base::MakeUnique<base::RunLoop>();
|
| + runner_->Run();
|
| + }
|
| +
|
| + void StartTracing() {
|
| + base::trace_event::TraceConfig trace_config(
|
| + "{"
|
| + "\"enable_argument_filter\":false,"
|
| + "\"enable_systrace\":false,"
|
| + "\"included_categories\":["
|
| + "\"latencyInfo\""
|
| + "],"
|
| + "\"record_mode\":\"record-until-full\""
|
| + "}");
|
| +
|
| + base::RunLoop run_loop;
|
| + ASSERT_TRUE(TracingController::GetInstance()->StartTracing(
|
| + trace_config, run_loop.QuitClosure()));
|
| + }
|
| +
|
| + const base::Value& StopTracing() {
|
| + bool success = TracingController::GetInstance()->StopTracing(
|
| + TracingController::CreateStringSink(
|
| + base::Bind(&MouseLatencyBrowserTest::OnTraceDataCollected,
|
| + base::Unretained(this))));
|
| + EXPECT_TRUE(success);
|
| +
|
| + // Runs until we get the OnTraceDataCollected callback, which populates
|
| + // trace_data_;
|
| + runner_ = base::MakeUnique<base::RunLoop>();
|
| + runner_->Run();
|
| + return trace_data_;
|
| + }
|
| +
|
| + private:
|
| + base::MessageLoop loop_;
|
| + std::unique_ptr<base::RunLoop> runner_;
|
| + base::Value trace_data_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(MouseLatencyBrowserTest);
|
| +};
|
| +
|
| +// Ensures that LatencyInfo async slices are reported correctly for MouseUp and
|
| +// MouseDown events in the case where no swap is generated.
|
| +// Disabled on Android because we don't support synthetic mouse input on
|
| +// Android (crbug.com/723618).
|
| +#if defined(OS_ANDROID)
|
| +#define MAYBE_MouseDownAndUpRecordedWithoutSwap \
|
| + DISABLED_MouseDownAndUpRecordedWithoutSwap
|
| +#else
|
| +#define MAYBE_MouseDownAndUpRecordedWithoutSwap \
|
| + MouseDownAndUpRecordedWithoutSwap
|
| +#endif
|
| +IN_PROC_BROWSER_TEST_F(MouseLatencyBrowserTest,
|
| + MAYBE_MouseDownAndUpRecordedWithoutSwap) {
|
| + LoadURL();
|
| +
|
| + StartTracing();
|
| + DoSyncClick(gfx::PointF(100, 100));
|
| + const base::Value trace_data = StopTracing();
|
| +
|
| + const base::DictionaryValue* trace_data_dict;
|
| + trace_data.GetAsDictionary(&trace_data_dict);
|
| + ASSERT_TRUE(trace_data.GetAsDictionary(&trace_data_dict));
|
| +
|
| + const base::ListValue* traceEvents;
|
| + ASSERT_TRUE(trace_data_dict->GetList("traceEvents", &traceEvents));
|
| +
|
| + std::vector<std::string> trace_event_names;
|
| +
|
| + for (size_t i = 0; i < traceEvents->GetSize(); ++i) {
|
| + const base::DictionaryValue* traceEvent;
|
| + ASSERT_TRUE(traceEvents->GetDictionary(i, &traceEvent));
|
| +
|
| + std::string name;
|
| + ASSERT_TRUE(traceEvent->GetString("name", &name));
|
| +
|
| + if (name != "InputLatency::MouseUp" && name != "InputLatency::MouseDown")
|
| + continue;
|
| + trace_event_names.push_back(name);
|
| + }
|
| +
|
| + // We see two events per async slice, a begin and an end.
|
| + EXPECT_THAT(
|
| + trace_event_names,
|
| + testing::ElementsAre("InputLatency::MouseDown", "InputLatency::MouseDown",
|
| + "InputLatency::MouseUp", "InputLatency::MouseUp"));
|
| +}
|
| +
|
| +} // namespace content
|
|
|