Skip to content

Commit

Permalink
Added Lua-based Ajax handling functionality via
Browse files Browse the repository at this point in the history
setBrowserAjaxHandler / Browser.setAjaxHandler
Currently GET-only due to CEF limitations
  • Loading branch information
sbx320 committed Aug 12, 2015
1 parent bcdad0f commit 72147b4
Show file tree
Hide file tree
Showing 17 changed files with 389 additions and 11 deletions.
90 changes: 90 additions & 0 deletions MTA10/core/CAjaxResourceHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: core/AjaxResourceHandler.cpp
* PURPOSE: CEF Handler for Ajax Requests with delayed results
*
*****************************************************************************/

#include "StdInc.h"
#include "CWebCore.h"
#include "CWebView.h"
#include "CAjaxResourceHandler.h"

CAjaxResourceHandler::CAjaxResourceHandler ( std::vector<SString>& vecGet, std::vector<SString>& vecPost, const CefString& strMime)
: m_vecGetData(vecGet), m_vecPostData(vecPost), m_strMime(strMime)
{
}

std::vector<SString>& CAjaxResourceHandler::GetGetData ()
{
return m_vecGetData;
}

std::vector<SString>& CAjaxResourceHandler::GetPostData ()
{
return m_vecPostData;
}


void CAjaxResourceHandler::SetResponse ( const SString& data )
{
m_strResponse = data;
m_bHasData = true;
m_callback->Continue ();
}

// CefResourceHandler implementation
void CAjaxResourceHandler::Cancel ()
{
}

bool CAjaxResourceHandler::CanGetCookie ( const CefCookie& cookie )
{
return false;
}

bool CAjaxResourceHandler::CanSetCookie ( const CefCookie& cookie )
{
return false;
}

void CAjaxResourceHandler::GetResponseHeaders ( CefRefPtr< CefResponse > response, int64& response_length, CefString& redirectUrl )
{
response->SetStatus ( 200 );
response->SetStatusText ( "OK" );
response->SetMimeType ( m_strMime );
response_length = -1;
}

bool CAjaxResourceHandler::ProcessRequest ( CefRefPtr< CefRequest > request, CefRefPtr< CefCallback > callback )
{
// Since we have nothing to process yet, continue
callback->Continue ();
return true;
}


bool CAjaxResourceHandler::ReadResponse ( void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr< CefCallback > callback )
{
if ( m_bHasRead )
return false;

if ( !m_bHasData )
{
bytes_read = 0;
m_callback = callback;
callback->Continue ();
return true;
}

// +1 due to terminating \0
int copyBytes = min ( (uint)bytes_to_read, m_strResponse.length () +1 );
memcpy ( data_out, m_strResponse.c_str (), copyBytes );
((char*)data_out) [copyBytes] = '\0';
bytes_read = copyBytes;
m_bHasRead = true;

return true;
}
48 changes: 48 additions & 0 deletions MTA10/core/CAjaxResourceHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: core/AjaxResourceHandler.h
* PURPOSE: CEF Handler for Ajax Requests with delayed results
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/
#pragma once

#include <core/CAjaxResourceHandlerInterface.h>
#include <cef3/include/cef_resource_handler.h>
#include <SString.h>

class CWebView;

class CAjaxResourceHandler : public CefResourceHandler, public CAjaxResourceHandlerInterface
{
public:
CAjaxResourceHandler ( std::vector<SString>& vecGet, std::vector<SString>& vecPost, const CefString& mimeType);

virtual std::vector<SString>& GetGetData ();
virtual std::vector<SString>& GetPostData ();
virtual void SetResponse ( const SString& data );

// CefResourceHandler
virtual void Cancel () override;
virtual bool CanGetCookie ( const CefCookie& cookie ) override;
virtual bool CanSetCookie ( const CefCookie& cookie ) override;
virtual void GetResponseHeaders ( CefRefPtr< CefResponse > response, int64& response_length, CefString& redirectUrl ) override;
virtual bool ProcessRequest ( CefRefPtr< CefRequest > request, CefRefPtr< CefCallback > callback ) override;
virtual bool ReadResponse ( void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr< CefCallback > callback ) override;

IMPLEMENT_REFCOUNTING ( CAjaxResourceHandler );
DISALLOW_COPY_AND_ASSIGN ( CAjaxResourceHandler );

private:
//
CefRefPtr< CefCallback > m_callback;
std::vector<SString> m_vecGetData;
std::vector<SString> m_vecPostData;
SString m_strResponse;
CefString m_strMime;
bool m_bHasData = false;
bool m_bHasRead = false;
};
58 changes: 49 additions & 9 deletions MTA10/core/CWebCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "CWebCore.h"
#include "CWebView.h"
#include "CWebsiteRequests.h"
#include "CAjaxResourceHandler.h"
#include <cef3/include/cef_app.h>
#include <cef3/include/cef_browser.h>
#include <cef3/include/cef_sandbox_win.h>
Expand Down Expand Up @@ -797,23 +798,62 @@ CefRefPtr<CefResourceHandler> CCefApp::Create ( CefRefPtr<CefBrowser> browser, C

// Get full path
SString path = UTF16ToMbUTF8 ( urlParts.path.str ).substr ( 2 );
if ( !pWebView->GetFullPathFromLocal ( path ) )
return nullptr;

// Get mime type from extension
CefString mimeType;
size_t pos = path.find_last_of('.');
if (pos != std::string::npos)
size_t pos = path.find_last_of ( '.' );
if ( pos != std::string::npos )
mimeType = CefGetMimeType ( path.substr ( pos + 1 ) );

// Make sure we provide a mime type, even
// when we cannot deduct it from the file extension
if ( mimeType.empty( ) )
if ( mimeType.empty () )
mimeType = "application/octet-stream";

auto stream = CefStreamReader::CreateForFile ( path );
if ( stream.get () )
return new CefStreamResourceHandler ( mimeType, stream );

if( pWebView->HasAjaxHandler ( path ) )
{
std::vector<SString> vecGet;
std::vector<SString> vecPost;

SString strGet = UTF16ToMbUTF8(urlParts.query.str);
std::vector<SString> vecTmp;
strGet.Split ( "&", vecTmp, 0, 0 );

SString key; SString value;
for ( auto&& param : vecTmp )
{
param.Split ( "=", &key, &value );
vecGet.push_back ( key );
vecGet.push_back ( value );
}

// ToDo: POST Information is Empty for non-standard URI schemes
// Getting POST parameters into Lua will require changing
// mtalocal:// to a standard scheme first
/*
CefPostData::ElementVector vecPostElements;
request->GetPostData ().get ()->GetElements ( vecPostElements );
for ( auto&& post : vecPostElements )
{
// ToDo: Parse POST data into our vector
}
*/

auto handler = new CAjaxResourceHandler ( vecGet, vecPost, mimeType );
pWebView->HandleAjaxRequest ( path, handler );
return handler;
}
else
{
if ( !pWebView->GetFullPathFromLocal ( path ) )
return nullptr;

auto stream = CefStreamReader::CreateForFile ( path );
if ( stream.get () )
return new CefStreamResourceHandler ( mimeType, stream );
}

return nullptr;
}
2 changes: 1 addition & 1 deletion MTA10/core/CWebCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class CWebCore : public CWebCoreInterface
static bool StaticFetchRevisionProgress ( double dDownloadNow, double dDownloadTotal, char* pCompletedData, size_t completedLength, void *pObj, bool bComplete, int iError );
static bool StaticFetchWhitelistProgress ( double dDownloadNow, double dDownloadTotal, char* pCompletedData, size_t completedLength, void *pObj, bool bComplete, int iError );
static bool StaticFetchBlacklistProgress ( double dDownloadNow, double dDownloadTotal, char* pCompletedData, size_t completedLength, void *pObj, bool bComplete, int iError );

private:
typedef std::pair<bool, eWebFilterType> WebFilterPair;

Expand Down
26 changes: 26 additions & 0 deletions MTA10/core/CWebView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*****************************************************************************/
#include "StdInc.h"
#include "CWebView.h"
#include "CAjaxResourceHandler.h"
#include <cef3/include/cef_parser.h>
#include <cef3/include/cef_task.h>
#include <cef3/include/cef_runnable.h>
Expand Down Expand Up @@ -320,6 +321,30 @@ bool CWebView::GetFullPathFromLocal ( SString& strPath )
return m_pEventsInterface->Events_OnResourcePathCheck ( strPath );
}

bool CWebView::RegisterAjaxHandler ( const SString& strURL )
{
auto result = m_AjaxHandlers.insert ( strURL );
return result.second;
}

bool CWebView::UnregisterAjaxHandler ( const SString& strURL )
{
return m_AjaxHandlers.erase ( strURL ) == 1;
}


bool CWebView::HasAjaxHandler ( const SString& strURL )
{
auto iterCB = m_AjaxHandlers.find ( strURL );
return iterCB != m_AjaxHandlers.end ();
}

void CWebView::HandleAjaxRequest ( const SString& strURL, CAjaxResourceHandler * pHandler )
{
auto func = std::bind ( &CWebBrowserEventsInterface::Events_OnAjaxRequest, m_pEventsInterface, pHandler, strURL );
g_pCore->GetWebCore ()->AddEventToEventQueue ( func, this, "AjaxResourceRequest" );
}


////////////////////////////////////////////////////////////////////
// //
Expand Down Expand Up @@ -824,3 +849,4 @@ void CWebView::ConvertURL ( const CefString& url, SString& convertedURL )
convertedURL = "";
}
}

8 changes: 7 additions & 1 deletion MTA10/core/CWebView.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ class CWebView : public CWebViewInterface, private CefClient, private CefRenderH
void GetSourceCode ( const std::function<void( const std::string& code )>& callback );

bool GetFullPathFromLocal ( SString& strPath );

virtual bool RegisterAjaxHandler ( const SString& strURL ) override;
virtual bool UnregisterAjaxHandler ( const SString& strURL ) override;
virtual bool HasAjaxHandler ( const SString& strURL );
virtual void HandleAjaxRequest ( const SString& strURL, class CAjaxResourceHandler * pHandler );

// CefClient methods
virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; };
Expand Down Expand Up @@ -136,7 +141,8 @@ class CWebView : public CWebViewInterface, private CefClient, private CefRenderH
int m_RenderPopupOffsetX, m_RenderPopupOffsetY;
std::map<SString, SString> m_Properties;
bool m_bHasInputFocus;

std::set<std::string> m_AjaxHandlers;

CWebBrowserEventsInterface* m_pEventsInterface;

public:
Expand Down
2 changes: 2 additions & 0 deletions MTA10/core/_Core 2008.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="CAdditionalVertexStreamManager.cpp" />
<ClCompile Include="CAjaxResourceHandler.cpp" />
<ClCompile Include="CChat.cpp" />
<ClCompile Include="CClientVariables.cpp" />
<ClCompile Include="CCommandFuncs.cpp" />
Expand Down Expand Up @@ -396,6 +397,7 @@
<ClInclude Include="..\sdk\core\CWebBrowserEventsInterface.h" />
<ClInclude Include="..\sdk\core\CWebCoreInterface.h" />
<ClInclude Include="..\sdk\core\CWebViewInterface.h" />
<ClInclude Include="CAjaxResourceHandler.h" />
<ClInclude Include="CAdditionalVertexStreamManager.h" />
<ClInclude Include="CAspectRatioConverter.h" />
<ClInclude Include="CChat.h" />
Expand Down
6 changes: 6 additions & 0 deletions MTA10/core/_Core 2008.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,9 @@
<ClCompile Include="CWebView.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CAjaxResourceHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="CAdditionalVertexStreamManager.h">
Expand Down Expand Up @@ -1288,5 +1291,8 @@
<ClInclude Include="..\sdk\core\CWebCoreInterface.h">
<Filter>Header Files\sdk\core</Filter>
</ClInclude>
<ClInclude Include="CAjaxResourceHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
35 changes: 35 additions & 0 deletions MTA10/mods/shared_logic/CClientWebBrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,39 @@ void CClientWebBrowser::Events_OnResourceBlocked ( const SString& strURL, const
CallEvent ( "onClientBrowserResourceBlocked", Arguments, false );
}

void CClientWebBrowser::Events_OnAjaxRequest ( CAjaxResourceHandlerInterface* pHandler, const SString& strURL )
{
auto callbackMapEntry = m_mapAjaxCallback.find ( strURL );

if ( callbackMapEntry == m_mapAjaxCallback.end () )
{
pHandler->SetResponse ( "" );
return;
}

auto callback = callbackMapEntry->second;
SString result = callback ( pHandler->GetGetData (), pHandler->GetPostData () );
pHandler->SetResponse ( result );
}


bool CClientWebBrowser::AddAjaxHandler ( const SString& strURL, ajax_callback_t& handler )
{
if ( !m_pWebView->RegisterAjaxHandler ( strURL ) )
return false;

m_mapAjaxCallback.insert ( std::make_pair ( strURL, handler ) );
return true;
}


bool CClientWebBrowser::RemoveAjaxHandler ( const SString& strURL )
{
if ( !m_pWebView->UnregisterAjaxHandler ( strURL ) )
return false;

return m_mapAjaxCallback.erase ( strURL ) == 1;
}


CClientGUIWebBrowser::CClientGUIWebBrowser ( bool isLocal, bool isTransparent, uint width, uint height, CClientManager* pManager, CLuaMain* pLuaMain, CGUIElement* pCGUIElement, ElementID ID )
Expand All @@ -268,3 +301,5 @@ CClientGUIWebBrowser::CClientGUIWebBrowser ( bool isLocal, bool isTransparent, u
// Set our owner resource
m_pBrowser->SetResource ( pLuaMain->GetResource () );
}


0 comments on commit 72147b4

Please sign in to comment.