[M108 Migration] Implement ewk_view_main_frame_scrollbar_visible_set 70/288370/4
authorayush.k123 <ayush.k123@samsung.com>
Wed, 15 Feb 2023 05:58:50 +0000 (11:28 +0530)
committerBot Blink <blinkbot@samsung.com>
Thu, 16 Feb 2023 12:35:11 +0000 (12:35 +0000)
This patch implements ewk_view_main_frame_scrollbar_visible_set
which is at least required by HbbTV. It also implements
ewk_view_main_frame_scrollbar_visible_get and adds a
unit test utc_blink_ewk_view_main_frame_scrollbar_visible_set.

Reference: https://review.tizen.org/gerrit/280384/

Change-Id: I05a4f74e74d2305975d2cca81d246036c61987e8
Signed-off-by: Ayush Kumar <ayush.k123@samsung.com>
27 files changed:
content/browser/renderer_host/render_widget_host_impl.cc
content/browser/renderer_host/render_widget_host_impl.h
content/browser/renderer_host/render_widget_host_view_aura.cc
content/browser/renderer_host/render_widget_host_view_aura.h
content/browser/renderer_host/render_widget_host_view_base.h
content/public/browser/web_contents_delegate.h
third_party/blink/public/mojom/widget/platform_widget.mojom
third_party/blink/public/web/web_local_frame.h
third_party/blink/renderer/core/frame/local_frame_view.cc
third_party/blink/renderer/core/frame/local_frame_view.h
third_party/blink/renderer/core/frame/visual_viewport.cc
third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
third_party/blink/renderer/core/frame/web_frame_widget_impl.h
third_party/blink/renderer/core/frame/web_local_frame_impl.cc
third_party/blink/renderer/core/frame/web_local_frame_impl.h
third_party/blink/renderer/platform/widget/widget_base.cc
third_party/blink/renderer/platform/widget/widget_base.h
third_party/blink/renderer/platform/widget/widget_base_client.h
tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc
tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.h
tizen_src/ewk/efl_integration/eweb_view.cc
tizen_src/ewk/efl_integration/eweb_view.h
tizen_src/ewk/efl_integration/public/ewk_view.cc
tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc
tizen_src/ewk/efl_integration/web_contents_delegate_efl.h
tizen_src/ewk/unittest/BUILD.gn
tizen_src/ewk/unittest/utc_blink_ewk_view_main_frame_scrollbar_visible_set_func.cpp [new file with mode: 0644]

index 2dcf337..4c81a6c 100644 (file)
@@ -1023,6 +1023,23 @@ void RenderWidgetHostImpl::PrintToPdf(int width,
                                       const base::FilePath& filename) {
   blink_widget_->PrintToPdf(width, height, filename);
 }
+
+void RenderWidgetHostImpl::SetMainFrameScrollbarVisible(bool visible) {
+  blink_widget_->SetMainFrameScrollbarVisible(visible);
+}
+
+void RenderWidgetHostImpl::RequestMainFrameScrollbarVisible(int callback_id) {
+  blink_widget_->RequestMainFrameScrollbarVisible(
+      base::BindOnce(&RenderWidgetHostImpl::OnGetMainFrameScrollbarVisible,
+                     weak_factory_.GetWeakPtr(), callback_id));
+}
+
+void RenderWidgetHostImpl::OnGetMainFrameScrollbarVisible(int callback_id,
+                                                          bool visible) {
+  if (!view_)
+    return;
+  view_->OnGetMainFrameScrollbarVisible(callback_id, visible);
+}
 #endif
 
 #if defined(TIZEN_VIDEO_HOLE)
index 3e509d3..7ce20f4 100644 (file)
@@ -450,6 +450,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl
   void OnGetFocusedNodeBounds(const gfx::RectF& rect);
   void SetLongPollingGlobalTimeout(uint64_t timeout);
   void PrintToPdf(int width, int height, const base::FilePath& filename);
+  void SetMainFrameScrollbarVisible(bool visible);
+  void RequestMainFrameScrollbarVisible(int callback_id);
+  void OnGetMainFrameScrollbarVisible(int callback_id, bool visible);
 #endif
 
 #if defined(TIZEN_VIDEO_HOLE)
index 325ae91..80532e1 100644 (file)
@@ -2280,6 +2280,12 @@ void RenderWidgetHostViewAura::OnGetFocusedNodeBounds(const gfx::RectF& rect) {
   if (offscreen_helper_)
     offscreen_helper_->OnGetFocusedNodeBounds(rect);
 }
+
+void RenderWidgetHostViewAura::OnGetMainFrameScrollbarVisible(int callback_id,
+                                                              bool visible) {
+  if (offscreen_helper_)
+    offscreen_helper_->OnGetMainFrameScrollbarVisible(callback_id, visible);
+}
 #endif
 
 ////////////////////////////////////////////////////////////////////////////////
index f2c730d..ad53ed5 100644 (file)
@@ -431,6 +431,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
   void TextInputStateChanged(const ui::mojom::TextInputState& params) override;
   void BackgroundColorReceived(int callback_id, SkColor bg_color) override;
   void OnGetFocusedNodeBounds(const gfx::RectF& rect) override;
+  void OnGetMainFrameScrollbarVisible(int callback_id, bool visible) override;
 #endif
 
  protected:
index 4653432..02b76fa 100644 (file)
@@ -288,6 +288,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView {
   virtual void BackgroundColorReceived(int callback_id, SkColor bg_color) {}
 
   virtual void OnGetFocusedNodeBounds(const gfx::RectF&) {}
+
+  virtual void OnGetMainFrameScrollbarVisible(int callback_id, bool visible) {}
 #endif
 
   // This method will reset the fallback to the first surface after navigation.
index acf088d..bfa80ca 100644 (file)
@@ -515,6 +515,7 @@ class CONTENT_EXPORT WebContentsDelegate {
   virtual void BackgroundColorReceived(int callback_id, SkColor bg_color) {}
   virtual void OnDidChangeFocusedNodeBounds(
       const gfx::RectF& focused_node_bounds) {}
+  virtual void OnGetMainFrameScrollbarVisible(int callback_id, bool visible) {}
 #endif
 
 #if BUILDFLAG(IS_ANDROID)
index 46ca55c..d9cd695 100644 (file)
@@ -114,6 +114,12 @@ interface Widget {
                     gfx.mojom.Rect window_screen_rect) => ();
 
   [EnableIf=is_efl]
+  SetMainFrameScrollbarVisible(bool visible);
+
+  [EnableIf=is_efl]
+  RequestMainFrameScrollbarVisible() => (bool visible);
+
+  [EnableIf=is_efl]
   GetBackgroundColor() => (skia.mojom.SkColor bg_color);
 
   [EnableIf=is_efl]
index f15c5f8..d3b3529 100644 (file)
@@ -706,6 +706,13 @@ class BLINK_EXPORT WebLocalFrame : public WebFrame {
   virtual gfx::PointF GetScrollOffset() const = 0;
   virtual void SetScrollOffset(const gfx::PointF&) = 0;
 
+#if BUILDFLAG(IS_EFL)
+  // If set to false, do not draw scrollbars on this frame's view.
+  virtual void ChangeScrollbarVisibility(bool) = 0;
+  virtual bool HasHorizontalScrollbar() const = 0;
+  virtual bool HasVerticalScrollbar() const = 0;
+#endif
+
   // The size of the document in this frame.
   virtual gfx::Size DocumentSize() const = 0;
 
index c9d4e71..a30a289 100644 (file)
 #include "ui/gfx/geometry/quad_f.h"
 #include "ui/gfx/geometry/rect_f.h"
 
+#if BUILDFLAG(IS_EFL)
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.h"
+#include "third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_mobile.h"
+#endif
+
 // Used to check for dirty layouts violating document lifecycle rules.
 // If arg evaluates to true, the program will continue. If arg evaluates to
 // false, program will crash if DCHECK_IS_ON() or return false from the current
@@ -5025,4 +5030,47 @@ void LocalFrameView::UpdateAllPendingTransforms() {
   });
 }
 
+#if BUILDFLAG(IS_EFL)
+void LocalFrameView::ChangeScrollbarVisibility(bool visible) {
+  has_visible_scrollbars_ = visible;
+
+  if (!frame_ && !frame_->IsMainFrame())
+    return;
+
+  const VisualViewport& visual_viewport =
+      frame_->GetPage()->GetVisualViewport();
+
+  int horizontal_scrollbar_width = 0;
+  int horizontal_scrollbar_height = 0;
+  int vertical_scrollbar_width = 0;
+  int vertical_scrollbar_height = 0;
+
+  if (visible) {
+    auto& theme = ScrollbarThemeOverlayMobile::GetInstance();
+
+    const int scrollbar_thickness = theme.ScrollbarThickness(
+        visual_viewport.ScaleFromDIP(), EScrollbarWidth::kAuto);
+    horizontal_scrollbar_width =
+        visual_viewport.Size().width() - scrollbar_thickness;
+    horizontal_scrollbar_height = scrollbar_thickness;
+
+    vertical_scrollbar_width = scrollbar_thickness;
+    vertical_scrollbar_height =
+        visual_viewport.Size().height() - scrollbar_thickness;
+  }
+
+  cc::Layer* scrollbar_graphics_layer =
+      visual_viewport.LayerForHorizontalScrollbar();
+  if (scrollbar_graphics_layer) {
+    scrollbar_graphics_layer->SetBounds(
+        gfx::Size(horizontal_scrollbar_width, horizontal_scrollbar_height));
+  }
+
+  scrollbar_graphics_layer = visual_viewport.LayerForVerticalScrollbar();
+  if (scrollbar_graphics_layer) {
+    scrollbar_graphics_layer->SetBounds(
+        gfx::Size(vertical_scrollbar_width, vertical_scrollbar_height));
+  }
+}
+#endif
 }  // namespace blink
index bb71479..e6fd44f 100644 (file)
@@ -175,6 +175,11 @@ class CORE_EXPORT LocalFrameView final
 
   void SetLayoutOverflowSize(const gfx::Size&);
 
+#if BUILDFLAG(IS_EFL)
+  void ChangeScrollbarVisibility(bool);
+  bool HasVisibleScrollbars() { return has_visible_scrollbars_; }
+#endif
+
   bool DidFirstLayout() const;
   bool LifecycleUpdatesActive() const;
   void SetLifecycleUpdatesThrottledForTesting(bool throttled = true);
@@ -1026,6 +1031,10 @@ class CORE_EXPORT LocalFrameView final
   bool can_have_scrollbars_;
   bool in_post_lifecycle_steps_ = false;
 
+#if BUILDFLAG(IS_EFL)
+  bool has_visible_scrollbars_ = true;
+#endif
+
   bool has_pending_layout_;
   LayoutSubtreeRootList layout_subtree_root_list_;
   DepthOrderedLayoutObjectList orthogonal_writing_mode_root_list_;
index 2dc150f..f2fae50 100644 (file)
@@ -747,6 +747,13 @@ void VisualViewport::UpdateScrollbarLayer(ScrollbarOrientation orientation) {
     scrollbar_layer->SetIsDrawable(true);
   }
 
+#if BUILDFLAG(IS_EFL)
+  if (IsActiveViewport() && LocalMainFrame().View() &&
+      !LocalMainFrame().View()->HasVisibleScrollbars()) {
+    scrollbar_layer->SetBounds(gfx::Size(0, 0));
+    return;
+  }
+#endif
   scrollbar_layer->SetBounds(
       orientation == kHorizontalScrollbar
           ? gfx::Size(size_.width() - ScrollbarThickness(),
index fe072e5..873ec6c 100644 (file)
@@ -4199,6 +4199,25 @@ void WebFrameWidgetImpl::PrintToPdf(uint32_t width,
       width, height, filename,
       content::RenderFrame::FromWebFrame(focused_frame));
 }
+
+void WebFrameWidgetImpl::SetMainFrameScrollbarVisible(bool visible) {
+  blink::WebView* view = View();
+  if (!view || !view->MainFrame() || !view->MainFrame()->ToWebLocalFrame())
+    return;
+
+  view->MainFrame()->ToWebLocalFrame()->ChangeScrollbarVisibility(visible);
+}
+
+bool WebFrameWidgetImpl::RequestMainFrameScrollbarVisible(bool& visible) {
+  blink::WebView* view = View();
+  if (!view || !view->MainFrame() || !view->MainFrame()->ToWebLocalFrame())
+    return false;
+
+  auto local_frame = view->MainFrame()->ToWebLocalFrame();
+  visible = local_frame->HasHorizontalScrollbar() ||
+            local_frame->HasVerticalScrollbar();
+  return true;
+}
 #endif
 
 #if BUILDFLAG(IS_TIZEN)
index af3dca2..7ec9d04 100644 (file)
@@ -716,6 +716,8 @@ class CORE_EXPORT WebFrameWidgetImpl
   void PrintToPdf(uint32_t width,
                   uint32_t height,
                   const base::FilePath& filename) override;
+  void SetMainFrameScrollbarVisible(bool visible) override;
+  bool RequestMainFrameScrollbarVisible(bool& visible) override;
 #endif
 #if defined(TIZEN_VIDEO_HOLE)
   void SetVideoHoleForRender(bool enable) override;
index 682a6bb..1e3c21a 100644 (file)
@@ -2518,6 +2518,23 @@ void WebLocalFrameImpl::DidFinishLoadForPrinting() {
   Client()->DidFinishLoadForPrinting();
 }
 
+#if BUILDFLAG(IS_EFL)
+void WebLocalFrameImpl::ChangeScrollbarVisibility(bool visible) {
+  if (LocalFrameView* view = GetFrameView())
+    view->ChangeScrollbarVisibility(visible);
+}
+
+bool WebLocalFrameImpl::HasHorizontalScrollbar() const {
+  return GetFrame() && GetFrame()->View() &&
+         GetFrame()->View()->LayoutViewport()->HasHorizontalScrollbar();
+}
+
+bool WebLocalFrameImpl::HasVerticalScrollbar() const {
+  return GetFrame() && GetFrame()->View() &&
+         GetFrame()->View()->LayoutViewport()->HasVerticalScrollbar();
+}
+#endif
+
 HitTestResult WebLocalFrameImpl::HitTestResultForVisualViewportPos(
     const gfx::Point& pos_in_viewport) {
   gfx::Point root_frame_point(
index ecdea72..ac7d5d2 100644 (file)
@@ -266,6 +266,12 @@ class CORE_EXPORT WebLocalFrameImpl final
   void ReloadImage(const WebNode&) override;
   bool IsAllowedToDownload() const override;
   bool IsCrossOriginToOutermostMainFrame() const override;
+#if BUILDFLAG(IS_EFL)
+  void ChangeScrollbarVisibility(bool) override;
+  bool HasHorizontalScrollbar() const override;
+  bool HasVerticalScrollbar() const override;
+#endif
+
   bool FindForTesting(int identifier,
                       const WebString& search_text,
                       bool match_case,
index 4f07693..f43e43c 100644 (file)
@@ -489,6 +489,17 @@ void WidgetBase::UpdateFocusedNodeBounds(
   std::move(callback).Run(client_->UpdateFocusedNodeBounds());
 }
 
+void WidgetBase::SetMainFrameScrollbarVisible(bool visible) {
+  client_->SetMainFrameScrollbarVisible(visible);
+}
+
+void WidgetBase::RequestMainFrameScrollbarVisible(
+    RequestMainFrameScrollbarVisibleCallback callback) {
+  bool visible = false;
+  if (client_->RequestMainFrameScrollbarVisible(visible))
+    std::move(callback).Run(visible);
+}
+
 void WidgetBase::SetLongPollingGlobalTimeout(uint64_t timeout) {
   client_->SetLongPollingGlobalTimeout(timeout);
 }
index 43344d4..61a926a 100644 (file)
@@ -147,6 +147,9 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
   void PrintToPdf(uint32_t width,
                   uint32_t height,
                   const base::FilePath& filename) override;
+  void SetMainFrameScrollbarVisible(bool visible) override;
+  void RequestMainFrameScrollbarVisible(
+      RequestMainFrameScrollbarVisibleCallback callback) override;
 #endif
 #if defined(TIZEN_VIDEO_HOLE)
   void SetVideoHoleForRender(bool enable) override;
index d34b06f..fd7dbf1 100644 (file)
@@ -179,6 +179,8 @@ class WidgetBaseClient {
   virtual void PrintToPdf(uint32_t width,
                           uint32_t height,
                           const base::FilePath& filename) {}
+  virtual void SetMainFrameScrollbarVisible(bool visible) {}
+  virtual bool RequestMainFrameScrollbarVisible(bool& visible) { return false; }
 #endif
 #if defined(TIZEN_VIDEO_HOLE)
   virtual void SetVideoHoleForRender(bool enable) {}
index 7005822..aea5901 100644 (file)
@@ -1153,6 +1153,12 @@ void RWHVAuraOffscreenHelperEfl::ClearLabels() {
 }
 #endif
 
+void RWHVAuraOffscreenHelperEfl::OnGetMainFrameScrollbarVisible(int callback_id,
+                                                                bool visible) {
+  web_contents_->GetDelegate()->OnGetMainFrameScrollbarVisible(callback_id,
+                                                               visible);
+}
+
 void RWHVAuraOffscreenHelperEfl::OnGetFocusedNodeBounds(
     const gfx::RectF& rect) {
   web_contents_->GetDelegate()->OnDidChangeFocusedNodeBounds(rect);
index 216e234..e93b196 100644 (file)
@@ -65,6 +65,7 @@ class CONTENT_EXPORT RWHVAuraOffscreenHelperEfl {
   void BackgroundColorReceived(int callback_id, SkColor bg_color);
   void Show();
   void Hide();
+  void OnGetMainFrameScrollbarVisible(int callback_id, bool visible);
 
   gfx::Size GetVisibleViewportSize();
   gfx::Rect GetViewBounds();
index ede6cd4..a614933 100644 (file)
@@ -2758,6 +2758,47 @@ void EWebView::ClosePage() {
   web_contents_->ClosePage();
 }
 
+bool EWebView::SetMainFrameScrollbarVisible(bool visible) {
+  if (web_contents_->GetPrimaryMainFrame()->IsRenderFrameLive() && rwhva())
+    rwhva()->host()->SetMainFrameScrollbarVisible(visible);
+  return true;
+}
+
+bool EWebView::GetMainFrameScrollbarVisible(
+    Ewk_View_Main_Frame_Scrollbar_Visible_Get_Callback callback,
+    void* user_data) {
+  if (!rwhva())
+    return false;
+
+  MainFrameScrollbarVisibleGetCallback* callback_ptr =
+      new MainFrameScrollbarVisibleGetCallback;
+  callback_ptr->Set(callback, user_data);
+  int callback_id =
+      main_frame_scrollbar_visible_callback_map_.Add(callback_ptr);
+  rwhva()->host()->RequestMainFrameScrollbarVisible(callback_id);
+  return true;
+}
+
+void EWebView::InvokeMainFrameScrollbarVisibleCallback(int callback_id,
+                                                       bool visible) {
+  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    content::GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE,
+        base::BindOnce(&EWebView::InvokeMainFrameScrollbarVisibleCallback,
+                       base::Unretained(this), visible, callback_id));
+    return;
+  }
+
+  MainFrameScrollbarVisibleGetCallback* callback =
+      main_frame_scrollbar_visible_callback_map_.Lookup(callback_id);
+  if (!callback)
+    return;
+
+  main_frame_scrollbar_visible_callback_map_.Remove(callback_id);
+  callback->Run(evas_object(), visible);
+  main_frame_scrollbar_visible_callback_map_.Remove(callback_id);
+}
+
 void EWebView::OnOverscrolled(const gfx::Vector2dF& accumulated_overscroll,
                               const gfx::Vector2dF& latest_overscroll_delta) {
   const gfx::Vector2dF old_overscroll =
index eda7a4a..9d87a7a 100644 (file)
@@ -599,6 +599,13 @@ class EWebView {
   content::ContextMenuControllerEfl* GetContextMenuController() {
     return context_menu_.get();
   }
+
+  bool SetMainFrameScrollbarVisible(bool visible);
+  bool GetMainFrameScrollbarVisible(
+      Ewk_View_Main_Frame_Scrollbar_Visible_Get_Callback callback,
+      void* user_data);
+  void InvokeMainFrameScrollbarVisibleCallback(int callback_id, bool visible);
+
   void ResetContextMenuController();
   Eina_Bool AddJavaScriptMessageHandler(Evas_Object* view,
                                         Ewk_View_Script_Message_Cb callback,
index de2255c..6a6cb6d 100644 (file)
@@ -1223,10 +1223,20 @@ Eina_Bool ewk_view_top_controls_state_set(Evas_Object* ewk_view, Ewk_Top_Control
   return false;
 }
 
-Eina_Bool ewk_view_main_frame_scrollbar_visible_set(Evas_Object* o, Eina_Bool visible)
-{
-  LOG_EWK_API_MOCKUP();
-  return false;
+Eina_Bool ewk_view_main_frame_scrollbar_visible_set(Evas_Object* ewk_view,
+                                                    Eina_Bool visible) {
+  EWK_VIEW_IMPL_GET_OR_RETURN(ewk_view, impl, EINA_FALSE);
+  return impl->SetMainFrameScrollbarVisible(!!visible);
+}
+
+Eina_Bool ewk_view_main_frame_scrollbar_visible_get(
+    Evas_Object* ewk_view,
+    Ewk_View_Main_Frame_Scrollbar_Visible_Get_Callback callback,
+    void* user_data) {
+  EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EINA_FALSE);
+  EWK_VIEW_IMPL_GET_OR_RETURN(ewk_view, impl, EINA_FALSE);
+
+  return impl->GetMainFrameScrollbarVisible(callback, user_data);
 }
 
 Eina_Bool ewk_view_set_custom_device_pixel_ratio(Evas_Object* ewkView, Eina_Bool enabled)
index b911043..cf2899b 100644 (file)
@@ -656,4 +656,8 @@ void WebContentsDelegateEfl::OnDidGetManifest(
   }
 }
 
+void WebContentsDelegateEfl::OnGetMainFrameScrollbarVisible(int callback_id,
+                                                            bool visible) {
+  web_view_->InvokeMainFrameScrollbarVisibleCallback(callback_id, visible);
+}
 }  // namespace content
index 4fbbb1f..2c491c3 100644 (file)
@@ -64,6 +64,8 @@ class WebContentsDelegateEfl : public WebContentsDelegate {
                  int active_match_ordinal,
                  bool final_update) override;
   void DidRenderFrame() override;
+
+  void OnGetMainFrameScrollbarVisible(int callback_id, bool visible) override;
   void RequestCertificateConfirm(
       WebContents* web_contents,
       int cert_error,
index 4c47880..691ef67 100644 (file)
@@ -334,6 +334,7 @@ test("ewk_unittests") {
     "utc_blink_ewk_view_javascript_confirm_reply_func.cpp",
     "utc_blink_ewk_view_load_progress_get_func.cpp",
     "utc_blink_ewk_view_main_frame_get_func.cpp",
+    "utc_blink_ewk_view_main_frame_scrollbar_visible_set_func.cpp",
     "utc_blink_ewk_view_mhtml_data_get_func.cpp",
     "utc_blink_ewk_view_notification_permission_callback_set_func.cpp",
     "utc_blink_ewk_view_orientation_send_func.cpp",
diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_view_main_frame_scrollbar_visible_set_func.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_view_main_frame_scrollbar_visible_set_func.cpp
new file mode 100644 (file)
index 0000000..1e33ce6
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright 2022 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "utc_blink_ewk_base.h"
+
+class utc_blink_ewk_view_main_frame_scrollbar_visible_set
+    : public utc_blink_ewk_base {
+ protected:
+  void PostSetUp() override {
+    evas_object_smart_callback_add(GetEwkWebView(), "contents,size,changed",
+                                   ContentsSizeChanged, this);
+  }
+
+  void PreTearDown() override {
+    evas_object_smart_callback_del(GetEwkWebView(), "contents,size,changed",
+                                   ContentsSizeChanged);
+  }
+
+  static void ContentsSizeChanged(void* data,
+                                  Evas_Object* eObject,
+                                  void* dataFinished) {
+    if (data) {
+      static_cast<utc_blink_ewk_view_main_frame_scrollbar_visible_set*>(data)
+          ->EventLoopStop(Success);
+    }
+  }
+
+  static void ScrollbarVisibleGetCallback(Evas_Object* eObject,
+                                          Eina_Bool visible,
+                                          void* data) {
+    utc_check_ne(data, nullptr);
+    utc_blink_ewk_view_main_frame_scrollbar_visible_set* owner = nullptr;
+    OwnerFromVoid(data, &owner);
+    utc_message("[ScrollbarVisibleGetCallback] :: visible = %s\n",
+                visible == EINA_TRUE ? "EINA_TRUE" : "EINA_FALSE");
+    utc_check_eq(owner->expected_visible_, visible);
+    owner->EventLoopStop(Success);
+  }
+
+ protected:
+  Eina_Bool expected_visible_;
+};
+
+TEST_F(utc_blink_ewk_view_main_frame_scrollbar_visible_set, TURN_OFF) {
+  Eina_Bool ret = EINA_FALSE;
+
+  // Loading the page triggers a call to ContentsSizeChanged callback.
+  utc_check_eq(EINA_TRUE, ewk_view_url_set(
+                              GetEwkWebView(),
+                              GetResourceUrl("common/sample_2.html").c_str()));
+  utc_check_eq(Success, EventLoopStart());
+
+  // Initially the scrollbar is visible.
+  expected_visible_ = EINA_TRUE;
+  ret = ewk_view_main_frame_scrollbar_visible_get(
+      GetEwkWebView(), ScrollbarVisibleGetCallback, this);
+  utc_check_eq(ret, EINA_TRUE);
+  utc_check_eq(Success, EventLoopStart());
+
+  // Check that changing scrollbar visiblity triggers "contents,size,changed"
+  // callback. Indeed at this point only ContentsSizeChanged callback can stop
+  // the next call to EventLoopStart.
+  ret = ewk_view_main_frame_scrollbar_visible_set(GetEwkWebView(), false);
+  utc_check_eq(ret, EINA_TRUE);
+  utc_check_eq(Success, EventLoopStart());
+
+  // Check that the scrollbar is not visible.
+  expected_visible_ = EINA_FALSE;
+  ret = ewk_view_main_frame_scrollbar_visible_get(
+      GetEwkWebView(), ScrollbarVisibleGetCallback, this);
+  utc_check_eq(ret, EINA_TRUE);
+  utc_check_eq(Success, EventLoopStart());
+
+  // Make the scrollbar visible again.
+  ret = ewk_view_main_frame_scrollbar_visible_set(GetEwkWebView(), true);
+  utc_check_eq(ret, EINA_TRUE);
+  utc_check_eq(Success, EventLoopStart());
+  expected_visible_ = EINA_TRUE;
+  ret = ewk_view_main_frame_scrollbar_visible_get(
+      GetEwkWebView(), ScrollbarVisibleGetCallback, this);
+  utc_check_eq(ret, EINA_TRUE);
+  utc_check_eq(Success, EventLoopStart());
+}