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