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