Set focus to web engine.
[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/scripting/enum-helper.h>
24 #include <dali/devel-api/scripting/scripting.h>
25 #include <dali/devel-api/common/stage.h>
26 #include <dali/public-api/adaptor-framework/native-image-source.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/public-api/object/type-registry-helper.h>
29
30 // INTERNAL INCLUDES
31 #include <dali-toolkit/devel-api/controls/control-devel.h>
32 #include <dali-toolkit/devel-api/image-loader/texture-manager.h>
33 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
34 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
35
36 namespace Dali
37 {
38
39 namespace Toolkit
40 {
41
42 namespace Internal
43 {
44
45 namespace
46 {
47
48 BaseHandle Create()
49 {
50   return Toolkit::WebView::New();
51 }
52
53 DALI_ENUM_TO_STRING_TABLE_BEGIN( CacheModel )
54 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::WebView::CacheModel, DOCUMENT_VIEWER )
55 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::WebView::CacheModel, DOCUMENT_BROWSER )
56 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::WebView::CacheModel, PRIMARY_WEB_BROWSER )
57 DALI_ENUM_TO_STRING_TABLE_END( CacheModel )
58
59 DALI_ENUM_TO_STRING_TABLE_BEGIN( CookieAcceptPolicy )
60 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::WebView::CookieAcceptPolicy, ALWAYS )
61 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::WebView::CookieAcceptPolicy, NEVER )
62 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::WebView::CookieAcceptPolicy, NO_THIRD_PARTY )
63 DALI_ENUM_TO_STRING_TABLE_END( CookieAcceptPolicy )
64
65 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::WebView, Toolkit::Control, Create )
66
67 DALI_PROPERTY_REGISTRATION( Toolkit, WebView, "url",                     STRING,  URL                        )
68 DALI_PROPERTY_REGISTRATION( Toolkit, WebView, "cacheModel",              STRING,  CACHE_MODEL                )
69 DALI_PROPERTY_REGISTRATION( Toolkit, WebView, "cookieAcceptPolicy",      STRING,  COOKIE_ACCEPT_POLICY       )
70 DALI_PROPERTY_REGISTRATION( Toolkit, WebView, "userAgent",               STRING,  USER_AGENT                 )
71 DALI_PROPERTY_REGISTRATION( Toolkit, WebView, "enableJavaScript",        BOOLEAN, ENABLE_JAVASCRIPT          )
72 DALI_PROPERTY_REGISTRATION( Toolkit, WebView, "loadImagesAutomatically", BOOLEAN, LOAD_IMAGES_AUTOMATICALLY  )
73 DALI_PROPERTY_REGISTRATION( Toolkit, WebView, "defaultTextEncodingName", STRING,  DEFAULT_TEXT_ENCODING_NAME )
74 DALI_PROPERTY_REGISTRATION( Toolkit, WebView, "defaultFontSize",         INTEGER, DEFAULT_FONT_SIZE          )
75
76 DALI_SIGNAL_REGISTRATION(   Toolkit, WebView, "pageLoadStarted",         PAGE_LOAD_STARTED_SIGNAL            )
77 DALI_SIGNAL_REGISTRATION(   Toolkit, WebView, "pageLoadFinished",        PAGE_LOAD_FINISHED_SIGNAL           )
78 DALI_SIGNAL_REGISTRATION(   Toolkit, WebView, "pageLoadError",           PAGE_LOAD_ERROR_SIGNAL              )
79
80 DALI_TYPE_REGISTRATION_END()
81
82 const std::string kEmptyString;
83
84 } // anonymous namepsace
85
86 #define GET_ENUM_STRING( structName, inputExp ) \
87   Scripting::GetLinearEnumerationName< Toolkit::WebView::structName::Type >( static_cast< Toolkit::WebView::structName::Type >( inputExp ), structName##_TABLE, structName##_TABLE_COUNT )
88
89 #define GET_ENUM_VALUE( structName, inputExp, outputExp ) \
90   Scripting::GetEnumerationProperty< Toolkit::WebView::structName::Type >( inputExp, structName##_TABLE, structName##_TABLE_COUNT, outputExp )
91
92 WebView::WebView( const std::string& locale, const std::string& timezoneId )
93 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS ) ),
94   mUrl(),
95   mVisual(),
96   mWebViewSize( Stage::GetCurrent().GetSize() ),
97   mWebEngine(),
98   mPageLoadStartedSignal(),
99   mPageLoadFinishedSignal(),
100   mPageLoadErrorSignal()
101 {
102   mWebEngine = Dali::WebEngine::New();
103
104   // WebEngine is empty when it is not properly initialized.
105   if( mWebEngine )
106   {
107     mWebEngine.Create( mWebViewSize.width, mWebViewSize.height, locale, timezoneId );
108   }
109 }
110
111 WebView::WebView()
112 : WebView( "", "" )
113 {
114 }
115
116 WebView::~WebView()
117 {
118 }
119
120 Toolkit::WebView WebView::New()
121 {
122   WebView* impl = new WebView();
123   Toolkit::WebView handle = Toolkit::WebView( *impl );
124
125   impl->Initialize();
126   return handle;
127 }
128
129 Toolkit::WebView WebView::New( const std::string& locale, const std::string& timezoneId )
130 {
131   WebView* impl = new WebView( locale, timezoneId );
132   Toolkit::WebView handle = Toolkit::WebView( *impl );
133
134   impl->Initialize();
135   return handle;
136 }
137
138 void WebView::OnInitialize()
139 {
140   Self().SetProperty( Actor::Property::KEYBOARD_FOCUSABLE, true );
141   Self().TouchedSignal().Connect( this, &WebView::OnTouchEvent );
142
143   if( mWebEngine )
144   {
145     mWebEngine.PageLoadStartedSignal().Connect( this, &WebView::OnPageLoadStarted );
146     mWebEngine.PageLoadFinishedSignal().Connect( this, &WebView::OnPageLoadFinished );
147     mWebEngine.PageLoadErrorSignal().Connect( this, &WebView::OnPageLoadError );
148   }
149 }
150
151 void WebView::LoadUrl( const std::string& url )
152 {
153   mUrl = url;
154   if( mWebEngine )
155   {
156     Texture texture = Dali::Texture::New( *mWebEngine.GetNativeImageSource() );
157     const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture( texture );
158     mVisual = Toolkit::VisualFactory::Get().CreateVisual(
159       { { Toolkit::Visual::Property::TYPE,  Toolkit::Visual::IMAGE } ,
160         { Toolkit::ImageVisual::Property::URL, nativeImageUrl } } );
161
162     if( mVisual )
163     {
164       // Clean up previously registered visual and add new one.
165       DevelControl::RegisterVisual( *this, Toolkit::WebView::Property::URL, mVisual );
166       mWebEngine.LoadUrl( url );
167     }
168   }
169 }
170
171 void WebView::LoadHTMLString( const std::string& htmlString )
172 {
173   if( mWebEngine )
174   {
175     Texture texture = Dali::Texture::New( *mWebEngine.GetNativeImageSource() );
176     const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture( texture );
177     mVisual = Toolkit::VisualFactory::Get().CreateVisual(
178       { { Toolkit::Visual::Property::TYPE,  Toolkit::Visual::IMAGE } ,
179         { Toolkit::ImageVisual::Property::URL, nativeImageUrl } } );
180
181     if( mVisual )
182     {
183       DevelControl::RegisterVisual( *this, Toolkit::WebView::Property::URL, mVisual );
184       mWebEngine.LoadHTMLString( htmlString );
185     }
186   }
187 }
188
189 void WebView::Reload()
190 {
191   if( mWebEngine )
192   {
193     mWebEngine.Reload();
194   }
195 }
196
197 void WebView::StopLoading()
198 {
199   if( mWebEngine )
200   {
201     mWebEngine.StopLoading();
202   }
203 }
204
205 void WebView::Suspend()
206 {
207   if( mWebEngine )
208   {
209     mWebEngine.Suspend();
210   }
211 }
212
213 void WebView::Resume()
214 {
215   if( mWebEngine )
216   {
217     mWebEngine.Resume();
218   }
219 }
220
221 bool WebView::CanGoForward()
222 {
223   return mWebEngine ? mWebEngine.CanGoForward() : false;
224 }
225
226 void WebView::GoForward()
227 {
228   if( mWebEngine )
229   {
230     mWebEngine.GoForward();
231   }
232 }
233
234 bool WebView::CanGoBack()
235 {
236   return mWebEngine ? mWebEngine.CanGoBack() : false;
237 }
238
239 void WebView::GoBack()
240 {
241   if( mWebEngine )
242   {
243     mWebEngine.GoBack();
244   }
245 }
246
247 void WebView::EvaluateJavaScript( const std::string& script, std::function< void( const std::string& ) > resultHandler )
248 {
249   if( mWebEngine )
250   {
251     mWebEngine.EvaluateJavaScript( script, resultHandler );
252   }
253 }
254
255 void WebView::AddJavaScriptMessageHandler( const std::string& exposedObjectName, std::function< void( const std::string& ) > handler )
256 {
257   if( mWebEngine )
258   {
259     mWebEngine.AddJavaScriptMessageHandler( exposedObjectName, handler );
260   }
261 }
262
263 void WebView::ClearHistory()
264 {
265   if( mWebEngine )
266   {
267     mWebEngine.ClearHistory();
268   }
269 }
270
271 void WebView::ClearCache()
272 {
273   if( mWebEngine )
274   {
275     mWebEngine.ClearCache();
276   }
277 }
278
279 void WebView::ClearCookies()
280 {
281   if( mWebEngine )
282   {
283     mWebEngine.ClearCookies();
284   }
285 }
286
287 Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadStartedSignal()
288 {
289   return mPageLoadStartedSignal;
290 }
291
292 Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadFinishedSignal()
293 {
294   return mPageLoadFinishedSignal;
295 }
296
297 Dali::Toolkit::WebView::WebViewPageLoadErrorSignalType& WebView::PageLoadErrorSignal()
298 {
299   return mPageLoadErrorSignal;
300 }
301
302 void WebView::OnPageLoadStarted( const std::string& url )
303 {
304   if( !mPageLoadStartedSignal.Empty() )
305   {
306     Dali::Toolkit::WebView handle( GetOwner() );
307     mPageLoadStartedSignal.Emit( handle, url );
308   }
309 }
310
311 void WebView::OnPageLoadFinished( const std::string& url )
312 {
313   if( !mPageLoadFinishedSignal.Empty() )
314   {
315     Dali::Toolkit::WebView handle( GetOwner() );
316     mPageLoadFinishedSignal.Emit( handle, url );
317   }
318 }
319
320 void WebView::OnPageLoadError( const std::string& url, int errorCode )
321 {
322   if( !mPageLoadErrorSignal.Empty() )
323   {
324     Dali::Toolkit::WebView handle( GetOwner() );
325     mPageLoadErrorSignal.Emit( handle, url, static_cast< Toolkit::WebView::LoadErrorCode >( errorCode ) );
326   }
327 }
328
329 bool WebView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
330 {
331   Dali::BaseHandle handle( object );
332
333   bool connected = false;
334   Toolkit::WebView webView = Toolkit::WebView::DownCast( handle );
335
336   if( 0 == strcmp( signalName.c_str(), PAGE_LOAD_STARTED_SIGNAL ) )
337   {
338     webView.PageLoadStartedSignal().Connect( tracker, functor );
339     connected = true;
340   }
341   else if( 0 == strcmp( signalName.c_str(), PAGE_LOAD_FINISHED_SIGNAL ) )
342   {
343     webView.PageLoadFinishedSignal().Connect( tracker, functor );
344     connected = true;
345   }
346   else if( 0 == strcmp( signalName.c_str(), PAGE_LOAD_ERROR_SIGNAL ) )
347   {
348     webView.PageLoadErrorSignal().Connect( tracker, functor );
349     connected = true;
350   }
351
352   return connected;
353 }
354
355 Vector3 WebView::GetNaturalSize()
356 {
357   if( mVisual )
358   {
359     Vector2 rendererNaturalSize;
360     mVisual.GetNaturalSize( rendererNaturalSize );
361     return Vector3( rendererNaturalSize );
362   }
363
364   return Vector3( mWebViewSize );
365 }
366
367 void WebView::OnRelayout( const Vector2& size, RelayoutContainer& container )
368 {
369   Control::OnRelayout( size, container );
370
371   if( size.width > 0 && size.height > 0 && mWebViewSize != size )
372   {
373     mWebViewSize = size;
374
375     if( mWebEngine )
376     {
377       mWebEngine.SetSize( size.width, size.height );
378     }
379   }
380 }
381
382 void WebView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
383 {
384   Toolkit::WebView webView = Toolkit::WebView::DownCast( Dali::BaseHandle( object ) );
385
386   if( webView )
387   {
388     WebView& impl = GetImpl( webView );
389     switch( index )
390     {
391       case Toolkit::WebView::Property::URL:
392       {
393         std::string url;
394         if( value.Get( url ) )
395         {
396           impl.LoadUrl( url );
397         }
398         break;
399       }
400       case Toolkit::WebView::Property::CACHE_MODEL:
401       {
402         Toolkit::WebView::CacheModel::Type output = impl.GetCacheModel();
403         GET_ENUM_VALUE( CacheModel, value, output );
404         impl.SetCacheModel( output );
405         break;
406       }
407       case Toolkit::WebView::Property::COOKIE_ACCEPT_POLICY:
408       {
409         Toolkit::WebView::CookieAcceptPolicy::Type output = impl.GetCookieAcceptPolicy();
410         GET_ENUM_VALUE( CookieAcceptPolicy, value, output );
411         impl.SetCookieAcceptPolicy( output );
412         break;
413       }
414       case Toolkit::WebView::Property::USER_AGENT:
415       {
416         std::string input;
417         if( value.Get( input ) )
418         {
419           impl.SetUserAgent( input );
420         }
421         break;
422       }
423       case Toolkit::WebView::Property::ENABLE_JAVASCRIPT:
424       {
425         bool input;
426         if( value.Get( input ) )
427         {
428           impl.EnableJavaScript( input );
429         }
430         break;
431       }
432       case Toolkit::WebView::Property::LOAD_IMAGES_AUTOMATICALLY:
433       {
434         bool input;
435         if( value.Get( input ) )
436         {
437           impl.LoadImagesAutomatically( input );
438         }
439         break;
440       }
441       case Toolkit::WebView::Property::DEFAULT_TEXT_ENCODING_NAME:
442       {
443         std::string input;
444         if( value.Get( input ) )
445         {
446           impl.SetDefaultTextEncodingName( input );
447         }
448         break;
449       }
450       case Toolkit::WebView::Property::DEFAULT_FONT_SIZE:
451       {
452         int input;
453         if( value.Get( input ) )
454         {
455           impl.SetDefaultFontSize( input );
456         }
457         break;
458       }
459     }
460   }
461 }
462
463 Property::Value WebView::GetProperty( BaseObject* object, Property::Index propertyIndex )
464 {
465   Property::Value value;
466
467   Toolkit::WebView webView = Toolkit::WebView::DownCast( Dali::BaseHandle( object ) );
468
469   if( webView )
470   {
471     WebView& impl = GetImpl( webView );
472     switch( propertyIndex )
473     {
474       case Toolkit::WebView::Property::URL:
475       {
476         value = impl.mUrl;
477         break;
478       }
479       case Toolkit::WebView::Property::CACHE_MODEL:
480       {
481         value = GET_ENUM_STRING( CacheModel, impl.GetCacheModel() );
482         break;
483       }
484       case Toolkit::WebView::Property::COOKIE_ACCEPT_POLICY:
485       {
486         value = GET_ENUM_STRING( CookieAcceptPolicy, impl.GetCookieAcceptPolicy() );
487         break;
488       }
489       case Toolkit::WebView::Property::USER_AGENT:
490       {
491         value = impl.GetUserAgent();
492         break;
493       }
494       case Toolkit::WebView::Property::ENABLE_JAVASCRIPT:
495       {
496         value = impl.IsJavaScriptEnabled();
497         break;
498       }
499       case Toolkit::WebView::Property::LOAD_IMAGES_AUTOMATICALLY:
500       {
501         value = impl.AreImagesAutomaticallyLoaded();
502         break;
503       }
504       case Toolkit::WebView::Property::DEFAULT_TEXT_ENCODING_NAME:
505       {
506         value = impl.GetDefaultTextEncodingName();
507         break;
508       }
509       case Toolkit::WebView::Property::DEFAULT_FONT_SIZE:
510       {
511         value = impl.GetDefaultFontSize();
512         break;
513       }
514       default:
515          break;
516     }
517   }
518
519   return value;
520 }
521
522 bool WebView::OnTouchEvent( Actor actor, const Dali::TouchEvent& touch )
523 {
524   bool result = false;
525
526   if( mWebEngine )
527   {
528     result = mWebEngine.SendTouchEvent( touch );
529   }
530   return result;
531 }
532
533 bool WebView::OnKeyEvent( const Dali::KeyEvent& event )
534 {
535   bool result = false;
536
537   if( mWebEngine )
538   {
539     result = mWebEngine.SendKeyEvent( event );
540   }
541   return result;
542 }
543
544 void WebView::OnKeyInputFocusGained()
545 {
546   if( mWebEngine )
547   {
548     mWebEngine.SetFocus( true );
549   }
550
551   EmitKeyInputFocusSignal( true ); // Calls back into the Control hence done last.
552 }
553
554 void WebView::OnKeyInputFocusLost()
555 {
556   if( mWebEngine )
557   {
558     mWebEngine.SetFocus( false );
559   }
560
561   EmitKeyInputFocusSignal( false ); // Calls back into the Control hence done last.
562 }
563
564 Toolkit::WebView::CacheModel::Type WebView::GetCacheModel() const
565 {
566   return mWebEngine ? static_cast< Toolkit::WebView::CacheModel::Type >( mWebEngine.GetCacheModel() ) : Toolkit::WebView::CacheModel::DOCUMENT_VIEWER;
567 }
568
569 void WebView::SetCacheModel( Toolkit::WebView::CacheModel::Type cacheModel )
570 {
571   if( mWebEngine )
572   {
573     mWebEngine.SetCacheModel( static_cast< WebEnginePlugin::CacheModel >( cacheModel ) );
574   }
575 }
576
577 Toolkit::WebView::CookieAcceptPolicy::Type WebView::GetCookieAcceptPolicy() const
578 {
579   return mWebEngine ? static_cast< Toolkit::WebView::CookieAcceptPolicy::Type >( mWebEngine.GetCookieAcceptPolicy() ) : Toolkit::WebView::CookieAcceptPolicy::NO_THIRD_PARTY;
580 }
581
582 void WebView::SetCookieAcceptPolicy( Toolkit::WebView::CookieAcceptPolicy::Type policy )
583 {
584   if( mWebEngine )
585   {
586     mWebEngine.SetCookieAcceptPolicy( static_cast< WebEnginePlugin::CookieAcceptPolicy >( policy ) );
587   }
588 }
589
590 const std::string& WebView::GetUserAgent() const
591 {
592   return mWebEngine ? mWebEngine.GetUserAgent() : kEmptyString;
593 }
594
595 void WebView::SetUserAgent( const std::string& userAgent )
596 {
597   if( mWebEngine )
598   {
599     mWebEngine.SetUserAgent( userAgent );
600   }
601 }
602
603 bool WebView::IsJavaScriptEnabled() const
604 {
605   return mWebEngine ? mWebEngine.IsJavaScriptEnabled() : true;
606 }
607
608 void WebView::EnableJavaScript( bool enabled )
609 {
610   if( mWebEngine )
611   {
612     mWebEngine.EnableJavaScript( enabled );
613   }
614 }
615
616 bool WebView::AreImagesAutomaticallyLoaded() const
617 {
618   return mWebEngine ? mWebEngine.AreImagesAutomaticallyLoaded() : true;
619 }
620
621 void WebView::LoadImagesAutomatically( bool automatic )
622 {
623   if( mWebEngine )
624   {
625     mWebEngine.LoadImagesAutomatically( automatic );
626   }
627 }
628
629 const std::string& WebView::GetDefaultTextEncodingName() const
630 {
631   return mWebEngine ? mWebEngine.GetDefaultTextEncodingName() : kEmptyString;
632 }
633
634 void WebView::SetDefaultTextEncodingName( const std::string& defaultTextEncodingName )
635 {
636   if( mWebEngine )
637   {
638     mWebEngine.SetDefaultTextEncodingName( defaultTextEncodingName );
639   }
640 }
641
642 int WebView::GetDefaultFontSize() const
643 {
644   return mWebEngine ? mWebEngine.GetDefaultFontSize() : 0;
645 }
646
647 void WebView::SetDefaultFontSize( int defaultFontSize )
648 {
649   if( mWebEngine )
650   {
651     mWebEngine.SetDefaultFontSize( defaultFontSize );
652   }
653 }
654
655 #undef GET_ENUM_STRING
656 #undef GET_ENUM_VALUE
657
658 } // namespace Internal
659
660 } // namespace Toolkit
661
662 } // namespace Dali