Commit 92c5ab40 authored by Mohsen Izadi's avatar Mohsen Izadi Committed by Commit Bot

Honor overscroll-behavior CSS property in new gesture-nav UI

When overscroll-behavior-x for the root element of a page is set to
anything other than 'auto', gesture-nav should not start on the page.

Similarly, when overscroll-behavior-y for the root element of a page is
set to anything other than 'auto', pull-to-refresh should not start on
the page.

BUG=800074,742510
TEST=GestureNavSimpleTest.* in content_unittests

Change-Id: I86cf2f50c5ceb6613dc293c1fd32ca2cfff4daa2
Reviewed-on: https://chromium-review.googlesource.com/981127Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Commit-Queue: Mohsen Izadi <mohsen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#546736}
parent 7555a545
......@@ -555,6 +555,12 @@ bool GestureNavSimple::OnOverscrollUpdate(float delta_x, float delta_y) {
}
void GestureNavSimple::OnOverscrollComplete(OverscrollMode overscroll_mode) {
if (mode_ == OverscrollMode::OVERSCROLL_NONE) {
// Previous mode change has been ignored because of overscroll-behavior
// value; so, ignore this, too.
return;
}
DCHECK_EQ(mode_, overscroll_mode);
mode_ = OVERSCROLL_NONE;
......@@ -599,6 +605,29 @@ void GestureNavSimple::OnOverscrollModeChange(OverscrollMode old_mode,
OverscrollMode new_mode,
OverscrollSource source,
cc::OverscrollBehavior behavior) {
DCHECK(old_mode == OverscrollMode::OVERSCROLL_NONE ||
new_mode == OverscrollMode::OVERSCROLL_NONE);
// Do not start a new gesture-nav if overscroll-behavior-x is not auto.
if ((new_mode == OverscrollMode::OVERSCROLL_EAST ||
new_mode == OverscrollMode::OVERSCROLL_WEST) &&
behavior.x != cc::OverscrollBehavior::kOverscrollBehaviorTypeAuto) {
return;
}
// Do not start a new pull-to-refresh if overscroll-behavior-y is not auto.
if (new_mode == OverscrollMode::OVERSCROLL_SOUTH &&
behavior.y != cc::OverscrollBehavior::kOverscrollBehaviorTypeAuto) {
return;
}
if (old_mode != OverscrollMode::OVERSCROLL_NONE &&
mode_ == OverscrollMode::OVERSCROLL_NONE) {
// Previous mode change has been ignored because of overscroll-behavior
// value; so, ignore this one, too.
return;
}
DCHECK_EQ(mode_, old_mode);
if (mode_ == new_mode)
return;
......
......@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
#include "content/common/content_export.h"
namespace content {
......@@ -17,7 +18,7 @@ class WebContentsImpl;
// A simple delegate for the overscroll controller that paints an arrow on top
// of the web-contents as a hint for pending navigations from overscroll.
class GestureNavSimple : public OverscrollControllerDelegate {
class CONTENT_EXPORT GestureNavSimple : public OverscrollControllerDelegate {
public:
explicit GestureNavSimple(WebContentsImpl* web_contents);
~GestureNavSimple() override;
......@@ -27,6 +28,8 @@ class GestureNavSimple : public OverscrollControllerDelegate {
void OnAffordanceAnimationEnded();
private:
friend class GestureNavSimpleTest;
// OverscrollControllerDelegate:
gfx::Size GetDisplaySize() const override;
bool OnOverscrollUpdate(float delta_x, float delta_y) override;
......
// Copyright 2018 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/browser/web_contents/aura/gesture_nav_simple.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/site_instance.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "ui/aura/window.h"
#include <memory>
namespace content {
namespace {
// A subclass of TestWebContents that offers a fake content window.
class GestureNavTestWebContents : public TestWebContents {
public:
~GestureNavTestWebContents() override {}
static GestureNavTestWebContents* Create(
BrowserContext* browser_context,
scoped_refptr<SiteInstance> instance,
std::unique_ptr<aura::Window> fake_native_view,
std::unique_ptr<aura::Window> fake_contents_window) {
auto* web_contents = new GestureNavTestWebContents(
browser_context, std::move(fake_native_view),
std::move(fake_contents_window));
web_contents->Init(
WebContents::CreateParams(browser_context, std::move(instance)));
return web_contents;
}
// Overriden from TestWebContents:
gfx::NativeView GetNativeView() override { return fake_native_view_.get(); }
gfx::NativeView GetContentNativeView() override {
return fake_contents_window_.get();
}
protected:
explicit GestureNavTestWebContents(
BrowserContext* browser_context,
std::unique_ptr<aura::Window> fake_native_view,
std::unique_ptr<aura::Window> fake_contents_window)
: TestWebContents(browser_context),
fake_native_view_(std::move(fake_native_view)),
fake_contents_window_(std::move(fake_contents_window)) {}
private:
std::unique_ptr<aura::Window> fake_native_view_;
std::unique_ptr<aura::Window> fake_contents_window_;
};
} // namespace
class GestureNavSimpleTest : public RenderViewHostImplTestHarness {
public:
GestureNavSimpleTest()
: first_("https://www.google.com"), second_("http://www.chromium.org") {}
~GestureNavSimpleTest() override {}
protected:
// RenderViewHostImplTestHarness:
void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
// Set up the fake web contents native view.
auto fake_native_view = std::make_unique<aura::Window>(nullptr);
fake_native_view->Init(ui::LAYER_SOLID_COLOR);
root_window()->AddChild(fake_native_view.get());
fake_native_view->SetBounds(gfx::Rect(root_window()->bounds().size()));
// Set up the fake contents window.
auto fake_contents_window = std::make_unique<aura::Window>(nullptr);
fake_contents_window->Init(ui::LAYER_SOLID_COLOR);
root_window()->AddChild(fake_contents_window.get());
fake_contents_window->SetBounds(gfx::Rect(root_window()->bounds().size()));
// Replace the default test web contents with our custom class.
SetContents(GestureNavTestWebContents::Create(
browser_context(), SiteInstance::Create(browser_context()),
std::move(fake_native_view), std::move(fake_contents_window)));
// Add two pages to navigation history.
contents()->NavigateAndCommit(first_);
EXPECT_TRUE(controller().GetVisibleEntry());
EXPECT_FALSE(controller().CanGoBack());
contents()->NavigateAndCommit(second_);
EXPECT_TRUE(controller().CanGoBack());
EXPECT_FALSE(controller().CanGoForward());
gesture_nav_simple_ = std::make_unique<GestureNavSimple>(contents());
}
void TearDown() override {
gesture_nav_simple_ = nullptr;
RenderViewHostImplTestHarness::TearDown();
}
const GURL first() const { return first_; }
const GURL second() const { return second_; }
void OnOverscrollModeChange(OverscrollMode old_mode,
OverscrollMode new_mode,
OverscrollSource source,
cc::OverscrollBehavior behavior) {
gesture_nav_simple_->OnOverscrollModeChange(old_mode, new_mode, source,
behavior);
}
void OnOverscrollComplete(OverscrollMode overscroll_mode) {
gesture_nav_simple_->OnOverscrollComplete(overscroll_mode);
}
OverscrollMode mode() const { return gesture_nav_simple_->mode_; }
OverscrollSource source() const { return gesture_nav_simple_->source_; }
private:
// Test URLs.
const GURL first_;
const GURL second_;
std::unique_ptr<GestureNavSimple> gesture_nav_simple_;
DISALLOW_COPY_AND_ASSIGN(GestureNavSimpleTest);
};
// Tests that setting 'overscroll-behavior-x' to 'auto' allows gesture-nav.
TEST_F(GestureNavSimpleTest, OverscrollBehaviorXAutoAllowsGestureNav) {
EXPECT_EQ(second(), contents()->GetURL());
cc::OverscrollBehavior behavior_x_auto;
behavior_x_auto.x = cc::OverscrollBehavior::kOverscrollBehaviorTypeAuto;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_EAST,
OverscrollSource::TOUCHSCREEN, behavior_x_auto);
EXPECT_EQ(OverscrollMode::OVERSCROLL_EAST, mode());
EXPECT_EQ(OverscrollSource::TOUCHSCREEN, source());
}
// Tests that setting 'overscroll-behavior-x' to 'contain' prevents gesture-nav.
TEST_F(GestureNavSimpleTest, OverscrollBehaviorXContainPreventsGestureNav) {
EXPECT_EQ(second(), contents()->GetURL());
cc::OverscrollBehavior behavior_x_contain;
behavior_x_contain.x = cc::OverscrollBehavior::kOverscrollBehaviorTypeContain;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_EAST,
OverscrollSource::TOUCHSCREEN, behavior_x_contain);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
}
// Tests that setting 'overscroll-behavior-x' to 'none' prevents gesture-nav.
TEST_F(GestureNavSimpleTest, OverscrollBehaviorXNonePreventsGestureNav) {
EXPECT_EQ(second(), contents()->GetURL());
cc::OverscrollBehavior behavior_x_none;
behavior_x_none.x = cc::OverscrollBehavior::kOverscrollBehaviorTypeNone;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_EAST,
OverscrollSource::TOUCHSCREEN, behavior_x_none);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
}
// Tests that setting 'overscroll-behavior-y' to 'auto' allows pull-to-refresh.
TEST_F(GestureNavSimpleTest, OverscrollBehaviorYAutoAllowsPullToRefresh) {
cc::OverscrollBehavior behavior_y_auto;
behavior_y_auto.y = cc::OverscrollBehavior::kOverscrollBehaviorTypeAuto;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_SOUTH,
OverscrollSource::TOUCHSCREEN, behavior_y_auto);
EXPECT_EQ(OverscrollMode::OVERSCROLL_SOUTH, mode());
EXPECT_EQ(OverscrollSource::TOUCHSCREEN, source());
}
// Tests that setting 'overscroll-behavior-y' to 'contain' prevents
// pull-to-refresh.
TEST_F(GestureNavSimpleTest, OverscrollBehaviorYContainPreventsPullToRefresh) {
cc::OverscrollBehavior behavior_y_contain;
behavior_y_contain.y = cc::OverscrollBehavior::kOverscrollBehaviorTypeContain;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_SOUTH,
OverscrollSource::TOUCHSCREEN, behavior_y_contain);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
}
// Tests that setting 'overscroll-behavior-y' to 'none' prevents
// pull-to-refresh.
TEST_F(GestureNavSimpleTest, OverscrollBehaviorYNonePreventsPullToRefresh) {
cc::OverscrollBehavior behavior_y_none;
behavior_y_none.y = cc::OverscrollBehavior::kOverscrollBehaviorTypeNone;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_SOUTH,
OverscrollSource::TOUCHSCREEN, behavior_y_none);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
}
// Tests that setting 'overscroll-behavior-x' to a value that prevents
// gesture-nav after it has started does not affect aborting it.
TEST_F(GestureNavSimpleTest, PreventGestureNavBeforeAbort) {
EXPECT_EQ(second(), contents()->GetURL());
cc::OverscrollBehavior behavior_x_auto;
behavior_x_auto.x = cc::OverscrollBehavior::kOverscrollBehaviorTypeAuto;
cc::OverscrollBehavior behavior_x_contain;
behavior_x_contain.x = cc::OverscrollBehavior::kOverscrollBehaviorTypeContain;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_EAST,
OverscrollSource::TOUCHSCREEN, behavior_x_auto);
EXPECT_EQ(OverscrollMode::OVERSCROLL_EAST, mode());
EXPECT_EQ(OverscrollSource::TOUCHSCREEN, source());
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_EAST,
OverscrollMode::OVERSCROLL_NONE,
OverscrollSource::TOUCHSCREEN, behavior_x_contain);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
EXPECT_EQ(second(), contents()->GetURL());
}
// Tests that after gesture-nav was prevented due to 'overscroll-behavior-x',
// setting it to 'auto' does not affect aborting overscroll.
TEST_F(GestureNavSimpleTest, AllowGestureNavBeforeAbort) {
EXPECT_EQ(second(), contents()->GetURL());
cc::OverscrollBehavior behavior_x_contain;
behavior_x_contain.x = cc::OverscrollBehavior::kOverscrollBehaviorTypeContain;
cc::OverscrollBehavior behavior_x_auto;
behavior_x_auto.x = cc::OverscrollBehavior::kOverscrollBehaviorTypeAuto;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_EAST,
OverscrollSource::TOUCHSCREEN, behavior_x_contain);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_EAST,
OverscrollMode::OVERSCROLL_NONE,
OverscrollSource::TOUCHSCREEN, behavior_x_auto);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
EXPECT_EQ(second(), contents()->GetURL());
}
// Tests that preventing gesture-nav using 'overscroll-behavior-x' does not
// affect completing overscroll.
TEST_F(GestureNavSimpleTest, CompletePreventedGestureNav) {
EXPECT_EQ(second(), contents()->GetURL());
cc::OverscrollBehavior behavior_x_contain;
behavior_x_contain.x = cc::OverscrollBehavior::kOverscrollBehaviorTypeContain;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_EAST,
OverscrollSource::TOUCHSCREEN, behavior_x_contain);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
OnOverscrollComplete(OverscrollMode::OVERSCROLL_EAST);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
EXPECT_EQ(second(), contents()->GetURL());
}
// Tests that setting 'overscroll-behavior-y' to a value that prevents
// pull-to-refresh after it has started does not affect aborting it.
TEST_F(GestureNavSimpleTest, PreventPullToRefreshBeforeAbort) {
cc::OverscrollBehavior behavior_y_auto;
behavior_y_auto.y = cc::OverscrollBehavior::kOverscrollBehaviorTypeAuto;
cc::OverscrollBehavior behavior_y_contain;
behavior_y_contain.y = cc::OverscrollBehavior::kOverscrollBehaviorTypeContain;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_SOUTH,
OverscrollSource::TOUCHSCREEN, behavior_y_auto);
EXPECT_EQ(OverscrollMode::OVERSCROLL_SOUTH, mode());
EXPECT_EQ(OverscrollSource::TOUCHSCREEN, source());
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_SOUTH,
OverscrollMode::OVERSCROLL_NONE,
OverscrollSource::TOUCHSCREEN, behavior_y_contain);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
}
// Tests that after pull-to-refresh was prevented due to
// 'overscroll-behavior-y', setting it to 'auto' does not affect aborting
// overscroll.
TEST_F(GestureNavSimpleTest, AllowPullToRefreshBeforeAbort) {
cc::OverscrollBehavior behavior_y_contain;
behavior_y_contain.y = cc::OverscrollBehavior::kOverscrollBehaviorTypeContain;
cc::OverscrollBehavior behavior_y_auto;
behavior_y_auto.y = cc::OverscrollBehavior::kOverscrollBehaviorTypeAuto;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_SOUTH,
OverscrollSource::TOUCHSCREEN, behavior_y_contain);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_SOUTH,
OverscrollMode::OVERSCROLL_NONE,
OverscrollSource::TOUCHSCREEN, behavior_y_auto);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
}
// Tests that preventing pull-to-refresh using 'overscroll-behavior-y' does not
// affect completing overscroll.
TEST_F(GestureNavSimpleTest, CompletePreventedPullToRefresh) {
cc::OverscrollBehavior behavior_y_contain;
behavior_y_contain.y = cc::OverscrollBehavior::kOverscrollBehaviorTypeContain;
OnOverscrollModeChange(OverscrollMode::OVERSCROLL_NONE,
OverscrollMode::OVERSCROLL_SOUTH,
OverscrollSource::TOUCHSCREEN, behavior_y_contain);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
OnOverscrollComplete(OverscrollMode::OVERSCROLL_SOUTH);
EXPECT_EQ(OverscrollMode::OVERSCROLL_NONE, mode());
EXPECT_EQ(OverscrollSource::NONE, source());
}
} // namespace content
......@@ -1497,6 +1497,7 @@ test("content_unittests") {
"../browser/tracing/background_memory_tracing_observer_unittest.cc",
"../browser/tracing/background_tracing_config_unittest.cc",
"../browser/tracing/tracing_ui_unittest.cc",
"../browser/web_contents/aura/gesture_nav_simple_unittest.cc",
"../browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc",
"../browser/web_contents/aura/overscroll_window_animation_unittest.cc",
"../browser/web_contents/aura/overscroll_window_delegate_unittest.cc",
......@@ -2025,6 +2026,7 @@ test("content_unittests") {
} else {
sources -= [
"../browser/renderer_host/render_widget_host_view_aura_unittest.cc",
"../browser/web_contents/aura/gesture_nav_simple_unittest.cc",
"../browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc",
"../browser/web_contents/aura/overscroll_window_animation_unittest.cc",
"../browser/web_contents/aura/overscroll_window_delegate_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment