Merge "Dummy graphics controller for test suite" into devel/graphics
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / web-view / web-view-impl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "web-view-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/adaptor-framework/web-engine-back-forward-list.h>
23 #include <dali/devel-api/adaptor-framework/web-engine-context.h>
24 #include <dali/devel-api/adaptor-framework/web-engine-cookie-manager.h>
25 #include <dali/devel-api/adaptor-framework/web-engine-settings.h>
26 #include <dali/devel-api/common/stage.h>
27 #include <dali/devel-api/scripting/enum-helper.h>
28 #include <dali/devel-api/scripting/scripting.h>
29 #include <dali/public-api/adaptor-framework/native-image-source.h>
30 #include <dali/public-api/object/type-registry-helper.h>
31 #include <dali/public-api/object/type-registry.h>
32 #include <cstring>
33
34 // INTERNAL INCLUDES
35 #include <dali-toolkit/devel-api/controls/control-devel.h>
36 #include <dali-toolkit/devel-api/controls/web-view/web-back-forward-list.h>
37 #include <dali-toolkit/devel-api/controls/web-view/web-context.h>
38 #include <dali-toolkit/devel-api/controls/web-view/web-cookie-manager.h>
39 #include <dali-toolkit/devel-api/controls/web-view/web-settings.h>
40 #include <dali-toolkit/devel-api/image-loader/texture-manager.h>
41 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
42 #include <dali-toolkit/public-api/image-loader/image.h>
43 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
44
45 namespace Dali
46 {
47 namespace Toolkit
48 {
49 namespace Internal
50 {
51 namespace
52 {
53 BaseHandle Create()
54 {
55   return Toolkit::WebView::New();
56 }
57
58 // clang-format off
59 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::WebView, Toolkit::Control, Create)
60
61 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "url",              STRING,  URL               )
62 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "userAgent",        STRING,  USER_AGENT        )
63 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "scrollPosition",   VECTOR2, SCROLL_POSITION   )
64 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "scrollSize",       VECTOR2, SCROLL_SIZE       )
65 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "contentSize",      VECTOR2, CONTENT_SIZE      )
66 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "title",            STRING,  TITLE             )
67 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "videoHoleEnabled", BOOLEAN, VIDEO_HOLE_ENABLED)
68
69 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadStarted",   PAGE_LOAD_STARTED_SIGNAL  )
70 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadFinished",  PAGE_LOAD_FINISHED_SIGNAL )
71 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadError",     PAGE_LOAD_ERROR_SIGNAL    )
72 DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "scrollEdgeReached", SCROLL_EDGE_REACHED_SIGNAL)
73
74 DALI_TYPE_REGISTRATION_END()
75 // clang-format on
76
77 const std::string kEmptyString;
78
79 } // namespace
80
81 #define GET_ENUM_STRING(structName, inputExp) \
82   Scripting::GetLinearEnumerationName<Toolkit::WebView::structName::Type>(static_cast<Toolkit::WebView::structName::Type>(inputExp), structName##_TABLE, structName##_TABLE_COUNT)
83
84 #define GET_ENUM_VALUE(structName, inputExp, outputExp) \
85   Scripting::GetEnumerationProperty<Toolkit::WebView::structName::Type>(inputExp, structName##_TABLE, structName##_TABLE_COUNT, outputExp)
86
87 WebView::WebView(const std::string& locale, const std::string& timezoneId)
88 : Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)),
89   mUrl(),
90   mVisual(),
91   mWebViewSize(Stage::GetCurrent().GetSize()),
92   mWebEngine(),
93   mPageLoadStartedSignal(),
94   mPageLoadFinishedSignal(),
95   mPageLoadErrorSignal(),
96   mVideoHoleEnabled(true),
97   mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height)
98 {
99   mWebEngine = Dali::WebEngine::New();
100
101   // WebEngine is empty when it is not properly initialized.
102   if(mWebEngine)
103   {
104     mWebEngine.Create(mWebViewSize.width, mWebViewSize.height, locale, timezoneId);
105   }
106 }
107
108 WebView::WebView(int argc, char** argv)
109 : Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)),
110   mUrl(),
111   mVisual(),
112   mWebViewSize(Stage::GetCurrent().GetSize()),
113   mWebEngine(),
114   mPageLoadStartedSignal(),
115   mPageLoadFinishedSignal(),
116   mPageLoadErrorSignal(),
117   mVideoHoleEnabled(true),
118   mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height)
119 {
120   mWebEngine = Dali::WebEngine::New();
121
122   // WebEngine is empty when it is not properly initialized.
123   if(mWebEngine)
124   {
125     mWebEngine.Create(mWebViewSize.width, mWebViewSize.height, argc, argv);
126   }
127 }
128
129 WebView::WebView()
130 : WebView("", "")
131 {
132 }
133
134 WebView::~WebView()
135 {
136   if(mWebEngine)
137   {
138     mWebEngine.Destroy();
139   }
140 }
141
142 Toolkit::WebView WebView::New()
143 {
144   WebView*         impl   = new WebView();
145   Toolkit::WebView handle = Toolkit::WebView(*impl);
146
147   impl->Initialize();
148   return handle;
149 }
150
151 Toolkit::WebView WebView::New(const std::string& locale, const std::string& timezoneId)
152 {
153   WebView*         impl   = new WebView(locale, timezoneId);
154   Toolkit::WebView handle = Toolkit::WebView(*impl);
155
156   impl->Initialize();
157   return handle;
158 }
159
160 Toolkit::WebView WebView::New(int argc, char** argv)
161 {
162   WebView*         impl   = new WebView(argc, argv);
163   Toolkit::WebView handle = Toolkit::WebView(*impl);
164
165   impl->Initialize();
166   return handle;
167 }
168
169 void WebView::OnInitialize()
170 {
171   Actor self = Self();
172
173   self.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
174   self.TouchedSignal().Connect(this, &WebView::OnTouchEvent);
175
176   mPositionUpdateNotification = self.AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f));
177   mSizeUpdateNotification     = self.AddPropertyNotification(Actor::Property::SIZE, StepCondition(1.0f, 1.0f));
178   mScaleUpdateNotification    = self.AddPropertyNotification(Actor::Property::WORLD_SCALE, StepCondition(0.1f, 1.0f));
179   mPositionUpdateNotification.NotifySignal().Connect(this, &WebView::UpdateDisplayArea);
180   mSizeUpdateNotification.NotifySignal().Connect(this, &WebView::UpdateDisplayArea);
181   mScaleUpdateNotification.NotifySignal().Connect(this, &WebView::UpdateDisplayArea);
182
183   if(mWebEngine)
184   {
185     mWebEngine.PageLoadStartedSignal().Connect(this, &WebView::OnPageLoadStarted);
186     mWebEngine.PageLoadFinishedSignal().Connect(this, &WebView::OnPageLoadFinished);
187     mWebEngine.PageLoadErrorSignal().Connect(this, &WebView::OnPageLoadError);
188     mWebEngine.ScrollEdgeReachedSignal().Connect(this, &WebView::OnScrollEdgeReached);
189
190     mWebContext         = std::unique_ptr<Dali::Toolkit::WebContext>(new WebContext(mWebEngine.GetContext()));
191     mWebCookieManager   = std::unique_ptr<Dali::Toolkit::WebCookieManager>(new WebCookieManager(mWebEngine.GetCookieManager()));
192     mWebSettings        = std::unique_ptr<Dali::Toolkit::WebSettings>(new WebSettings(mWebEngine.GetSettings()));
193     mWebBackForwardList = std::unique_ptr<Dali::Toolkit::WebBackForwardList>(new WebBackForwardList(mWebEngine.GetBackForwardList()));
194   }
195 }
196
197 Dali::Toolkit::WebSettings* WebView::GetSettings() const
198 {
199   return mWebSettings.get();
200 }
201
202 Dali::Toolkit::WebContext* WebView::GetContext() const
203 {
204   return mWebContext.get();
205 }
206
207 Dali::Toolkit::WebCookieManager* WebView::GetCookieManager() const
208 {
209   return mWebCookieManager.get();
210 }
211
212 Dali::Toolkit::WebBackForwardList* WebView::GetBackForwardList() const
213 {
214   return mWebBackForwardList.get();
215 }
216
217 Dali::Toolkit::ImageView& WebView::GetFavicon()
218 {
219   if(mWebEngine)
220   {
221     Dali::PixelData pixelData = mWebEngine.GetFavicon();
222     std::string     url       = Dali::Toolkit::Image::GenerateUrl(pixelData);
223     mFaviconView              = Dali::Toolkit::ImageView::New(url);
224     mFaviconView.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS);
225     mFaviconView.SetProperty(Dali::Actor::Property::SIZE, Vector2(pixelData.GetWidth(), pixelData.GetHeight()));
226   }
227   return mFaviconView;
228 }
229
230 void WebView::LoadUrl(const std::string& url)
231 {
232   mUrl = url;
233   if(mWebEngine)
234   {
235     Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
236     const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
237     mVisual                          = Toolkit::VisualFactory::Get().CreateVisual(
238       {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
239        {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
240
241     if(mVisual)
242     {
243       // Clean up previously registered visual and add new one.
244       DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
245       mWebEngine.LoadUrl(url);
246     }
247
248     if(mVideoHoleEnabled)
249     {
250       EnableBlendMode(false);
251     }
252   }
253 }
254
255 void WebView::LoadHtmlString(const std::string& htmlString)
256 {
257   if(mWebEngine)
258   {
259     Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
260     const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
261     mVisual                          = Toolkit::VisualFactory::Get().CreateVisual(
262       {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
263        {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
264
265     if(mVisual)
266     {
267       DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
268       mWebEngine.LoadHtmlString(htmlString);
269     }
270
271     if(mVideoHoleEnabled)
272     {
273       EnableBlendMode(false);
274     }
275   }
276 }
277
278 void WebView::Reload()
279 {
280   if(mWebEngine)
281   {
282     mWebEngine.Reload();
283   }
284 }
285
286 void WebView::StopLoading()
287 {
288   if(mWebEngine)
289   {
290     mWebEngine.StopLoading();
291   }
292 }
293
294 void WebView::Suspend()
295 {
296   if(mWebEngine)
297   {
298     mWebEngine.Suspend();
299   }
300 }
301
302 void WebView::Resume()
303 {
304   if(mWebEngine)
305   {
306     mWebEngine.Resume();
307   }
308 }
309
310 void WebView::ScrollBy(int deltaX, int deltaY)
311 {
312   if(mWebEngine)
313   {
314     mWebEngine.ScrollBy(deltaX, deltaY);
315   }
316 }
317
318 bool WebView::CanGoForward()
319 {
320   return mWebEngine ? mWebEngine.CanGoForward() : false;
321 }
322
323 void WebView::GoForward()
324 {
325   if(mWebEngine)
326   {
327     mWebEngine.GoForward();
328   }
329 }
330
331 bool WebView::CanGoBack()
332 {
333   return mWebEngine ? mWebEngine.CanGoBack() : false;
334 }
335
336 void WebView::GoBack()
337 {
338   if(mWebEngine)
339   {
340     mWebEngine.GoBack();
341   }
342 }
343
344 void WebView::EvaluateJavaScript(const std::string& script, std::function<void(const std::string&)> resultHandler)
345 {
346   if(mWebEngine)
347   {
348     mWebEngine.EvaluateJavaScript(script, resultHandler);
349   }
350 }
351
352 void WebView::AddJavaScriptMessageHandler(const std::string& exposedObjectName, std::function<void(const std::string&)> handler)
353 {
354   if(mWebEngine)
355   {
356     mWebEngine.AddJavaScriptMessageHandler(exposedObjectName, handler);
357   }
358 }
359
360 void WebView::ClearAllTilesResources()
361 {
362   if(mWebEngine)
363   {
364     mWebEngine.ClearAllTilesResources();
365   }
366 }
367
368 void WebView::ClearHistory()
369 {
370   if(mWebEngine)
371   {
372     mWebEngine.ClearHistory();
373   }
374 }
375
376 void WebView::UpdateDisplayArea(Dali::PropertyNotification& /*source*/)
377 {
378   if(!mWebEngine)
379     return;
380
381   Actor self(Self());
382
383   bool    positionUsesAnchorPoint = self.GetProperty<bool>(Actor::Property::POSITION_USES_ANCHOR_POINT);
384   Vector3 actorSize               = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * self.GetCurrentProperty<Vector3>(Actor::Property::SCALE);
385   Vector3 anchorPointOffSet       = actorSize * (positionUsesAnchorPoint ? self.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT);
386   Vector2 screenPosition          = self.GetProperty<Vector2>(Actor::Property::SCREEN_POSITION);
387
388   Dali::Rect<int> displayArea;
389   displayArea.x      = screenPosition.x - anchorPointOffSet.x;
390   displayArea.y      = screenPosition.y - anchorPointOffSet.y;
391   displayArea.width  = actorSize.x;
392   displayArea.height = actorSize.y;
393
394   Size displaySize = Size(displayArea.width, displayArea.height);
395   if(mWebViewSize != displaySize)
396   {
397     mWebViewSize = displaySize;
398   }
399
400   if(mWebViewArea != displayArea)
401   {
402     mWebViewArea = displayArea;
403     mWebEngine.UpdateDisplayArea(mWebViewArea);
404   }
405 }
406
407 void WebView::EnableVideoHole(bool enabled)
408 {
409   mVideoHoleEnabled = enabled;
410
411   EnableBlendMode(!mVideoHoleEnabled);
412
413   if(mWebEngine)
414   {
415     mWebEngine.EnableVideoHole(mVideoHoleEnabled);
416   }
417 }
418
419 void WebView::EnableBlendMode(bool blendEnabled)
420 {
421   Actor self = Self();
422   for(uint32_t i = 0; i < self.GetRendererCount(); i++)
423   {
424     Dali::Renderer render = self.GetRendererAt(i);
425     render.SetProperty(Renderer::Property::BLEND_MODE, blendEnabled ? BlendMode::ON : BlendMode::OFF);
426   }
427 }
428
429 Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadStartedSignal()
430 {
431   return mPageLoadStartedSignal;
432 }
433
434 Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadFinishedSignal()
435 {
436   return mPageLoadFinishedSignal;
437 }
438
439 Dali::Toolkit::WebView::WebViewPageLoadErrorSignalType& WebView::PageLoadErrorSignal()
440 {
441   return mPageLoadErrorSignal;
442 }
443
444 Dali::Toolkit::WebView::WebViewScrollEdgeReachedSignalType& WebView::ScrollEdgeReachedSignal()
445 {
446   return mScrollEdgeReachedSignal;
447 }
448
449 void WebView::OnPageLoadStarted(const std::string& url)
450 {
451   if(!mPageLoadStartedSignal.Empty())
452   {
453     Dali::Toolkit::WebView handle(GetOwner());
454     mPageLoadStartedSignal.Emit(handle, url);
455   }
456 }
457
458 void WebView::OnPageLoadFinished(const std::string& url)
459 {
460   if(!mPageLoadFinishedSignal.Empty())
461   {
462     Dali::Toolkit::WebView handle(GetOwner());
463     mPageLoadFinishedSignal.Emit(handle, url);
464   }
465 }
466
467 void WebView::OnPageLoadError(const std::string& url, int errorCode)
468 {
469   if(!mPageLoadErrorSignal.Empty())
470   {
471     Dali::Toolkit::WebView handle(GetOwner());
472     mPageLoadErrorSignal.Emit(handle, url, static_cast<Toolkit::WebView::LoadErrorCode>(errorCode));
473   }
474 }
475
476 void WebView::OnScrollEdgeReached(Dali::WebEnginePlugin::ScrollEdge edge)
477 {
478   if(!mScrollEdgeReachedSignal.Empty())
479   {
480     Dali::Toolkit::WebView handle(GetOwner());
481     mScrollEdgeReachedSignal.Emit(handle, edge);
482   }
483 }
484
485 bool WebView::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
486 {
487   Dali::BaseHandle handle(object);
488
489   bool             connected = false;
490   Toolkit::WebView webView   = Toolkit::WebView::DownCast(handle);
491
492   if(0 == strcmp(signalName.c_str(), PAGE_LOAD_STARTED_SIGNAL))
493   {
494     webView.PageLoadStartedSignal().Connect(tracker, functor);
495     connected = true;
496   }
497   else if(0 == strcmp(signalName.c_str(), PAGE_LOAD_FINISHED_SIGNAL))
498   {
499     webView.PageLoadFinishedSignal().Connect(tracker, functor);
500     connected = true;
501   }
502   else if(0 == strcmp(signalName.c_str(), PAGE_LOAD_ERROR_SIGNAL))
503   {
504     webView.PageLoadErrorSignal().Connect(tracker, functor);
505     connected = true;
506   }
507   else if(0 == strcmp(signalName.c_str(), SCROLL_EDGE_REACHED_SIGNAL))
508   {
509     webView.ScrollEdgeReachedSignal().Connect(tracker, functor);
510     connected = true;
511   }
512
513   return connected;
514 }
515
516 Vector3 WebView::GetNaturalSize()
517 {
518   if(mVisual)
519   {
520     Vector2 rendererNaturalSize;
521     mVisual.GetNaturalSize(rendererNaturalSize);
522     return Vector3(rendererNaturalSize);
523   }
524
525   return Vector3(mWebViewSize);
526 }
527
528 void WebView::OnSceneConnection(int depth)
529 {
530   Control::OnSceneConnection(depth);
531
532   EnableBlendMode(!mVideoHoleEnabled);
533 }
534
535 void WebView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
536 {
537   Toolkit::WebView webView = Toolkit::WebView::DownCast(Dali::BaseHandle(object));
538
539   if(webView)
540   {
541     WebView& impl = GetImpl(webView);
542     switch(index)
543     {
544       case Toolkit::WebView::Property::URL:
545       {
546         std::string url;
547         if(value.Get(url))
548         {
549           impl.LoadUrl(url);
550         }
551         break;
552       }
553       case Toolkit::WebView::Property::USER_AGENT:
554       {
555         std::string input;
556         if(value.Get(input))
557         {
558           impl.SetUserAgent(input);
559         }
560         break;
561       }
562       case Toolkit::WebView::Property::SCROLL_POSITION:
563       {
564         Vector2 input;
565         if(value.Get(input))
566         {
567           impl.SetScrollPosition(input.x, input.y);
568         }
569         break;
570       }
571       case Toolkit::WebView::Property::VIDEO_HOLE_ENABLED:
572       {
573         bool input;
574         if(value.Get(input))
575         {
576           impl.EnableVideoHole(input);
577         }
578         break;
579       }
580     }
581   }
582 }
583
584 Property::Value WebView::GetProperty(BaseObject* object, Property::Index propertyIndex)
585 {
586   Property::Value value;
587
588   Toolkit::WebView webView = Toolkit::WebView::DownCast(Dali::BaseHandle(object));
589
590   if(webView)
591   {
592     WebView& impl = GetImpl(webView);
593     switch(propertyIndex)
594     {
595       case Toolkit::WebView::Property::URL:
596       {
597         value = impl.mUrl;
598         break;
599       }
600       case Toolkit::WebView::Property::USER_AGENT:
601       {
602         value = impl.GetUserAgent();
603         break;
604       }
605       case Toolkit::WebView::Property::SCROLL_POSITION:
606       {
607         value = impl.GetScrollPosition();
608         break;
609       }
610       case Toolkit::WebView::Property::SCROLL_SIZE:
611       {
612         value = impl.GetScrollSize();
613         break;
614       }
615       case Toolkit::WebView::Property::CONTENT_SIZE:
616       {
617         value = impl.GetContentSize();
618         break;
619       }
620       case Toolkit::WebView::Property::TITLE:
621       {
622         value = impl.GetTitle();
623         break;
624       }
625       case Toolkit::WebView::Property::VIDEO_HOLE_ENABLED:
626       {
627         value = impl.mVideoHoleEnabled;
628         break;
629       }
630       default:
631         break;
632     }
633   }
634
635   return value;
636 }
637
638 bool WebView::OnTouchEvent(Actor actor, const Dali::TouchEvent& touch)
639 {
640   bool result = false;
641
642   if(mWebEngine)
643   {
644     result = mWebEngine.SendTouchEvent(touch);
645   }
646   return result;
647 }
648
649 bool WebView::OnKeyEvent(const Dali::KeyEvent& event)
650 {
651   bool result = false;
652
653   if(mWebEngine)
654   {
655     result = mWebEngine.SendKeyEvent(event);
656   }
657   return result;
658 }
659
660 void WebView::OnKeyInputFocusGained()
661 {
662   if(mWebEngine)
663   {
664     mWebEngine.SetFocus(true);
665   }
666
667   EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last.
668 }
669
670 void WebView::OnKeyInputFocusLost()
671 {
672   if(mWebEngine)
673   {
674     mWebEngine.SetFocus(false);
675   }
676
677   EmitKeyInputFocusSignal(false); // Calls back into the Control hence done last.
678 }
679
680 void WebView::SetScrollPosition(int x, int y)
681 {
682   if(mWebEngine)
683   {
684     mWebEngine.SetScrollPosition(x, y);
685   }
686 }
687
688 Dali::Vector2 WebView::GetScrollPosition() const
689 {
690   return mWebEngine ? mWebEngine.GetScrollPosition() : Dali::Vector2::ZERO;
691 }
692
693 Dali::Vector2 WebView::GetScrollSize() const
694 {
695   return mWebEngine ? mWebEngine.GetScrollSize() : Dali::Vector2::ZERO;
696 }
697
698 Dali::Vector2 WebView::GetContentSize() const
699 {
700   return mWebEngine ? mWebEngine.GetContentSize() : Dali::Vector2::ZERO;
701 }
702
703 std::string WebView::GetTitle() const
704 {
705   return mWebEngine ? mWebEngine.GetTitle() : kEmptyString;
706 }
707
708 const std::string& WebView::GetUserAgent() const
709 {
710   return mWebEngine ? mWebEngine.GetUserAgent() : kEmptyString;
711 }
712
713 void WebView::SetUserAgent(const std::string& userAgent)
714 {
715   if(mWebEngine)
716   {
717     mWebEngine.SetUserAgent(userAgent);
718   }
719 }
720
721 #undef GET_ENUM_STRING
722 #undef GET_ENUM_VALUE
723
724 } // namespace Internal
725
726 } // namespace Toolkit
727
728 } // namespace Dali