aboutsummaryrefslogtreecommitdiff
path: root/mp/src/vgui2/chromehtml/chromewrapper.cpp
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /mp/src/vgui2/chromehtml/chromewrapper.cpp
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/vgui2/chromehtml/chromewrapper.cpp')
-rw-r--r--mp/src/vgui2/chromehtml/chromewrapper.cpp441
1 files changed, 441 insertions, 0 deletions
diff --git a/mp/src/vgui2/chromehtml/chromewrapper.cpp b/mp/src/vgui2/chromehtml/chromewrapper.cpp
new file mode 100644
index 00000000..179974f0
--- /dev/null
+++ b/mp/src/vgui2/chromehtml/chromewrapper.cpp
@@ -0,0 +1,441 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Creates a HTML control
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "winlite.h"
+#include "html_chrome.h"
+#include "tier1/interface.h"
+#include "reliabletimer.h"
+#include "htmlmanager.h"
+
+#include "html/htmlprotobuf.h"
+#include <html/ichromehtmlwrapper.h>
+
+//-----------------------------------------------------------------------------
+// Purpose: owner object that gets responses from the CEF thread and dispatches them
+//-----------------------------------------------------------------------------
+class CHTMLController : public IHTMLChromeController
+{
+public:
+ CHTMLController() { m_BrowserSerial = 0; m_nCefTargetFrameRate = 0; SetDefLessFunc( m_mapBrowserRequests ); SetDefLessFunc( m_mapBrowsers ); }
+ ~CHTMLController() {}
+
+ bool Init( const char *pchHTMLCacheDir, const char *pchCookiePath );
+ void Shutdown();
+
+ void SetWebCookie( const char *pchHostname, const char *pchKey, const char *pchValue, const char *pchPath, RTime32 nExpires );
+ void GetWebCookiesForURL( CUtlString *pstrValue, const char *pchURL, const char *pchName );
+ void SetClientBuildID( uint64 ulBuildID );
+
+ bool BHasPendingMessages();
+
+ void CreateBrowser( IHTMLResponses *pBrowser, bool bPopupWindow, const char *pchUserAgentIdentifier );
+ void RemoveBrowser( IHTMLResponses *pBrowser );
+ bool RunFrame();
+
+ void WakeThread() { AccessHTMLWrapper().WakeThread(); }
+ HTMLCommandBuffer_t *GetFreeCommandBuffer( EHTMLCommands eCmd, int iBrowser ) { return AccessHTMLWrapper().GetFreeCommandBuffer( eCmd, iBrowser ); }
+ void PushCommand( HTMLCommandBuffer_t *pCmd ) { AccessHTMLWrapper().PushCommand( pCmd ); }
+
+
+ bool GetMainThreadCommand( HTMLCommandBuffer_t **pCmd ) { return AccessHTMLWrapper().GetMainThreadCommand( pCmd ); }
+ void ReleaseCommandBuffer( HTMLCommandBuffer_t *pCmd ) { AccessHTMLWrapper().ReleaseCommandBuffer( pCmd ); }
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, const char *pchName );
+ bool ChromePrepareForValidate();
+ bool ChromeResumeFromValidate();
+#endif
+
+ void SetCefThreadTargetFrameRate( uint32 nFPS );
+
+private:
+ // keeps track of outstanding browser create requests
+ CUtlMap< uint32, IHTMLResponses *, int > m_mapBrowserRequests;
+ // the next unique identifier to use when doing a browser create
+ uint32 m_BrowserSerial;
+ // the map of browser handles to our html panel objects, used for cef thread command dispatching
+ CUtlMap< uint32, IHTMLResponses *, int > m_mapBrowsers;
+
+ int m_nCefTargetFrameRate;
+};
+
+
+static CHTMLController s_HTMLController;
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CHTMLController, IHTMLChromeController, CHROMEHTML_CONTROLLER_INTERFACE_VERSION, s_HTMLController );
+
+
+//-----------------------------------------------------------------------------
+// Purpose: request the cef thread to make a new browser
+//-----------------------------------------------------------------------------
+void CHTMLController::CreateBrowser( IHTMLResponses *pBrowser, bool bPopupWindow, const char *pchUserAgentIdentifier )
+{
+ m_BrowserSerial++;
+ m_mapBrowserRequests.Insert( m_BrowserSerial, pBrowser );
+
+ CHTMLProtoBufMsg<CMsgBrowserCreate> cmd( eHTMLCommands_BrowserCreate );
+ cmd.Body().set_request_id( m_BrowserSerial );
+ cmd.Body().set_popup( bPopupWindow );
+ cmd.Body().set_useragent( pchUserAgentIdentifier );
+ HTMLCommandBuffer_t *pBuf = AccessHTMLWrapper().GetFreeCommandBuffer( eHTMLCommands_BrowserCreate, -1 );
+ cmd.SerializeCrossProc( &pBuf->m_Buffer );
+ AccessHTMLWrapper().PushCommand( pBuf );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: delete a browser we have
+//-----------------------------------------------------------------------------
+void CHTMLController::RemoveBrowser( IHTMLResponses *pBrowser )
+{
+
+ // pull ourselves from the browser handle list as we are doing away
+ FOR_EACH_MAP_FAST( m_mapBrowsers, i)
+ {
+ if ( m_mapBrowsers[i] == pBrowser )
+ {
+ // tell the cef thread this browser is going away
+ CHTMLProtoBufMsg<CMsgBrowserRemove> cmd( eHTMLCommands_BrowserRemove );
+ cmd.Body().set_browser_handle( pBrowser->BrowserGetIndex() );
+ HTMLCommandBuffer_t *pBuf = AccessHTMLWrapper().GetFreeCommandBuffer( eHTMLCommands_BrowserRemove, pBrowser->BrowserGetIndex() );
+ cmd.SerializeCrossProc( &pBuf->m_Buffer );
+ AccessHTMLWrapper().PushCommand( pBuf );
+
+ // now kill it
+ m_mapBrowsers.RemoveAt( i );
+ }
+ }
+
+ // also remove us from pending list if in it
+ FOR_EACH_MAP_FAST( m_mapBrowserRequests, i)
+ {
+ if ( m_mapBrowserRequests[i] == pBrowser )
+ m_mapBrowserRequests.RemoveAt( i );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: turn on the cef engine
+//-----------------------------------------------------------------------------
+bool CHTMLController::Init( const char *pchHTMLCacheDir, const char *pchCookiePath )
+{
+#if !defined(WIN64) && !defined(STATIC_TIER0)
+ ChromeInit( pchHTMLCacheDir, pchCookiePath );
+#endif
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: shutdown chrome
+//-----------------------------------------------------------------------------
+void CHTMLController::Shutdown()
+{
+#if !defined(WIN64) && !defined(STATIC_TIER0)
+ ChromeShutdown();
+#endif
+}
+
+
+
+// helper macro to dispatch messages from the cef thread
+#define HTML_MSG_FUNC( eHTMLCommand, bodyType, commandFunc ) \
+ case eHTMLCommand: \
+{ \
+ CHTMLProtoBufMsg< bodyType > cmd( pCmd->m_eCmd ); \
+ if ( !cmd.BDeserializeCrossProc( &pCmd->m_Buffer ) ) \
+{ \
+ bError = true; \
+} \
+ else \
+{ \
+ int idx = m_mapBrowsers.Find( cmd.BodyConst().browser_handle() ); \
+ if ( idx != m_mapBrowsers.InvalidIndex() ) \
+{ \
+ if ( m_mapBrowsers[idx] ) \
+ m_mapBrowsers[idx]->commandFunc( &cmd.BodyConst() ); \
+} \
+} \
+} \
+ break; \
+
+
+//-----------------------------------------------------------------------------
+// Purpose: process any ipc responses we have pending
+//-----------------------------------------------------------------------------
+bool CHTMLController::RunFrame()
+{
+ VPROF_BUDGET( "CHTMLController::RunFrame", VPROF_BUDGETGROUP_TENFOOT );
+ HTMLCommandBuffer_t *pCmd;
+ bool bError = false;
+ bool bDidwork = false;
+
+ // Paint messages are dispatched last to avoid doing excessive work on
+ // the main thread when two paint messages have stacked up in the queue.
+ // This could be greatly optimized by doing atomic buffer swaps instead
+ // of pushing the paint updates through a queue, but this helps for now.
+ // -henryg
+ CUtlVector< HTMLCommandBuffer_t * > vecDeferredPaint;
+
+ while( GetMainThreadCommand( &pCmd ) )
+ {
+ bool bRelease = true;
+ bDidwork = true;
+ //Msg( "Got response %d\n", pCmd->m_eCmd );
+ switch( pCmd->m_eCmd )
+ {
+ default:
+ break;
+ case eHTMLCommands_BrowserCreateResponse:
+ {
+ CHTMLProtoBufMsg< CMsgBrowserCreateResponse > cmd( pCmd->m_eCmd );
+ if ( !cmd.BDeserializeCrossProc( &pCmd->m_Buffer ) )
+ {
+ bError = true;
+ }
+ else
+ {
+ int idx = m_mapBrowserRequests.Find( cmd.BodyConst().request_id() );
+ if ( idx != m_mapBrowserRequests.InvalidIndex() )
+ {
+ m_mapBrowsers.Insert( cmd.BodyConst().browser_handle(), m_mapBrowserRequests[idx] );
+ m_mapBrowserRequests[idx]->BrowserSetIndex( cmd.BodyConst().browser_handle() );
+ m_mapBrowserRequests.RemoveAt( idx );
+ }
+ }
+ }
+ break;
+ case eHTMLCommands_NeedsPaint:
+ {
+ bRelease = false;
+ vecDeferredPaint.AddToTail( pCmd );
+ }
+ break;
+
+ HTML_MSG_FUNC( eHTMLCommands_BrowserReady, CMsgBrowserReady, BrowserReady );
+ HTML_MSG_FUNC( eHTMLCommands_StartRequest, CMsgStartRequest, BrowserStartRequest );
+ HTML_MSG_FUNC( eHTMLCommands_URLChanged, CMsgURLChanged, BrowserURLChanged );
+ HTML_MSG_FUNC( eHTMLCommands_FinishedRequest, CMsgFinishedRequest, BrowserFinishedRequest );
+ HTML_MSG_FUNC( eHTMLCommands_ShowPopup, CMsgShowPopup, BrowserShowPopup );
+ HTML_MSG_FUNC( eHTMLCommands_HidePopup, CMsgHidePopup, BrowserHidePopup );
+ HTML_MSG_FUNC( eHTMLCommands_OpenNewTab, CMsgOpenNewTab, BrowserOpenNewTab );
+ HTML_MSG_FUNC( eHTMLCommands_PopupHTMLWindow, CMsgPopupHTMLWindow, BrowserPopupHTMLWindow );
+ HTML_MSG_FUNC( eHTMLCommands_SetHTMLTitle, CMsgSetHTMLTitle, BrowserSetHTMLTitle );
+ HTML_MSG_FUNC( eHTMLCommands_LoadingResource, CMsgLoadingResource, BrowserLoadingResource );
+ HTML_MSG_FUNC( eHTMLCommands_StatusText, CMsgStatusText, BrowserStatusText );
+ HTML_MSG_FUNC( eHTMLCommands_SetCursor, CMsgSetCursor, BrowserSetCursor );
+ HTML_MSG_FUNC( eHTMLCommands_FileLoadDialog, CMsgFileLoadDialog, BrowserFileLoadDialog );
+ HTML_MSG_FUNC( eHTMLCommands_ShowToolTip, CMsgShowToolTip, BrowserShowToolTip );
+ HTML_MSG_FUNC( eHTMLCommands_UpdateToolTip, CMsgUpdateToolTip, BrowserUpdateToolTip );
+ HTML_MSG_FUNC( eHTMLCommands_HideToolTip, CMsgHideToolTip, BrowserHideToolTip );
+ HTML_MSG_FUNC( eHTMLCommands_SearchResults, CMsgSearchResults, BrowserSearchResults );
+ HTML_MSG_FUNC( eHTMLCommands_Close, CMsgClose, BrowserClose );
+ HTML_MSG_FUNC( eHTMLCommands_GetZoomResponse, CMsgGetZoomResponse, BrowserGetZoomResponse );
+ HTML_MSG_FUNC( eHTMLCommands_HorizontalScrollBarSizeResponse, CMsgHorizontalScrollBarSizeResponse, BrowserHorizontalScrollBarSizeResponse );
+ HTML_MSG_FUNC( eHTMLCommands_VerticalScrollBarSizeResponse, CMsgVerticalScrollBarSizeResponse, BrowserVerticalScrollBarSizeResponse );
+ HTML_MSG_FUNC( eHTMLCommands_LinkAtPositionResponse, CMsgLinkAtPositionResponse, BrowserLinkAtPositionResponse );
+ HTML_MSG_FUNC( eHTMLCommands_ZoomToElementAtPositionResponse, CMsgZoomToElementAtPositionResponse, BrowserZoomToElementAtPositionResponse );
+ HTML_MSG_FUNC( eHTMLCommands_JSAlert, CMsgJSAlert, BrowserJSAlert );
+ HTML_MSG_FUNC( eHTMLCommands_JSConfirm, CMsgJSConfirm, BrowserJSConfirm );
+ HTML_MSG_FUNC( eHTMLCommands_OpenSteamURL, CMsgOpenSteamURL, BrowserOpenSteamURL );
+ HTML_MSG_FUNC( eHTMLCommands_CanGoBackandForward, CMsgCanGoBackAndForward, BrowserCanGoBackandForward );
+ HTML_MSG_FUNC( eHTMLCommands_SizePopup, CMsgSizePopup, BrowserSizePopup );
+ HTML_MSG_FUNC( eHTMLCommands_ScaleToValueResponse, CMsgScalePageToValueResponse, BrowserScalePageToValueResponse );
+ HTML_MSG_FUNC( eHTMLCommands_RequestFullScreen, CMsgRequestFullScreen, BrowserRequestFullScreen );
+ HTML_MSG_FUNC( eHTMLCommands_ExitFullScreen, CMsgExitFullScreen, BrowserExitFullScreen );
+ HTML_MSG_FUNC( eHTMLCommands_GetCookiesForURLResponse, CMsgGetCookiesForURLResponse, BrowserGetCookiesForURLResponse );
+ HTML_MSG_FUNC( eHTMLCommands_NodeGotFocus, CMsgNodeHasFocus, BrowserNodeGotFocus );
+ HTML_MSG_FUNC( eHTMLCommands_SavePageToJPEGResponse, CMsgSavePageToJPEGResponse, BrowserSavePageToJPEGResponse );
+ HTML_MSG_FUNC( eHTMLCommands_GetFocusedNodeValueResponse, CMsgFocusedNodeTextResponse, BrowserFocusedNodeValueResponse );
+ }
+ if ( bError )
+ {
+ Warning( "Failed to parse command %d", pCmd->m_eCmd );
+ Assert( !"Bad Command" );
+ }
+ if ( bRelease )
+ {
+ ReleaseCommandBuffer( pCmd );
+ }
+ }
+
+ // Collapse deferred paints by browser ID and process them; the latest texture always
+ // has fully updated bits, we simply union its dirty rect with the skipped updates.
+ // Note: browser resizes always include a full dirty rect, we don't have to check here.
+ while ( vecDeferredPaint.Count() )
+ {
+ // Pull the last paint off the queue
+ pCmd = vecDeferredPaint[ vecDeferredPaint.Count() - 1 ];
+ int iBrowser = pCmd->m_iBrowser;
+ CHTMLProtoBufMsg<CMsgNeedsPaint> cmd( eHTMLCommands_NeedsPaint );
+ DbgVerify( cmd.BDeserializeCrossProc( &pCmd->m_Buffer ) );
+ ReleaseCommandBuffer( pCmd );
+ vecDeferredPaint.Remove( vecDeferredPaint.Count() - 1 );
+
+
+ CMsgNeedsPaint &body = cmd.Body();
+ CChromeUpdateRegion region;
+ if ( body.updatewide() && body.updatetall() )
+ {
+ region.MarkDirtyRect( body.updatex(), body.updatey(), body.updatex() + body.updatewide(), body.updatey() + body.updatetall() );
+ }
+ else
+ {
+ region.MarkAllDirty();
+ }
+
+ // Remove earlier paints for the same browser from the queue
+ for ( int i = vecDeferredPaint.Count() - 1; i >= 0; --i )
+ {
+ if ( vecDeferredPaint[i]->m_iBrowser == iBrowser )
+ {
+ // Decode
+ CHTMLProtoBufMsg<CMsgNeedsPaint> cmdMerge( eHTMLCommands_NeedsPaint );
+ DbgVerify( cmdMerge.BDeserializeCrossProc( &vecDeferredPaint[i]->m_Buffer ) );
+ CMsgNeedsPaint &bodyMerge = cmdMerge.Body();
+
+ if ( body.browser_handle() == bodyMerge.browser_handle() )
+ {
+ ReleaseCommandBuffer( vecDeferredPaint[i] );
+ vecDeferredPaint.Remove( i );
+
+ // Merge update region
+ if ( bodyMerge.updatewide() && bodyMerge.updatetall() )
+ {
+ region.MarkDirtyRect( bodyMerge.updatex(), bodyMerge.updatey(), bodyMerge.updatex() + bodyMerge.updatewide(), bodyMerge.updatey() + bodyMerge.updatetall() );
+ }
+ else
+ {
+ region.MarkAllDirty();
+ }
+
+ // Send response to the skipped paint update to free up the texture slot
+ pCmd = GetFreeCommandBuffer( eHTMLCommands_NeedsPaintResponse, bodyMerge.browser_handle() );
+ CHTMLProtoBufMsg<CMsgNeedsPaintResponse> cmdResponse( eHTMLCommands_NeedsPaintResponse );
+ cmdResponse.Body().set_browser_handle( bodyMerge.browser_handle() );
+ cmdResponse.Body().set_textureid( bodyMerge.textureid() );
+ cmdResponse.SerializeCrossProc( &pCmd->m_Buffer );
+ PushCommand( pCmd );
+ }
+ }
+ }
+
+ // Dispatch the merged update
+ int idxBrowser = m_mapBrowsers.Find( body.browser_handle() );
+ if ( idxBrowser != m_mapBrowsers.InvalidIndex() )
+ {
+ if ( m_mapBrowsers[idxBrowser] )
+ {
+ int updateWide = region.GetUpdateWide( body.wide() );
+ int updateTall = region.GetUpdateTall( body.tall() );
+ if ( updateWide != body.wide() || updateTall != body.tall() )
+ {
+ body.set_updatex( region.GetUpdateX( body.wide() ) );
+ body.set_updatey( region.GetUpdateY( body.tall() ) );
+ body.set_updatewide( updateWide );
+ body.set_updatetall( updateTall );
+ }
+ else
+ {
+ body.clear_updatex();
+ body.clear_updatey();
+ body.clear_updatewide();
+ body.clear_updatetall();
+ }
+ m_mapBrowsers[idxBrowser]->BrowserNeedsPaint( &body );
+ }
+ }
+ }
+
+ return bDidwork;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: set a cef cookie
+//-----------------------------------------------------------------------------
+void CHTMLController::SetWebCookie( const char *pchHostname, const char *pchKey, const char *pchValue, const char *pchPath, RTime32 nExpires )
+{
+#if !defined(WIN64) && !defined(STATIC_TIER0)
+ ChromeSetWebCookie( pchHostname, pchKey, pchValue, pchPath, nExpires );
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: set the buildid to report
+//-----------------------------------------------------------------------------
+void CHTMLController::SetClientBuildID( uint64 ulBuildID )
+{
+#if !defined(WIN64) && !defined(STATIC_TIER0)
+ ChromeSetClientBuildID( ulBuildID );
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: get the cef cookies for a url
+//-----------------------------------------------------------------------------
+void CHTMLController::GetWebCookiesForURL( CUtlString *pstrValue, const char *pchURL, const char *pchName )
+{
+#if !defined(WIN64) && !defined(STATIC_TIER0)
+ ChromeGetWebCookiesForURL( pstrValue, pchURL, pchName );
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: true if any pending html message in the queue
+//-----------------------------------------------------------------------------
+bool CHTMLController::BHasPendingMessages()
+{
+ return AccessHTMLWrapper().BHasPendingMessages();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: tell the cef thread the frame rate to use if it changes
+//-----------------------------------------------------------------------------
+void CHTMLController::SetCefThreadTargetFrameRate( uint32 nFPS )
+{
+ if ( nFPS != m_nCefTargetFrameRate )
+ {
+ m_nCefTargetFrameRate = nFPS;
+ CHTMLProtoBufMsg<CMsgSetTargetFrameRate> cmd( eHTMLCommands_SetTargetFrameRate );
+ cmd.Body().set_ntargetframerate( nFPS );
+ HTMLCommandBuffer_t *pBuf = AccessHTMLWrapper().GetFreeCommandBuffer( eHTMLCommands_SetTargetFrameRate, -1 );
+ cmd.SerializeCrossProc( &pBuf->m_Buffer );
+ AccessHTMLWrapper().PushCommand( pBuf );
+ }
+}
+
+#ifdef DBGFLAG_VALIDATE
+//-----------------------------------------------------------------------------
+// Purpose: validate mem
+//-----------------------------------------------------------------------------
+void CHTMLController::Validate( CValidator &validator, const char *pchName )
+{
+ ChromeValidate( validator, "ChromeValidate" );
+
+ validator.Push( "CHTMLController::ValidateStatics", NULL, pchName );
+ ValidateObj( m_mapBrowserRequests );
+ ValidateObj( m_mapBrowsers );
+ validator.Pop();
+}
+
+bool CHTMLController::ChromeResumeFromValidate()
+{
+ return ::ChromeResumeFromValidate();
+}
+
+bool CHTMLController::ChromePrepareForValidate()
+{
+ return ::ChromePrepareForValidate();
+}
+#endif // DBGFLAG_VALIDATE
+
+
+