2 * Copyright (c) 2020 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-frame.h>
26 #include <dali/devel-api/adaptor-framework/web-engine-policy-decision.h>
27 #include <dali/devel-api/adaptor-framework/web-engine-settings.h>
28 #include <dali/public-api/adaptor-framework/native-image-source.h>
29 #include <dali/public-api/images/pixel-data.h>
30 #include <dali/public-api/object/any.h>
31 #include <dali/public-api/object/base-object.h>
32 #include <toolkit-application.h>
48 // Generally only one WebEngine instance exists.
49 // If > 1, a new web engine has been created by NewWindowCreated callback.
50 static WebEngine* gInstance = nullptr;
51 static int gInstanceCount = 0;
56 bool OnEvaluteJavaScript();
57 bool OnClearHistory();
58 bool OnPlainTextReceived();
60 static void ConnectToGlobalSignal( bool (*func)() )
62 Dali::Timer timer = Dali::Timer::New( 0 );
63 timer.TickSignal().Connect( func );
66 static void DisconnectFromGlobalSignal( bool (*func)() )
68 Dali::Timer timer = Dali::Timer::New( 0 );
69 timer.TickSignal().Disconnect( func );
73 class MockWebEngineContext : public Dali::WebEngineContext
76 MockWebEngineContext()
77 : mockModel( Dali::WebEngineContext::CacheModel::DOCUMENT_VIEWER )
81 Dali::WebEngineContext::CacheModel GetCacheModel() const override
86 void SetCacheModel( Dali::WebEngineContext::CacheModel cacheModel ) override
88 mockModel = cacheModel;
91 void SetProxyUri( const std::string& uri ) override
95 void SetDefaultProxyAuth( const std::string& username, const std::string& password ) override
99 void SetCertificateFilePath( const std::string& certificatePath ) override
103 void DeleteWebDatabase() override
107 void DeleteWebStorage() override
111 void DeleteLocalFileSystem() override
115 void DisableCache( bool cacheDisabled ) override
119 void ClearCache() override
124 Dali::WebEngineContext::CacheModel mockModel;
127 class MockWebEngineCookieManager : public Dali::WebEngineCookieManager
130 MockWebEngineCookieManager()
131 : mockCookieAcceptPolicy( Dali::WebEngineCookieManager::CookieAcceptPolicy::NO_THIRD_PARTY )
135 void SetCookieAcceptPolicy( Dali::WebEngineCookieManager::CookieAcceptPolicy policy ) override
137 mockCookieAcceptPolicy = policy;
140 Dali::WebEngineCookieManager::CookieAcceptPolicy GetCookieAcceptPolicy() const override
142 return mockCookieAcceptPolicy;
145 void ClearCookies() override
149 void SetPersistentStorage( const std::string& path, Dali::WebEngineCookieManager::CookiePersistentStorage storage ) override
154 Dali::WebEngineCookieManager::CookieAcceptPolicy mockCookieAcceptPolicy;
157 class MockWebEngineBackForwardListItem : public Dali::WebEngineBackForwardListItem
160 MockWebEngineBackForwardListItem()
161 : mockUrl( "http://url" ),
162 mockTitle( "title" ),
163 mockOriginalUrl( "http://originalurl" )
167 std::string GetUrl() const override
172 std::string GetTitle() const override
177 std::string GetOriginalUrl() const override
179 return mockOriginalUrl;
184 std::string mockTitle;
185 std::string mockOriginalUrl;
188 class MockWebEngineBackForwardList : public Dali::WebEngineBackForwardList
191 MockWebEngineBackForwardList( )
193 pMockItem( &mockItem )
197 Dali::WebEngineBackForwardListItem& GetCurrentItem() const override
202 Dali::WebEngineBackForwardListItem& GetItemAtIndex( uint32_t index ) const override
207 uint32_t GetItemCount() const override
213 MockWebEngineBackForwardListItem mockItem;
214 WebEngineBackForwardListItem* pMockItem;
217 class MockWebEngineFrame : public Dali::WebEngineFrame
224 bool IsMainFrame() const override
230 class MockWebEnginePolicyDecision : public Dali::WebEnginePolicyDecision
233 MockWebEnginePolicyDecision()
237 std::string GetUrl() const override
239 return "http://test.html";
242 std::string GetCookie() const override
247 Dali::WebEnginePolicyDecision::DecisionType GetDecisionType() const
249 return Dali::WebEnginePolicyDecision::DecisionType::USE;
252 std::string GetResponseMime() const
257 int32_t GetResponseStatusCode() const
262 Dali::WebEnginePolicyDecision::NavigationType GetNavigationType() const
264 return Dali::WebEnginePolicyDecision::NavigationType::LINK_CLICKED;
267 Dali::WebEngineFrame& GetFrame() const
269 return *(Dali::WebEngineFrame*)(&mockWebFrame);
272 std::string GetScheme() const
293 MockWebEngineFrame mockWebFrame;
296 class MockWebEngineSettings : public WebEngineSettings
299 MockWebEngineSettings()
300 : mockDefaultFontSize( 16 ),
301 mockJavaScriptEnabled( true ),
302 mockImageLoadedAutomatically( true ),
303 mockDefaultTextEncodingName()
307 uint32_t GetDefaultFontSize() const override
309 return mockDefaultFontSize;
312 void SetDefaultFontSize( uint32_t size ) override
314 mockDefaultFontSize = size;
317 bool IsJavaScriptEnabled() const override
319 return mockJavaScriptEnabled;
322 void EnableJavaScript( bool enabled ) override
324 mockJavaScriptEnabled = enabled;
327 bool AreImagesLoadedAutomatically() const override
329 return mockImageLoadedAutomatically;
332 void AllowImagesLoadAutomatically( bool automatic ) override
334 mockImageLoadedAutomatically = automatic;
337 std::string GetDefaultTextEncodingName() const override
339 return mockDefaultTextEncodingName;
342 void SetDefaultTextEncodingName( const std::string& defaultTextEncodingName ) override
344 mockDefaultTextEncodingName = defaultTextEncodingName;
347 void AllowMixedContents( bool allowed ) override
351 void EnableSpatialNavigation( bool enabled ) override
355 void EnableWebSecurity( bool enabled ) override
359 void AllowFileAccessFromExternalUrl( bool allowed ) override
363 void AllowScriptsOpenWindows( bool allowed ) override
368 int mockDefaultFontSize;
369 bool mockJavaScriptEnabled;
370 bool mockImageLoadedAutomatically;
371 std::string mockDefaultTextEncodingName;
374 class WebEngine: public Dali::BaseObject
380 , mCurrentPlusOnePos( 0 )
382 , mEvaluating( false )
383 , mScrollPosition( 0, 0 )
384 , mScrollSize( 500, 500 )
385 , mContentSize( 500, 500 )
388 if (gInstanceCount == 1) // only first web engine need be saved.
393 mockWebEngineSettings = new MockWebEngineSettings();
394 mockWebEngineContext = new MockWebEngineContext();
395 mockWebEngineCookieManager = new MockWebEngineCookieManager();
396 mockWebEngineBackForwardList = new MockWebEngineBackForwardList();
407 delete mockWebEngineSettings;
408 delete mockWebEngineContext;
409 delete mockWebEngineCookieManager;
410 delete mockWebEngineBackForwardList;
413 Dali::WebEngineSettings& GetSettings() const
415 return *mockWebEngineSettings;
418 Dali::WebEngineContext& GetContext() const
420 return *mockWebEngineContext;
423 Dali::WebEngineCookieManager& GetCookieManager() const
425 return *mockWebEngineCookieManager;
428 Dali::WebEngineBackForwardList& GetBackForwardList() const
430 return *mockWebEngineBackForwardList;
433 Dali::WebEnginePlugin* GetPlugin() const
438 void LoadUrl( const std::string& url )
441 ConnectToGlobalSignal( &OnLoadUrl );
444 const std::string& GetUrl() const
449 std::string GetTitle() const
451 return std::string("title");
454 Dali::PixelData GetFavicon() const
456 uint8_t* faviconData = new uint8_t[ 16 ];
458 faviconData[ 0 ] = 0xff;
459 faviconData[ 1 ] = 0x00;
460 faviconData[ 2 ] = 0x00;
461 faviconData[ 3 ] = 0xff;
462 faviconData[ 4 ] = 0xff;
463 faviconData[ 5 ] = 0x00;
464 faviconData[ 6 ] = 0x00;
465 faviconData[ 7 ] = 0xff;
466 faviconData[ 8 ] = 0xff;
467 faviconData[ 9 ] = 0x00;
468 faviconData[ 10 ] = 0x00;
469 faviconData[ 11 ] = 0xff;
470 faviconData[ 12 ] = 0xff;
471 faviconData[ 13 ] = 0x00;
472 faviconData[ 14 ] = 0x00;
473 faviconData[ 15 ] = 0xff;
475 return Dali::PixelData::New( faviconData, 16, 2, 2,
476 Dali::Pixel::Format::RGBA8888,
477 Dali::PixelData::ReleaseFunction::DELETE_ARRAY );
480 bool CanGoForward() const
482 return mHistory.size() > mCurrentPlusOnePos;
487 ConnectToGlobalSignal( &OnGoForward );
490 bool CanGoBack() const
492 return mCurrentPlusOnePos > 1;
497 ConnectToGlobalSignal( &OnGoBack );
500 void EvaluateJavaScript( const std::string& script, Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback resultHandler )
506 ConnectToGlobalSignal( &OnEvaluteJavaScript );
508 mResultCallbacks.push_back( resultHandler );
514 ConnectToGlobalSignal( &OnClearHistory );
517 const std::string& GetUserAgent() const
522 void SetUserAgent( const std::string& userAgent )
524 mUserAgent = userAgent;
527 void ScrollBy( int dx, int dy )
529 mScrollPosition += Dali::Vector2( dx, dy );
530 if ( mScrollPosition.y + mScrollSize.height > mContentSize.height )
532 gInstance->mScrollEdgeReachedCallback( Dali::WebEnginePlugin::ScrollEdge::BOTTOM );
536 void SetScrollPosition( int x, int y )
538 mScrollPosition.x = x;
539 mScrollPosition.y = y;
542 void GetScrollPosition( int& x, int& y ) const
544 x = mScrollPosition.x;
545 y = mScrollPosition.y;
548 void GetScrollSize( int& w, int& h ) const
550 w = mScrollSize.width;
551 h = mScrollSize.height;
554 void GetContentSize( int& w, int& h ) const
556 w = mContentSize.width;
557 h = mContentSize.height;
560 void RegisterPageLoadStartedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
562 mPageLoadStartedCallback = callback;
565 void RegisterPageLoadFinishedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
567 mPageLoadFinishedCallback = callback;
570 void RegisterPageLoadErrorCallback(Dali::WebEnginePlugin::WebEnginePageLoadErrorCallback callback)
572 mPageLoadErrorCallback = callback;
575 void RegisterScrollEdgeReachedCallback(Dali::WebEnginePlugin::WebEngineScrollEdgeReachedCallback callback)
577 mScrollEdgeReachedCallback = callback;
580 void RegisterUrlChangedCallback(Dali::WebEnginePlugin::WebEngineUrlChangedCallback callback)
582 mUrlChangedCallback = callback;
585 void RegisterNavigationPolicyDecidedCallback(Dali::WebEnginePlugin::WebEngineNavigationPolicyDecidedCallback callback)
587 mNavigationPolicyDecisionCallback = callback;
590 void RegisterNewWindowCreatedCallback(Dali::WebEnginePlugin::WebEngineNewWindowCreatedCallback callback)
592 mNewWindowCreatedCallback = callback;
595 void GetPlainTextAsynchronously(Dali::WebEnginePlugin::PlainTextReceivedCallback callback)
599 ConnectToGlobalSignal(&OnPlainTextReceived);
600 mPlainTextReceivedCallback = callback;
605 std::vector< std::string > mHistory;
606 size_t mCurrentPlusOnePos;
607 std::string mUserAgent;
609 Dali::WebEnginePlugin::WebEnginePageLoadCallback mPageLoadStartedCallback;
610 Dali::WebEnginePlugin::WebEnginePageLoadCallback mPageLoadFinishedCallback;
611 Dali::WebEnginePlugin::WebEnginePageLoadErrorCallback mPageLoadErrorCallback;
612 Dali::WebEnginePlugin::WebEngineScrollEdgeReachedCallback mScrollEdgeReachedCallback;
613 Dali::WebEnginePlugin::WebEngineUrlChangedCallback mUrlChangedCallback;
614 Dali::WebEnginePlugin::WebEngineNavigationPolicyDecidedCallback mNavigationPolicyDecisionCallback;
615 Dali::WebEnginePlugin::WebEngineNewWindowCreatedCallback mNewWindowCreatedCallback;
617 std::vector<Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback> mResultCallbacks;
620 Dali::Vector2 mScrollPosition;
621 Dali::Vector2 mScrollSize;
622 Dali::Vector2 mContentSize;
623 WebEngineBackForwardList* mockWebEngineBackForwardList;
624 WebEngineContext* mockWebEngineContext;
625 WebEngineCookieManager* mockWebEngineCookieManager;
626 WebEngineSettings* mockWebEngineSettings;
627 Dali::WebEnginePlugin::PlainTextReceivedCallback mPlainTextReceivedCallback;
630 inline WebEngine& GetImplementation( Dali::WebEngine& webEngine )
632 DALI_ASSERT_ALWAYS( webEngine && "WebEngine handle is empty." );
633 BaseObject& handle = webEngine.GetBaseObject();
634 return static_cast< Internal::Adaptor::WebEngine& >( handle );
637 inline const WebEngine& GetImplementation( const Dali::WebEngine& webEngine )
639 DALI_ASSERT_ALWAYS( webEngine && "WebEngine handle is empty." );
640 const BaseObject& handle = webEngine.GetBaseObject();
641 return static_cast< const Internal::Adaptor::WebEngine& >( handle );
649 DisconnectFromGlobalSignal( &OnGoBack );
651 if( gInstance && gInstance->CanGoBack() )
653 gInstance->mCurrentPlusOnePos--;
660 DisconnectFromGlobalSignal( &OnGoForward );
662 if( gInstance && gInstance->CanGoForward() )
664 gInstance->mCurrentPlusOnePos++;
671 DisconnectFromGlobalSignal( &OnLoadUrl );
675 if( gInstance->mHistory.size() > gInstance->mCurrentPlusOnePos )
677 gInstance->mHistory.erase( gInstance->mHistory.begin() + gInstance->mCurrentPlusOnePos, gInstance->mHistory.end() );
679 gInstance->mHistory.push_back( gInstance->mUrl );
680 gInstance->mCurrentPlusOnePos++;
681 if (gInstance->mPageLoadStartedCallback)
683 gInstance->mPageLoadStartedCallback( gInstance->mUrl );
685 if (gInstance->mPageLoadFinishedCallback)
687 gInstance->mPageLoadFinishedCallback( gInstance->mUrl );
689 if (gInstance->mPageLoadErrorCallback)
691 gInstance->mPageLoadErrorCallback(gInstance->mUrl, WebView::LoadErrorCode::UNKNOWN);
693 if (gInstance->mUrlChangedCallback)
695 gInstance->mUrlChangedCallback("http://new-test");
697 if (gInstance->mNavigationPolicyDecisionCallback)
699 std::unique_ptr<Dali::WebEnginePolicyDecision> policyDecision(new MockWebEnginePolicyDecision());
700 gInstance->mNavigationPolicyDecisionCallback(std::move(policyDecision));
702 if (gInstance->mNewWindowCreatedCallback)
704 Dali::WebEnginePlugin* plugin = 0;
705 gInstance->mNewWindowCreatedCallback(plugin);
711 bool OnEvaluteJavaScript()
713 DisconnectFromGlobalSignal( &OnEvaluteJavaScript );
717 for( auto& func : gInstance->mResultCallbacks )
721 gInstance->mResultCallbacks.clear();
726 bool OnClearHistory()
728 DisconnectFromGlobalSignal( &OnClearHistory );
730 if( gInstance && gInstance->mCurrentPlusOnePos ) {
731 std::string url = gInstance->mHistory[ gInstance->mCurrentPlusOnePos - 1 ];
732 std::vector< std::string >().swap( gInstance->mHistory );
733 gInstance->mHistory.push_back( url );
734 gInstance->mCurrentPlusOnePos = 1;
739 bool OnPlainTextReceived()
741 DisconnectFromGlobalSignal(&OnPlainTextReceived);
744 std::string dummyResultText;
745 gInstance->mPlainTextReceivedCallback(dummyResultText);
752 } // namespace Adaptor
754 } // namespace Internal
757 // Dali::WebEngine Implementation
758 WebEngine::WebEngine()
762 WebEngine::WebEngine( Internal::Adaptor::WebEngine* internal )
763 : BaseHandle( internal )
767 WebEngine::~WebEngine()
771 WebEngine WebEngine::New()
773 Internal::Adaptor::WebEngine* baseObject = new Internal::Adaptor::WebEngine();
775 return WebEngine( baseObject );
778 WebEngine::WebEngine( const WebEngine& WebEngine )
779 : BaseHandle( WebEngine )
783 WebEngine& WebEngine::operator=( const WebEngine& webEngine )
785 BaseHandle::operator=( webEngine );
789 WebEngine WebEngine::DownCast( BaseHandle handle )
791 return WebEngine( dynamic_cast< Internal::Adaptor::WebEngine* >( handle.GetObjectPtr() ) );
794 void WebEngine::Create( int width, int height, const std::string& locale, const std::string& timezoneId )
798 void WebEngine::Create( int width, int height, int argc, char** argv )
802 void WebEngine::Destroy()
806 WebEngineSettings& WebEngine::GetSettings() const
808 return Internal::Adaptor::GetImplementation( *this ).GetSettings();
811 WebEngineContext& WebEngine::GetContext() const
813 return Internal::Adaptor::GetImplementation( *this ).GetContext();
816 WebEngineCookieManager& WebEngine::GetCookieManager() const
818 return Internal::Adaptor::GetImplementation( *this ).GetCookieManager();
821 WebEngineBackForwardList& WebEngine::GetBackForwardList() const
823 return Internal::Adaptor::GetImplementation( *this ).GetBackForwardList();
826 void WebEngine::LoadUrl( const std::string& url )
828 return Internal::Adaptor::GetImplementation( *this ).LoadUrl( url );
831 std::string WebEngine::GetTitle() const
833 return Internal::Adaptor::GetImplementation( *this ).GetTitle();
836 Dali::PixelData WebEngine::GetFavicon() const
838 return Internal::Adaptor::GetImplementation( *this ).GetFavicon();
841 const std::string& WebEngine::GetUrl()
843 return Internal::Adaptor::GetImplementation( *this ).GetUrl();
846 NativeImageInterfacePtr WebEngine::GetNativeImageSource()
849 Dali::NativeImageSourcePtr sourcePtr = Dali::NativeImageSource::New( source );
853 void WebEngine::LoadHtmlString( const std::string& htmlString )
857 void WebEngine::Reload()
861 void WebEngine::StopLoading()
865 void WebEngine::Suspend()
869 void WebEngine::Resume()
873 bool WebEngine::CanGoForward()
875 return Internal::Adaptor::GetImplementation( *this ).CanGoForward();
878 void WebEngine::GoForward()
880 Internal::Adaptor::GetImplementation( *this ).GoForward();
883 bool WebEngine::CanGoBack()
885 return Internal::Adaptor::GetImplementation( *this ).CanGoBack();
888 void WebEngine::GoBack()
890 Internal::Adaptor::GetImplementation( *this ).GoBack();
893 void WebEngine::EvaluateJavaScript( const std::string& script, Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback resultHandler )
895 Internal::Adaptor::GetImplementation( *this ).EvaluateJavaScript( script, resultHandler );
898 void WebEngine::AddJavaScriptMessageHandler( const std::string& exposedObjectName, Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback handler )
902 void WebEngine::ClearAllTilesResources()
906 void WebEngine::ClearHistory()
908 Internal::Adaptor::GetImplementation( *this ).ClearHistory();
911 const std::string& WebEngine::GetUserAgent() const
913 return Internal::Adaptor::GetImplementation( *this ).GetUserAgent();
916 void WebEngine::SetUserAgent( const std::string& userAgent )
918 Internal::Adaptor::GetImplementation( *this ).SetUserAgent( userAgent );
921 void WebEngine::ScrollBy( int dx, int dy )
923 Internal::Adaptor::GetImplementation( *this ).ScrollBy( dx, dy );
926 void WebEngine::SetScrollPosition( int x, int y )
928 Internal::Adaptor::GetImplementation( *this ).SetScrollPosition( x, y );
931 void WebEngine::GetScrollPosition( int& x, int& y ) const
933 Internal::Adaptor::GetImplementation( *this ).GetScrollPosition( x, y );
936 void WebEngine::GetScrollSize( int& w, int& h ) const
938 Internal::Adaptor::GetImplementation( *this ).GetScrollSize( w, h );
941 void WebEngine::GetContentSize( int& w, int& h ) const
943 Internal::Adaptor::GetImplementation( *this ).GetContentSize( w, h );
946 void WebEngine::SetSize( int width, int height )
950 bool WebEngine::SendTouchEvent( const TouchEvent& touch )
955 bool WebEngine::SendKeyEvent( const KeyEvent& event )
960 void WebEngine::SetFocus( bool focused )
964 void WebEngine::UpdateDisplayArea( Dali::Rect< int > displayArea )
968 void WebEngine::EnableVideoHole( bool enabled )
972 void WebEngine::RegisterPageLoadStartedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
974 Internal::Adaptor::GetImplementation( *this ).RegisterPageLoadStartedCallback(callback);
977 void WebEngine::RegisterPageLoadFinishedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
979 Internal::Adaptor::GetImplementation( *this ).RegisterPageLoadFinishedCallback(callback);
982 void WebEngine::RegisterPageLoadErrorCallback(Dali::WebEnginePlugin::WebEnginePageLoadErrorCallback callback)
984 Internal::Adaptor::GetImplementation( *this ).RegisterPageLoadErrorCallback(callback);
987 void WebEngine::RegisterScrollEdgeReachedCallback(Dali::WebEnginePlugin::WebEngineScrollEdgeReachedCallback callback)
989 Internal::Adaptor::GetImplementation(*this).RegisterScrollEdgeReachedCallback(callback);
992 void WebEngine::RegisterUrlChangedCallback(Dali::WebEnginePlugin::WebEngineUrlChangedCallback callback)
994 Internal::Adaptor::GetImplementation(*this).RegisterUrlChangedCallback(callback);
997 void WebEngine::RegisterNavigationPolicyDecidedCallback(Dali::WebEnginePlugin::WebEngineNavigationPolicyDecidedCallback callback)
999 Internal::Adaptor::GetImplementation(*this).RegisterNavigationPolicyDecidedCallback(callback);
1002 void WebEngine::RegisterNewWindowCreatedCallback(Dali::WebEnginePlugin::WebEngineNewWindowCreatedCallback callback)
1004 Internal::Adaptor::GetImplementation(*this).RegisterNewWindowCreatedCallback(callback);
1007 void WebEngine::GetPlainTextAsynchronously(Dali::WebEnginePlugin::PlainTextReceivedCallback callback)
1009 Internal::Adaptor::GetImplementation(*this).GetPlainTextAsynchronously(callback);
1012 } // namespace Dali;