blob: 19052dcc693b5514154a132f5a32f2e77130ce31 [file] [log] [blame]
#include "config.h"
#include <gtest/gtest.h>
#include "FrameTestHelpers.h"
#include "RuntimeEnabledFeatures.h"
#include "URLTestHelpers.h"
#include "WebFrame.h"
#include "WebFrameClient.h"
#include "WebFrameImpl.h"
#include "WebHistoryItem.h"
#include "WebInputEvent.h"
#include "WebScriptSource.h"
#include "WebSettings.h"
#include "WebView.h"
#include "WebViewClient.h"
#include "WebViewImpl.h"
#include "core/page/FrameView.h"
#include "core/rendering/RenderView.h"
#include "public/platform/Platform.h"
#include "public/platform/WebUnitTestSupport.h"
using namespace WebCore;
using namespace WebKit;
namespace {
class MockWebFrameClient : public WebFrameClient {
};
class ProgrammaticScrollTest : public testing::Test {
public:
ProgrammaticScrollTest()
: m_baseURL("http://www.test.com/")
{
}
virtual void SetUp()
{
RuntimeEnabledFeatures::setProgrammaticScrollNotificationsEnabled(true);
}
virtual void TearDown()
{
Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
}
protected:
void registerMockedHttpURLLoad(const std::string& fileName)
{
URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(fileName.c_str()));
}
std::string m_baseURL;
MockWebFrameClient m_mockWebFrameClient;
};
class TestProgrammaticScrollClient : public WebViewClient {
public:
TestProgrammaticScrollClient()
{
reset();
}
void reset()
{
m_eventReceived = false;
}
bool eventReceived() const { return m_eventReceived; }
// WebWidgetClient:
virtual void didProgrammaticallyScroll(const WebPoint&) OVERRIDE
{
m_eventReceived = true;
}
private:
bool m_eventReceived;
};
TEST_F(ProgrammaticScrollTest, UserScroll)
{
registerMockedHttpURLLoad("short_scroll.html");
TestProgrammaticScrollClient client;
WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "short_scroll.html", false, 0, &client);
webView->resize(WebSize(1000, 1000));
webView->layout();
EXPECT_FALSE(client.eventReceived());
// Non zero page scale and scroll.
toWebViewImpl(webView)->applyScrollAndScale(WebSize(9, 13), 2.0f);
EXPECT_FALSE(client.eventReceived());
webView->close();
}
TEST_F(ProgrammaticScrollTest, ProgrammaticScroll)
{
registerMockedHttpURLLoad("long_scroll.html");
TestProgrammaticScrollClient client;
WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "long_scroll.html", true, 0, &client);
webView->resize(WebSize(1000, 1000));
webView->layout();
WebFrameImpl* frameImpl = toWebViewImpl(webView)->mainFrameImpl();
FrameView* frameView = frameImpl->frameView();
// Slow scroll path.
frameView->setCanBlitOnScroll(false);
EXPECT_FALSE(client.eventReceived());
frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 20);"));
EXPECT_TRUE(client.eventReceived());
client.reset();
frameImpl->executeScript(WebScriptSource("window.scrollBy(0, 0);"));
EXPECT_FALSE(client.eventReceived());
client.reset();
// Fast scroll path.
frameImpl->frameView()->setCanBlitOnScroll(true);
EXPECT_FALSE(client.eventReceived());
frameImpl->executeScript(WebScriptSource("window.scrollTo(0, 21);"));
EXPECT_TRUE(client.eventReceived());
client.reset();
frameImpl->executeScript(WebScriptSource("window.scrollBy(0, 0);"));
EXPECT_FALSE(client.eventReceived());
client.reset();
webView->close();
}
TEST_F(ProgrammaticScrollTest, UserScrollOnMainThread)
{
registerMockedHttpURLLoad("long_scroll.html");
TestProgrammaticScrollClient client;
WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "long_scroll.html", true, 0, &client);
webView->resize(WebSize(1000, 1000));
webView->layout();
WebGestureEvent gesture;
gesture.type = WebInputEvent::GestureScrollBegin;
webView->handleInputEvent(gesture);
FrameTestHelpers::runPendingTasks();
EXPECT_FALSE(client.eventReceived());
gesture.type = WebInputEvent::GestureScrollUpdate;
gesture.data.scrollUpdate.deltaY = 40;
webView->handleInputEvent(gesture);
FrameTestHelpers::runPendingTasks();
EXPECT_FALSE(client.eventReceived());
gesture.type = WebInputEvent::GestureScrollEnd;
gesture.data.scrollUpdate.deltaY = 0;
webView->handleInputEvent(gesture);
FrameTestHelpers::runPendingTasks();
EXPECT_FALSE(client.eventReceived());
webView->close();
}
TEST_F(ProgrammaticScrollTest, RestoreScrollPositionAndViewStateWithScale)
{
registerMockedHttpURLLoad("long_scroll.html");
TestProgrammaticScrollClient client;
WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "long_scroll.html", true, 0, &client);
webView->resize(WebSize(1000, 1000));
webView->layout();
WebViewImpl* webViewImpl = toWebViewImpl(webView);
FrameView* frameView = webViewImpl->mainFrameImpl()->frameView();
HistoryController* history = webViewImpl->page()->mainFrame()->loader()->history();
// Scale and scroll the page and save that state. Then scale and scroll again and restore.
webViewImpl->setPageScaleFactor(2.0f, WebPoint(0, 200));
history->saveDocumentAndScrollState();
webViewImpl->setPageScaleFactor(3.0f, WebPoint(0, 300));
// Flip back the wasScrolledByUser flag which was set to true by setPageScaleFactor
// because otherwise HistoryController::restoreScrollPositionAndViewState does nothing.
frameView->setWasScrolledByUser(false);
history->restoreScrollPositionAndViewState();
// Expect that both scroll and scale were restored, and that it was not a programmatic scroll.
EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor());
EXPECT_EQ(200, webViewImpl->mainFrameImpl()->scrollOffset().height);
EXPECT_TRUE(frameView->wasScrolledByUser());
EXPECT_FALSE(client.eventReceived());
webView->close();
}
TEST_F(ProgrammaticScrollTest, RestoreScrollPositionAndViewStateWithoutScale)
{
registerMockedHttpURLLoad("long_scroll.html");
TestProgrammaticScrollClient client;
WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "long_scroll.html", true, 0, &client);
webView->resize(WebSize(1000, 1000));
webView->layout();
WebViewImpl* webViewImpl = toWebViewImpl(webView);
FrameView* frameView = webViewImpl->mainFrameImpl()->frameView();
HistoryController* history = webViewImpl->page()->mainFrame()->loader()->history();
// Scale and scroll the page and save that state, but then set scale to zero. Then scale and
// scroll again and restore.
webViewImpl->setPageScaleFactor(2.0f, WebPoint(0, 400));
history->saveDocumentAndScrollState();
webViewImpl->setPageScaleFactor(3.0f, WebPoint(0, 500));
// Flip back the wasScrolledByUser flag which was set to true by setPageScaleFactor
// because otherwise HistoryController::restoreScrollPositionAndViewState does nothing.
frameView->setWasScrolledByUser(false);
// HistoryController::restoreScrollPositionAndViewState flows differently if scale is zero.
history->currentItem()->setPageScaleFactor(0.0f);
history->restoreScrollPositionAndViewState();
// Expect that only the scroll position was restored, and that it was not a programmatic scroll.
EXPECT_EQ(3.0f, webViewImpl->pageScaleFactor());
EXPECT_EQ(400, webViewImpl->mainFrameImpl()->scrollOffset().height);
EXPECT_TRUE(frameView->wasScrolledByUser());
EXPECT_FALSE(client.eventReceived());
webView->close();
}
}