--- /dev/null
+// Copyright (c) 2016 The Chromium Embedded Framework 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 "include/base/cef_bind.h"
+#include "include/cef_pack_strings.h"
+#include "include/views/cef_panel.h"
+#include "include/views/cef_panel_delegate.h"
+#include "include/views/cef_scroll_view.h"
+#include "include/wrapper/cef_closure_task.h"
+#include "tests/ceftests/thread_helper.h"
+#include "tests/ceftests/views/test_window_delegate.h"
+#include "tests/gtest/include/gtest/gtest.h"
+
+#define SCROLL_VIEW_TEST_ASYNC(name) \
+ UI_THREAD_TEST_ASYNC(ViewsScrollViewTest, name)
+
+namespace {
+
+const int kScrollViewID = 1;
+const int kContentPanelID = 2;
+
+// Make the Panel larger then the Window so scroll bars appear.
+const int kContentPanelSize = TestWindowDelegate::kWSize + 200;
+
+class TestScrollViewDelegate : public CefViewDelegate {
+ public:
+ TestScrollViewDelegate() {
+ }
+
+ CefSize GetPreferredSize(CefRefPtr<CefView> view) override {
+ EXPECT_EQ(kScrollViewID, view->GetID());
+ got_get_preferred_size_ = true;
+ return CefSize(kContentPanelSize, kContentPanelSize);
+ }
+
+ bool got_get_preferred_size_ = false;
+
+ private:
+ IMPLEMENT_REFCOUNTING(TestScrollViewDelegate);
+ DISALLOW_COPY_AND_ASSIGN(TestScrollViewDelegate);
+};
+
+class TestPanelDelegate : public CefPanelDelegate {
+ public:
+ TestPanelDelegate() {
+ }
+
+ CefSize GetPreferredSize(CefRefPtr<CefView> view) override {
+ EXPECT_EQ(kContentPanelID, view->GetID());
+ got_get_preferred_size_ = true;
+ return CefSize(kContentPanelSize, kContentPanelSize);
+ }
+
+ bool got_get_preferred_size_ = false;
+
+ private:
+ IMPLEMENT_REFCOUNTING(TestPanelDelegate);
+ DISALLOW_COPY_AND_ASSIGN(TestPanelDelegate);
+};
+
+void RunScrollViewLayout(bool with_delegate,
+ CefRefPtr<CefWindow> window) {
+ CefRefPtr<TestScrollViewDelegate> scroll_view_delegate;
+ CefRefPtr<TestPanelDelegate> panel_delegate;
+ if (with_delegate) {
+ scroll_view_delegate = new TestScrollViewDelegate();
+ panel_delegate = new TestPanelDelegate();
+ }
+
+ CefRefPtr<CefScrollView> scroll_view =
+ CefScrollView::CreateScrollView(scroll_view_delegate);
+ EXPECT_TRUE(scroll_view.get());
+ EXPECT_TRUE(scroll_view->AsScrollView().get());
+
+ // Verify default state.
+ EXPECT_FALSE(scroll_view->GetContentView().get());
+ EXPECT_EQ(CefRect(0, 0, 0, 0), scroll_view->GetVisibleContentRect());
+ EXPECT_FALSE(scroll_view->HasHorizontalScrollbar());
+ EXPECT_FALSE(scroll_view->HasVerticalScrollbar());
+
+ scroll_view->SetID(kScrollViewID);
+ scroll_view->SetBackgroundColor(CefColorSetARGB(255, 0, 255, 0));
+
+ CefRefPtr<CefPanel> content_panel = CefPanel::CreatePanel(panel_delegate);
+ content_panel->SetID(kContentPanelID);
+ content_panel->SetBackgroundColor(CefColorSetARGB(255, 255, 0, 0));
+
+ if (!with_delegate) {
+ // Explicitly set the content panel size. Otherwise, it will come from the
+ // delegate.
+ content_panel->SetSize(CefSize(kContentPanelSize, kContentPanelSize));
+ }
+
+ scroll_view->SetContentView(content_panel);
+ EXPECT_TRUE(content_panel->IsSame(scroll_view->GetContentView()));
+
+ window->AddChildView(scroll_view);
+
+ // Force layout.
+ window->Layout();
+
+ EXPECT_TRUE(scroll_view->HasHorizontalScrollbar());
+ EXPECT_TRUE(scroll_view->HasVerticalScrollbar());
+
+ if (with_delegate) {
+ EXPECT_TRUE(scroll_view_delegate->got_get_preferred_size_);
+ EXPECT_TRUE(panel_delegate->got_get_preferred_size_);
+ }
+
+ window->Show();
+
+ // With default FillLayout the ScrollView should be the size of the Window's
+ // client area.
+ const CefRect& client_bounds = window->GetClientAreaBoundsInScreen();
+ const CefRect& scroll_view_bounds = scroll_view->GetBoundsInScreen();
+ EXPECT_EQ(client_bounds, scroll_view_bounds);
+
+ // Content panel size should be unchanged.
+ const CefSize& content_panel_size = content_panel->GetSize();
+ EXPECT_EQ(CefSize(kContentPanelSize, kContentPanelSize), content_panel_size);
+
+ const int sb_height = scroll_view->GetHorizontalScrollbarHeight();
+ EXPECT_GT(sb_height, 0);
+ const int sb_width = scroll_view->GetVerticalScrollbarWidth();
+ EXPECT_GT(sb_width, 0);
+
+ // Verify visible content panel region.
+ const CefRect& visible_rect = scroll_view->GetVisibleContentRect();
+ EXPECT_EQ(CefRect(0, 0, scroll_view_bounds.width - sb_width,
+ scroll_view_bounds.height - sb_height), visible_rect);
+}
+
+void ScrollViewLayout(CefRefPtr<CefWaitableEvent> event,
+ bool with_delegate) {
+ TestWindowDelegate::Config config;
+ config.on_window_created = base::Bind(RunScrollViewLayout, with_delegate);
+ TestWindowDelegate::RunTest(event, config);
+}
+
+void ScrollViewLayoutWithDelegateImpl(CefRefPtr<CefWaitableEvent> event) {
+ ScrollViewLayout(event, true);
+}
+
+void ScrollViewLayoutNoDelegateImpl(CefRefPtr<CefWaitableEvent> event) {
+ ScrollViewLayout(event, false);
+}
+
+} // namespace
+
+// Test ScrollView layout. This is primarily to exercise exposed CEF APIs and is
+// not intended to comprehensively test ScrollView-related behavior (which we
+// presume that Chromium is testing).
+SCROLL_VIEW_TEST_ASYNC(ScrollViewLayoutWithDelegate);
+SCROLL_VIEW_TEST_ASYNC(ScrollViewLayoutNoDelegate);