2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "toolkit-timer.h"
20 #include <dali/devel-api/adaptor-framework/web-engine.h>
21 #include <dali/devel-api/adaptor-framework/web-engine-back-forward-list.h>
22 #include <dali/devel-api/adaptor-framework/web-engine-back-forward-list-item.h>
23 #include <dali/devel-api/adaptor-framework/web-engine-context.h>
24 #include <dali/devel-api/adaptor-framework/web-engine-cookie-manager.h>
25 #include <dali/devel-api/adaptor-framework/web-engine-settings.h>
26 #include <dali/public-api/adaptor-framework/native-image-source.h>
27 #include <dali/public-api/images/pixel-data.h>
28 #include <dali/public-api/object/any.h>
29 #include <dali/public-api/object/base-object.h>
30 #include <toolkit-application.h>
46 // Generally only one WebEngine instance exists.
47 // If > 1, a new web engine has been created by CreateWindowSignal.
48 static WebEngine* gInstance = 0;
49 static int gInstanceCount = 0;
54 bool OnEvaluteJavaScript();
55 bool OnJavaScriptAlert();
56 bool OnJavaScriptConfirm();
57 bool OnJavaScriptPrompt();
59 bool OnClearHistory();
61 static void ConnectToGlobalSignal( bool ( *func )() )
63 Dali::Timer timer = Dali::Timer::New( 0 );
64 timer.TickSignal().Connect( func );
67 static void DisconnectFromGlobalSignal( bool ( *func )() )
69 Dali::Timer timer = Dali::Timer::New( 0 );
70 timer.TickSignal().Disconnect( func );
72 } // namespace anonymous
74 class MockWebEngineContext : public Dali::WebEngineContext
77 MockWebEngineContext()
78 : mockModel( Dali::WebEngineContext::CacheModel::DOCUMENT_VIEWER )
82 Dali::WebEngineContext::CacheModel GetCacheModel() const override
87 void SetCacheModel( Dali::WebEngineContext::CacheModel cacheModel ) override
89 mockModel = cacheModel;
92 void SetProxyUri( const std::string& uri ) override
96 void SetDefaultProxyAuth( const std::string& username, const std::string& password ) override
100 void SetCertificateFilePath( const std::string& certificatePath ) override
104 void DeleteWebDatabase() override
108 void DeleteWebStorage() override
112 void DeleteLocalFileSystem() override
116 void DisableCache( bool cacheDisabled ) override
120 void ClearCache() override
125 Dali::WebEngineContext::CacheModel mockModel;
128 class MockWebEngineCookieManager : public Dali::WebEngineCookieManager
131 MockWebEngineCookieManager()
132 : mockCookieAcceptPolicy( Dali::WebEngineCookieManager::CookieAcceptPolicy::NO_THIRD_PARTY )
136 void SetCookieAcceptPolicy( Dali::WebEngineCookieManager::CookieAcceptPolicy policy ) override
138 mockCookieAcceptPolicy = policy;
141 Dali::WebEngineCookieManager::CookieAcceptPolicy GetCookieAcceptPolicy() const override
143 return mockCookieAcceptPolicy;
146 void ClearCookies() override
150 void SetPersistentStorage( const std::string& path, Dali::WebEngineCookieManager::CookiePersistentStorage storage ) override
155 Dali::WebEngineCookieManager::CookieAcceptPolicy mockCookieAcceptPolicy;
158 class MockWebEngineBackForwardListItem : public Dali::WebEngineBackForwardListItem
161 MockWebEngineBackForwardListItem()
162 : mockUrl( "http://url" ),
163 mockTitle( "title" ),
164 mockOriginalUrl( "http://originalurl" )
168 std::string GetUrl() const override
173 std::string GetTitle() const override
178 std::string GetOriginalUrl() const override
180 return mockOriginalUrl;
185 std::string mockTitle;
186 std::string mockOriginalUrl;
189 class MockWebEngineBackForwardList : public Dali::WebEngineBackForwardList
192 MockWebEngineBackForwardList( )
194 pMockItem( &mockItem )
198 Dali::WebEngineBackForwardListItem& GetCurrentItem() const override
203 Dali::WebEngineBackForwardListItem& GetItemAtIndex( uint32_t index ) const override
208 uint32_t GetItemCount() const override
214 MockWebEngineBackForwardListItem mockItem;
215 WebEngineBackForwardListItem* pMockItem;
218 class MockWebEngineSettings : public WebEngineSettings
221 MockWebEngineSettings()
222 : mockDefaultFontSize( 16 ),
223 mockJavaScriptEnabled( true ),
224 mockImageLoadedAutomatically( true ),
225 mockDefaultTextEncodingName()
229 uint32_t GetDefaultFontSize() const override
231 return mockDefaultFontSize;
234 void SetDefaultFontSize( uint32_t size ) override
236 mockDefaultFontSize = size;
239 bool IsJavaScriptEnabled() const override
241 return mockJavaScriptEnabled;
244 void EnableJavaScript( bool enabled ) override
246 mockJavaScriptEnabled = enabled;
249 bool AreImagesLoadedAutomatically() const override
251 return mockImageLoadedAutomatically;
254 void AllowImagesLoadAutomatically( bool automatic ) override
256 mockImageLoadedAutomatically = automatic;
259 std::string GetDefaultTextEncodingName() const override
261 return mockDefaultTextEncodingName;
264 void SetDefaultTextEncodingName( const std::string& defaultTextEncodingName ) override
266 mockDefaultTextEncodingName = defaultTextEncodingName;
269 void AllowMixedContents( bool allowed ) override
273 void EnableSpatialNavigation( bool enabled ) override
277 void EnableWebSecurity( bool enabled ) override
281 void AllowFileAccessFromExternalUrl( bool allowed ) override
285 void AllowScriptsOpenWindows( bool allowed ) override
290 int mockDefaultFontSize;
291 bool mockJavaScriptEnabled;
292 bool mockImageLoadedAutomatically;
293 std::string mockDefaultTextEncodingName;
296 class WebEngine: public Dali::BaseObject
300 using JavaScriptEvaluatedResultCallback = std::function<void(const std::string&)>;
301 using JavaScriptAlertCallback = std::function<bool(const std::string&)>;
302 using JavaScriptConfirmCallback = std::function<bool(const std::string&)>;
303 using JavaScriptPromptCallback = std::function<bool(const std::string&, const std::string&)>;
307 , mCurrentPlusOnePos( 0 )
309 , mEvaluating( false )
310 , mScrollPosition( 0, 0 )
311 , mScrollSize( 500, 500 )
312 , mContentSize( 500, 500 )
315 if ( gInstanceCount == 1 ) // only first web engine need be saved.
320 mockWebEngineSettings = new MockWebEngineSettings();
321 mockWebEngineContext = new MockWebEngineContext();
322 mockWebEngineCookieManager = new MockWebEngineCookieManager();
323 mockWebEngineBackForwardList = new MockWebEngineBackForwardList();
329 if( !gInstanceCount )
334 delete mockWebEngineSettings;
335 delete mockWebEngineContext;
336 delete mockWebEngineCookieManager;
337 delete mockWebEngineBackForwardList;
340 Dali::WebEngineSettings& GetSettings() const
342 return *mockWebEngineSettings;
345 Dali::WebEngineContext& GetContext() const
347 return *mockWebEngineContext;
350 Dali::WebEngineCookieManager& GetCookieManager() const
352 return *mockWebEngineCookieManager;
355 Dali::WebEngineBackForwardList& GetBackForwardList() const
357 return *mockWebEngineBackForwardList;
360 void LoadUrl( const std::string& url )
363 ConnectToGlobalSignal( &OnLoadUrl );
366 const std::string& GetUrl() const
371 std::string GetTitle() const
373 return std::string("title");
376 Dali::PixelData GetFavicon() const
378 uint8_t* faviconData = new uint8_t[ 16 ];
380 faviconData[ 0 ] = 0xff;
381 faviconData[ 1 ] = 0x00;
382 faviconData[ 2 ] = 0x00;
383 faviconData[ 3 ] = 0xff;
384 faviconData[ 4 ] = 0xff;
385 faviconData[ 5 ] = 0x00;
386 faviconData[ 6 ] = 0x00;
387 faviconData[ 7 ] = 0xff;
388 faviconData[ 8 ] = 0xff;
389 faviconData[ 9 ] = 0x00;
390 faviconData[ 10 ] = 0x00;
391 faviconData[ 11 ] = 0xff;
392 faviconData[ 12 ] = 0xff;
393 faviconData[ 13 ] = 0x00;
394 faviconData[ 14 ] = 0x00;
395 faviconData[ 15 ] = 0xff;
397 return Dali::PixelData::New( faviconData, 16, 2, 2,
398 Dali::Pixel::Format::RGBA8888,
399 Dali::PixelData::ReleaseFunction::DELETE_ARRAY );
402 bool CanGoForward() const
404 return mHistory.size() > mCurrentPlusOnePos;
409 ConnectToGlobalSignal( &OnGoForward );
412 bool CanGoBack() const
414 return mCurrentPlusOnePos > 1;
419 ConnectToGlobalSignal( &OnGoBack );
422 void EvaluateJavaScript( const std::string& script, std::function< void( const std::string& ) > resultHandler )
428 ConnectToGlobalSignal( &OnEvaluteJavaScript );
430 mResultCallbacks.push_back( resultHandler );
434 void RegisterJavaScriptAlertCallback( Dali::WebEnginePlugin::JavaScriptAlertCallback callback )
438 ConnectToGlobalSignal( &OnJavaScriptAlert );
439 mJavaScriptAlertCallback = callback;
443 void RegisterJavaScriptConfirmCallback( Dali::WebEnginePlugin::JavaScriptConfirmCallback callback )
447 ConnectToGlobalSignal( &OnJavaScriptConfirm );
448 mJavaScriptConfirmCallback = callback;
452 void RegisterJavaScriptPromptCallback( Dali::WebEnginePlugin::JavaScriptPromptCallback callback )
456 ConnectToGlobalSignal( &OnJavaScriptPrompt );
457 mJavaScriptPromptCallback = callback;
463 ConnectToGlobalSignal( &OnClearHistory );
466 const std::string& GetUserAgent() const
471 void SetUserAgent( const std::string& userAgent )
473 mUserAgent = userAgent;
476 void ScrollBy( int dx, int dy )
478 mScrollPosition += Dali::Vector2( dx, dy );
479 if ( mScrollPosition.y + mScrollSize.height > mContentSize.height )
481 ConnectToGlobalSignal( &OnScrollEdge );
485 void SetScrollPosition( int x, int y )
487 mScrollPosition.x = x;
488 mScrollPosition.y = y;
491 Dali::Vector2 GetScrollPosition() const
493 return mScrollPosition;
496 Dali::Vector2 GetScrollSize() const
501 Dali::Vector2 GetContentSize() const
506 Dali::WebEnginePlugin::WebEnginePageLoadSignalType& PageLoadStartedSignal()
508 return mPageLoadStartedSignal;
511 Dali::WebEnginePlugin::WebEnginePageLoadSignalType& PageLoadInProgressSignal()
513 return mPageLoadInProgressSignal;
516 Dali::WebEnginePlugin::WebEnginePageLoadSignalType& PageLoadFinishedSignal()
518 return mPageLoadFinishedSignal;
521 Dali::WebEnginePlugin::WebEnginePageLoadErrorSignalType& PageLoadErrorSignal()
523 return mPageLoadErrorSignal;
526 Dali::WebEnginePlugin::WebEngineScrollEdgeReachedSignalType& ScrollEdgeReachedSignal()
528 return mScrollEdgeReachedSignal;
531 Dali::WebEnginePlugin::WebEngineUrlChangedSignalType& UrlChangedSignal()
533 return mUrlChangedSignal;
537 std::vector< std::string > mHistory;
538 size_t mCurrentPlusOnePos;
539 std::string mUserAgent;
540 Dali::WebEnginePlugin::WebEnginePageLoadSignalType mPageLoadStartedSignal;
541 Dali::WebEnginePlugin::WebEnginePageLoadSignalType mPageLoadInProgressSignal;
542 Dali::WebEnginePlugin::WebEnginePageLoadSignalType mPageLoadFinishedSignal;
543 Dali::WebEnginePlugin::WebEnginePageLoadErrorSignalType mPageLoadErrorSignal;
544 std::vector<JavaScriptEvaluatedResultCallback> mResultCallbacks;
547 Dali::WebEnginePlugin::WebEngineScrollEdgeReachedSignalType mScrollEdgeReachedSignal;
548 Dali::Vector2 mScrollPosition;
549 Dali::Vector2 mScrollSize;
550 Dali::Vector2 mContentSize;
551 WebEngineBackForwardList* mockWebEngineBackForwardList;
552 WebEngineContext* mockWebEngineContext;
553 WebEngineCookieManager* mockWebEngineCookieManager;
554 WebEngineSettings* mockWebEngineSettings;
555 Dali::WebEnginePlugin::WebEngineUrlChangedSignalType mUrlChangedSignal;
557 JavaScriptAlertCallback mJavaScriptAlertCallback;
558 JavaScriptConfirmCallback mJavaScriptConfirmCallback;
559 JavaScriptPromptCallback mJavaScriptPromptCallback;
568 DisconnectFromGlobalSignal( &OnGoBack );
570 if( gInstance && gInstance->CanGoBack() )
572 gInstance->mCurrentPlusOnePos--;
579 DisconnectFromGlobalSignal( &OnGoForward );
581 if( gInstance && gInstance->CanGoForward() )
583 gInstance->mCurrentPlusOnePos++;
590 DisconnectFromGlobalSignal( &OnLoadUrl );
594 if( gInstance->mHistory.size() > gInstance->mCurrentPlusOnePos )
596 gInstance->mHistory.erase( gInstance->mHistory.begin() + gInstance->mCurrentPlusOnePos, gInstance->mHistory.end() );
598 gInstance->mHistory.push_back( gInstance->mUrl );
599 gInstance->mCurrentPlusOnePos++;
600 gInstance->mPageLoadStartedSignal.Emit( gInstance->mUrl );
601 gInstance->mPageLoadInProgressSignal.Emit( gInstance->mUrl );
602 gInstance->mPageLoadFinishedSignal.Emit( gInstance->mUrl );
603 gInstance->mUrlChangedSignal.Emit( "http://new-test" );
610 DisconnectFromGlobalSignal( &OnScrollEdge );
614 gInstance->mScrollEdgeReachedSignal.Emit( Dali::WebEnginePlugin::ScrollEdge::BOTTOM );
620 bool OnEvaluteJavaScript()
622 DisconnectFromGlobalSignal( &OnEvaluteJavaScript );
626 for( auto& func : gInstance->mResultCallbacks )
630 gInstance->mResultCallbacks.clear();
635 bool OnJavaScriptAlert()
637 DisconnectFromGlobalSignal( &OnJavaScriptAlert );
640 gInstance->mJavaScriptAlertCallback( "this is an alert popup." );
645 bool OnJavaScriptConfirm()
647 DisconnectFromGlobalSignal( &OnJavaScriptConfirm );
650 gInstance->mJavaScriptConfirmCallback( "this is a confirm popup." );
655 bool OnJavaScriptPrompt()
657 DisconnectFromGlobalSignal( &OnJavaScriptPrompt );
660 gInstance->mJavaScriptPromptCallback( "this is a prompt pompt.", "" );
665 bool OnClearHistory()
667 DisconnectFromGlobalSignal( &OnClearHistory );
669 if( gInstance && gInstance->mCurrentPlusOnePos )
671 std::string url = gInstance->mHistory[ gInstance->mCurrentPlusOnePos - 1 ];
672 std::vector< std::string >().swap( gInstance->mHistory );
673 gInstance->mHistory.push_back( url );
674 gInstance->mCurrentPlusOnePos = 1;
681 inline WebEngine& GetImplementation( Dali::WebEngine& webEngine )
683 DALI_ASSERT_ALWAYS( webEngine && "WebEngine handle is empty." );
684 BaseObject& handle = webEngine.GetBaseObject();
685 return static_cast< Internal::Adaptor::WebEngine& >( handle );
688 inline const WebEngine& GetImplementation( const Dali::WebEngine& webEngine )
690 DALI_ASSERT_ALWAYS( webEngine && "WebEngine handle is empty." );
691 const BaseObject& handle = webEngine.GetBaseObject();
692 return static_cast< const Internal::Adaptor::WebEngine& >( handle );
695 } // namespace Adaptor
697 } // namespace Internal
699 // Dali::WebEngine Implementation
700 WebEngine::WebEngine()
704 WebEngine::WebEngine( Internal::Adaptor::WebEngine* internal )
705 : BaseHandle( internal )
709 WebEngine::~WebEngine()
713 WebEngine WebEngine::New()
715 Internal::Adaptor::WebEngine* baseObject = new Internal::Adaptor::WebEngine();
717 return WebEngine( baseObject );
720 WebEngine::WebEngine( const WebEngine& WebEngine )
721 : BaseHandle( WebEngine )
725 WebEngine& WebEngine::operator=( const WebEngine& webEngine )
727 BaseHandle::operator=( webEngine );
731 WebEngine WebEngine::DownCast( BaseHandle handle )
733 return WebEngine( dynamic_cast< Internal::Adaptor::WebEngine* >( handle.GetObjectPtr() ) );
736 void WebEngine::Create( int width, int height, const std::string& locale, const std::string& timezoneId )
740 void WebEngine::Create( int width, int height, int argc, char** argv )
744 void WebEngine::Destroy()
748 WebEngineSettings& WebEngine::GetSettings() const
750 return Internal::Adaptor::GetImplementation( *this ).GetSettings();
753 WebEngineContext& WebEngine::GetContext() const
755 return Internal::Adaptor::GetImplementation( *this ).GetContext();
758 WebEngineCookieManager& WebEngine::GetCookieManager() const
760 return Internal::Adaptor::GetImplementation( *this ).GetCookieManager();
763 WebEngineBackForwardList& WebEngine::GetBackForwardList() const
765 return Internal::Adaptor::GetImplementation( *this ).GetBackForwardList();
768 void WebEngine::LoadUrl( const std::string& url )
770 return Internal::Adaptor::GetImplementation( *this ).LoadUrl( url );
773 std::string WebEngine::GetTitle() const
775 return Internal::Adaptor::GetImplementation( *this ).GetTitle();
778 Dali::PixelData WebEngine::GetFavicon() const
780 return Internal::Adaptor::GetImplementation( *this ).GetFavicon();
783 const std::string& WebEngine::GetUrl()
785 return Internal::Adaptor::GetImplementation( *this ).GetUrl();
788 NativeImageInterfacePtr WebEngine::GetNativeImageSource()
791 Dali::NativeImageSourcePtr sourcePtr = Dali::NativeImageSource::New( source );
795 void WebEngine::LoadHtmlString( const std::string& htmlString )
799 void WebEngine::Reload()
803 void WebEngine::StopLoading()
807 void WebEngine::Suspend()
811 void WebEngine::Resume()
815 bool WebEngine::CanGoForward()
817 return Internal::Adaptor::GetImplementation( *this ).CanGoForward();
820 void WebEngine::GoForward()
822 Internal::Adaptor::GetImplementation( *this ).GoForward();
825 bool WebEngine::CanGoBack()
827 return Internal::Adaptor::GetImplementation( *this ).CanGoBack();
830 void WebEngine::GoBack()
832 Internal::Adaptor::GetImplementation( *this ).GoBack();
835 void WebEngine::EvaluateJavaScript( const std::string& script, std::function< void( const std::string& ) > resultHandler )
837 Internal::Adaptor::GetImplementation( *this ).EvaluateJavaScript( script, resultHandler );
840 void WebEngine::AddJavaScriptMessageHandler( const std::string& exposedObjectName, std::function< void(const std::string&) > handler )
844 void WebEngine::RegisterJavaScriptAlertCallback( Dali::WebEnginePlugin::JavaScriptAlertCallback callback )
846 Internal::Adaptor::GetImplementation( *this ).RegisterJavaScriptAlertCallback( callback );
849 void WebEngine::JavaScriptAlertReply()
853 void WebEngine::RegisterJavaScriptConfirmCallback( Dali::WebEnginePlugin::JavaScriptConfirmCallback callback )
855 Internal::Adaptor::GetImplementation( *this ).RegisterJavaScriptConfirmCallback( callback );
858 void WebEngine::JavaScriptConfirmReply( bool confirmed )
862 void WebEngine::RegisterJavaScriptPromptCallback( Dali::WebEnginePlugin::JavaScriptPromptCallback callback )
864 Internal::Adaptor::GetImplementation( *this ).RegisterJavaScriptPromptCallback( callback );
867 void WebEngine::JavaScriptPromptReply( const std::string& result )
871 void WebEngine::ClearAllTilesResources()
875 void WebEngine::ClearHistory()
877 Internal::Adaptor::GetImplementation( *this ).ClearHistory();
880 const std::string& WebEngine::GetUserAgent() const
882 return Internal::Adaptor::GetImplementation( *this ).GetUserAgent();
885 void WebEngine::SetUserAgent( const std::string& userAgent )
887 Internal::Adaptor::GetImplementation( *this ).SetUserAgent( userAgent );
890 void WebEngine::ScrollBy( int dx, int dy )
892 Internal::Adaptor::GetImplementation( *this ).ScrollBy( dx, dy );
895 void WebEngine::SetScrollPosition( int x, int y )
897 Internal::Adaptor::GetImplementation( *this ).SetScrollPosition( x, y );
900 Dali::Vector2 WebEngine::GetScrollPosition() const
902 return Internal::Adaptor::GetImplementation( *this ).GetScrollPosition();
905 Dali::Vector2 WebEngine::GetScrollSize() const
907 return Internal::Adaptor::GetImplementation( *this ).GetScrollSize();
910 Dali::Vector2 WebEngine::GetContentSize() const
912 return Internal::Adaptor::GetImplementation( *this ).GetContentSize();
915 void WebEngine::SetSize( int width, int height )
919 bool WebEngine::SendTouchEvent( const TouchEvent& touch )
924 bool WebEngine::SendKeyEvent( const KeyEvent& event )
929 void WebEngine::SetFocus( bool focused )
933 void WebEngine::UpdateDisplayArea( Dali::Rect< int > displayArea )
937 void WebEngine::EnableVideoHole( bool enabled )
941 Dali::WebEnginePlugin::WebEnginePageLoadSignalType& WebEngine::PageLoadStartedSignal()
943 return Internal::Adaptor::GetImplementation( *this ).PageLoadStartedSignal();
946 Dali::WebEnginePlugin::WebEnginePageLoadSignalType& WebEngine::PageLoadInProgressSignal()
948 return Internal::Adaptor::GetImplementation( *this ).PageLoadInProgressSignal();
951 Dali::WebEnginePlugin::WebEnginePageLoadSignalType& WebEngine::PageLoadFinishedSignal()
953 return Internal::Adaptor::GetImplementation( *this ).PageLoadFinishedSignal();
956 Dali::WebEnginePlugin::WebEnginePageLoadErrorSignalType& WebEngine::PageLoadErrorSignal()
958 return Internal::Adaptor::GetImplementation( *this ).PageLoadErrorSignal();
961 Dali::WebEnginePlugin::WebEngineScrollEdgeReachedSignalType& WebEngine::ScrollEdgeReachedSignal()
963 return Internal::Adaptor::GetImplementation( *this ).ScrollEdgeReachedSignal();
966 Dali::WebEnginePlugin::WebEngineUrlChangedSignalType& WebEngine::UrlChangedSignal()
968 return Internal::Adaptor::GetImplementation( *this ).UrlChangedSignal();