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