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