Add wxWebViewHandler::StartRequest()

The new method an associated classes allow for a more detailed
handling in wxWebViewHandler instances.

Most notibly post data and headers from the request can be processsed.
The response can be send asynchronously.
This commit is contained in:
Tobias Taschner 2022-09-12 21:54:27 +02:00
parent 0021241d78
commit 4500a48407
No known key found for this signature in database
GPG key ID: AE6ECD71294F87FD
3 changed files with 230 additions and 44 deletions

View file

@ -92,6 +92,37 @@ enum wxWebViewUserScriptInjectionTime
wxWEBVIEW_INJECT_AT_DOCUMENT_END
};
class WXDLLIMPEXP_WEBVIEW wxWebViewHandlerRequest
{
public:
virtual ~wxWebViewHandlerRequest() { }
virtual wxString GetRawURI() const = 0;
virtual wxString GetURI() const { return GetRawURI(); }
virtual wxInputStream* GetData() const = 0;
virtual wxString GetDataString(const wxMBConv& conv = wxConvUTF8) const;
virtual wxString GetMethod() const = 0;
virtual wxString GetHeader(const wxString& name) const = 0;
};
class WXDLLIMPEXP_WEBVIEW wxWebViewHandlerResponseData
{
public:
virtual ~wxWebViewHandlerResponseData() { }
virtual wxInputStream* GetStream() = 0;
};
class WXDLLIMPEXP_WEBVIEW wxWebViewHandlerResponse
{
public:
virtual ~wxWebViewHandlerResponse() { }
virtual void SetStatus(int status) = 0;
virtual void SetContentType(const wxString& contentType) = 0;
virtual void SetHeader(const wxString& name, const wxString& value) = 0;
virtual void Finish(wxSharedPtr<wxWebViewHandlerResponseData> data) = 0;
virtual void Finish(const wxString& text, const wxMBConv& conv = wxConvUTF8);
virtual void FinishWithError() = 0;
};
//Base class for custom scheme handlers
class WXDLLIMPEXP_WEBVIEW wxWebViewHandler
{
@ -100,12 +131,17 @@ public:
: m_scheme(scheme), m_securityURL() {}
virtual ~wxWebViewHandler() {}
virtual wxString GetName() const { return m_scheme; }
virtual wxFSFile* GetFile(const wxString &uri) = 0;
virtual wxFSFile* GetFile(const wxString &uri);
virtual void SetSecurityURL(const wxString& url) { m_securityURL = url; }
virtual wxString GetSecurityURL() const { return m_securityURL; }
virtual void SetVirtualHost(const wxString& host) { m_virtualHost = host; }
virtual wxString GetVirtualHost() const;
virtual void StartRequest(const wxWebViewHandlerRequest& request,
wxSharedPtr<wxWebViewHandlerResponse> response);
private:
wxString m_scheme;
wxString m_securityURL;
wxString m_virtualHost;
};
extern WXDLLIMPEXP_DATA_WEBVIEW(const char) wxWebViewNameStr[];

View file

@ -13,6 +13,8 @@
#include "wx/webview.h"
#include "wx/filesys.h"
#include "wx/mstream.h"
#if defined(__WXOSX__)
#include "wx/osx/webview_webkit.h"
@ -52,6 +54,92 @@ wxDEFINE_EVENT( wxEVT_WEBVIEW_FULLSCREEN_CHANGED, wxWebViewEvent);
wxDEFINE_EVENT( wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, wxWebViewEvent);
wxDEFINE_EVENT( wxEVT_WEBVIEW_SCRIPT_RESULT, wxWebViewEvent);
// wxWebViewHandlerRequest
wxString wxWebViewHandlerRequest::GetDataString(const wxMBConv& conv) const
{
wxInputStream* data = GetData();
if (!data)
return wxString();
size_t length = data->GetLength();
wxMemoryBuffer buffer;
data->ReadAll(buffer.GetWriteBuf(length), length);
wxString dataStr((const char*) buffer.GetData(), conv, length);
return dataStr;
}
// wxWebViewHandlerResponseDataStream
class wxWebViewHandlerResponseDataString : public wxWebViewHandlerResponseData
{
public:
wxWebViewHandlerResponseDataString(const wxCharBuffer& data): m_data(data)
{
m_stream = new wxMemoryInputStream(m_data, m_data.length());
}
~wxWebViewHandlerResponseDataString() { delete m_stream; }
virtual wxInputStream* GetStream() wxOVERRIDE
{
return m_stream;
}
wxCharBuffer m_data;
wxInputStream* m_stream;
};
// wxWebViewHandlerResponse
void wxWebViewHandlerResponse::Finish(const wxString& text,
const wxMBConv& conv)
{
Finish(wxSharedPtr<wxWebViewHandlerResponseData>(
new wxWebViewHandlerResponseDataString(text.mb_str(conv))));
}
// wxWebViewHandlerResponseDataFile
class wxWebViewHandlerResponseDataFile : public wxWebViewHandlerResponseData
{
public:
wxWebViewHandlerResponseDataFile(wxFSFile* file): m_file(file) { }
~wxWebViewHandlerResponseDataFile() { delete m_file; }
virtual wxInputStream* GetStream() wxOVERRIDE
{ return m_file->GetStream(); }
wxFSFile* m_file;
};
// wxWebViewHandler
wxString wxWebViewHandler::GetVirtualHost() const
{
if (m_virtualHost.empty())
return GetName() + ".wxsite";
else
return m_virtualHost;
}
wxFSFile* wxWebViewHandler::GetFile(const wxString& WXUNUSED(uri))
{
return NULL;
}
void wxWebViewHandler::StartRequest(const wxWebViewHandlerRequest& request,
wxSharedPtr<wxWebViewHandlerResponse> response)
{
wxFSFile* file = GetFile(request.GetURI());
if (file)
{
response->SetContentType(file->GetMimeType());
response->Finish(wxSharedPtr<wxWebViewHandlerResponseData>(
new wxWebViewHandlerResponseDataFile(file)));
}
else
response->FinishWithError();
}
// wxWebView
wxStringWebViewFactoryMap wxWebView::m_factoryMap;
wxWebViewZoom wxWebView::GetZoom() const

View file

@ -30,6 +30,7 @@
#include "wx/hashmap.h"
#include "wx/filesys.h"
#include "wx/msgdlg.h"
#include "wx/mstream.h"
#include "wx/textdlg.h"
#include "wx/filedlg.h"
@ -847,6 +848,107 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebViewNavigationError* out)
@end
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13
class wxWebViewWebKitHandlerRequest: public wxWebViewHandlerRequest
{
public:
wxWebViewWebKitHandlerRequest(NSURLRequest* request):
m_data(NULL),
m_request(request)
{ }
~wxWebViewWebKitHandlerRequest()
{ wxDELETE(m_data); }
virtual wxString GetRawURI() const wxOVERRIDE
{ return wxCFStringRef::AsString(m_request.URL.absoluteString); }
virtual wxInputStream* GetData() const wxOVERRIDE
{
if (!m_data && m_request.HTTPBody)
m_data = new wxMemoryInputStream(m_request.HTTPBody.bytes, m_request.HTTPBody.length);
return m_data;
}
virtual wxString GetMethod() const wxOVERRIDE
{ return wxCFStringRef::AsString(m_request.HTTPMethod); }
virtual wxString GetHeader(const wxString& name) const wxOVERRIDE
{
return wxCFStringRef::AsString(
[m_request valueForHTTPHeaderField:wxCFStringRef(name).AsNSString()]);
}
mutable wxInputStream* m_data;
NSURLRequest* m_request;
};
class API_AVAILABLE(macos(10.13)) wxWebViewWebkitHandlerResponse: public wxWebViewHandlerResponse
{
public:
wxWebViewWebkitHandlerResponse(id<WKURLSchemeTask> task):
m_status(200),
m_task([task retain])
{
m_headers = [[NSMutableDictionary alloc] init];
}
~wxWebViewWebkitHandlerResponse()
{
[m_headers release];
[m_task release];
}
virtual void SetStatus(int status) wxOVERRIDE
{ m_status = status; }
virtual void SetContentType(const wxString& contentType) wxOVERRIDE
{ SetHeader("Content-Type", contentType); }
virtual void SetHeader(const wxString& name, const wxString& value) wxOVERRIDE
{
[m_headers setValue:wxCFStringRef(value).AsNSString()
forKey:wxCFStringRef(name).AsNSString()];
}
virtual void Finish(wxSharedPtr<wxWebViewHandlerResponseData> data) wxOVERRIDE
{
m_data = data;
wxInputStream* stream = data->GetStream();
size_t length = stream->GetLength();
NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:m_task.request.URL
statusCode:m_status
HTTPVersion:nil
headerFields:m_headers];
[m_task didReceiveResponse:response];
[response release];
//Load the data, we malloc it so it is tidied up properly
void* buffer = malloc(length);
stream->Read(buffer, length);
NSData *taskData = [[NSData alloc] initWithBytesNoCopy:buffer length:length];
[m_task didReceiveData:taskData];
[taskData release];
[m_task didFinish];
}
virtual void FinishWithError() wxOVERRIDE
{
NSError *error = [[NSError alloc] initWithDomain:NSURLErrorDomain
code:NSURLErrorFileDoesNotExist
userInfo:nil];
[m_task didFailWithError:error];
[error release];
}
int m_status;
NSMutableDictionary* m_headers;
id<WKURLSchemeTask> m_task;
wxSharedPtr<wxWebViewHandlerResponseData> m_data;
};
@implementation WebViewCustomProtocol
- (id)initWithHandler:(wxWebViewHandler *)handler
@ -858,49 +960,9 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebViewNavigationError* out)
- (void)webView:(WKWebView *)webView startURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask
WX_API_AVAILABLE_MACOS(10, 13)
{
NSURLRequest *request = urlSchemeTask.request;
NSString* path = [[request URL] absoluteString];
wxString wxpath = wxCFStringRef::AsString(path);
wxFSFile* file = m_handler->GetFile(wxpath);
if (!file)
{
NSError *error = [[NSError alloc] initWithDomain:NSURLErrorDomain
code:NSURLErrorFileDoesNotExist
userInfo:nil];
[urlSchemeTask didFailWithError:error];
[error release];
return;
}
size_t length = file->GetStream()->GetLength();
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[request URL]
MIMEType:wxCFStringRef(file->GetMimeType()).AsNSString()
expectedContentLength:length
textEncodingName:nil];
//Load the data, we malloc it so it is tidied up properly
void* buffer = malloc(length);
file->GetStream()->Read(buffer, length);
NSData *data = [[NSData alloc] initWithBytesNoCopy:buffer length:length];
//Set the data
[urlSchemeTask didReceiveResponse:response];
[urlSchemeTask didReceiveData:data];
//Notify that we have finished
[urlSchemeTask didFinish];
[data release];
[response release];
wxWebViewWebKitHandlerRequest request(urlSchemeTask.request);
wxSharedPtr<wxWebViewHandlerResponse> response(new wxWebViewWebkitHandlerResponse(urlSchemeTask));
m_handler->StartRequest(request, response);
}
- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask