Initial NSURLSession implementation

First incomplete implementation based on NSURLSession
This commit is contained in:
Tobias Taschner
2018-11-06 14:44:41 +00:00
parent 45f006d752
commit 152e160f76
4 changed files with 335 additions and 13 deletions

37
configure vendored
View File

@@ -1139,6 +1139,7 @@ enable_ole
enable_dataobj
enable_webrequest
enable_webrequestcurl
enable_webrequesturlsession
enable_ipc
enable_baseevtloop
enable_epollloop
@@ -2083,6 +2084,7 @@ Optional Features:
--enable-dataobj use data object classes
--enable-webrequest use wxWebRequest
--enable-webrequest-curl use libcurl with wxWebRequest
--enable-webrequest-urlsession use NSURLSession with wxWebRequest
--enable-ipc use interprocess communication (wxSocket etc.)
--enable-baseevtloop use event loop in console programs too
--enable-epollloop use wxEpollDispatcher class (Linux only)
@@ -6580,7 +6582,37 @@ fi
eval "$wx_cv_use_webrequestcurl"
if test "$USE_DARWIN" = 1; then
enablestring=
defaultval=$wxUSE_ALL_FEATURES
if test -z "$defaultval"; then
if test x"$enablestring" = xdisable; then
defaultval=yes
else
defaultval=no
fi
fi
# Check whether --enable-webrequesturlsession was given.
if test "${enable_webrequesturlsession+set}" = set; then :
enableval=$enable_webrequesturlsession;
if test "$enableval" = yes; then
wx_cv_use_webrequesturlsession='wxUSE_WEBREQUEST_URLSESSION=yes'
else
wx_cv_use_webrequesturlsession='wxUSE_WEBREQUEST_URLSESSION=no'
fi
else
wx_cv_use_webrequesturlsession='wxUSE_WEBREQUEST_URLSESSION=${'DEFAULT_wxUSE_WEBREQUEST_URLSESSION":-$defaultval}"
fi
eval "$wx_cv_use_webrequesturlsession"
fi
enablestring=
defaultval=$wxUSE_ALL_FEATURES
@@ -36714,6 +36746,11 @@ if test "$wxUSE_WEBREQUEST" = "yes"; then
$as_echo "#define wxUSE_WEBREQUEST 1" >>confdefs.h
if test "$wxUSE_WEBREQUEST_URLSESSION" = "yes"; then
$as_echo "#define wxUSE_WEBREQUEST_URLSESSION 1" >>confdefs.h
fi
if test "$wxUSE_MSW" = 1; then
$as_echo "#define wxUSE_WEBREQUEST_WINHTTP 1" >>confdefs.h

View File

@@ -700,6 +700,9 @@ WX_ARG_FEATURE(ole, [ --enable-ole use OLE classes (Win32
WX_ARG_FEATURE(dataobj, [ --enable-dataobj use data object classes], wxUSE_DATAOBJ)
WX_ARG_FEATURE(webrequest, [ --enable-webrequest use wxWebRequest], wxUSE_WEBREQUEST)
WX_ARG_FEATURE(webrequestcurl, [ --enable-webrequest-curl use libcurl with wxWebRequest], wxUSE_WEBREQUEST_LIBCURL)
if test "$USE_DARWIN" = 1; then
WX_ARG_FEATURE(webrequesturlsession, [ --enable-webrequest-urlsession use NSURLSession with wxWebRequest], wxUSE_WEBREQUEST_URLSESSION)
fi dnl USE_DARWIN
WX_ARG_FEATURE(ipc, [ --enable-ipc use interprocess communication (wxSocket etc.)], wxUSE_IPC)
@@ -6369,6 +6372,10 @@ fi
if test "$wxUSE_WEBREQUEST" = "yes"; then
AC_DEFINE(wxUSE_WEBREQUEST)
if test "$wxUSE_WEBREQUEST_URLSESSION" = "yes"; then
AC_DEFINE(wxUSE_WEBREQUEST_URLSESSION)
fi
if test "$wxUSE_MSW" = 1; then
dnl TODO: Check for the required headers/libraries under Windows
AC_DEFINE(wxUSE_WEBREQUEST_WINHTTP)

View File

@@ -13,28 +13,98 @@
#if wxUSE_WEBREQUEST_URLSESSION
DECLARE_WXCOCOA_OBJC_CLASS(NSURLSession);
DECLARE_WXCOCOA_OBJC_CLASS(NSURLTask);
DECLARE_WXCOCOA_OBJC_CLASS(NSURLSessionTask);
DECLARE_WXCOCOA_OBJC_CLASS(wxWebSessionDelegte);
class wxWebSessionURLSession;
class wxWebResponseURLSession;
class WXDLLIMPEXP_NET wxWebResponseURLSession: public wxWebResponse
{
public:
wxWebResponseURLSession(wxWebRequest& request, WX_NSURLSessionTask task);
~wxWebResponseURLSession();
wxInt64 GetContentLength() const wxOVERRIDE;
wxString GetURL() const wxOVERRIDE;
wxString GetHeader(const wxString& name) const wxOVERRIDE;
int GetStatus() const wxOVERRIDE;
wxString GetStatusText() const wxOVERRIDE;
wxString GetSuggestedFileName() const wxOVERRIDE;
void HandleData(WX_NSData data);
private:
WX_NSURLSessionTask m_task;
};
class WXDLLIMPEXP_NET wxWebRequestURLSession: public wxWebRequest
{
public:
wxWebRequestURLSession(wxWebSessionURLSession& session, const wxString& url, int id);
~wxWebRequestURLSession();
void Start() wxOVERRIDE;
void Cancel() wxOVERRIDE;
wxWebResponse* GetResponse() const wxOVERRIDE
{ return m_response.get(); }
wxWebAuthChallenge* GetAuthChallenge() const wxOVERRIDE;
wxFileOffset GetBytesSent() const wxOVERRIDE;
wxFileOffset GetBytesExpectedToSend() const wxOVERRIDE;
wxFileOffset GetBytesReceived() const wxOVERRIDE;
wxFileOffset GetBytesExpectedToReceive() const wxOVERRIDE;
void HandleCompletion();
private:
wxString m_url;
WX_NSURLSessionTask m_task;
wxScopedPtr<wxWebResponseURLSession> m_response;
wxDECLARE_NO_COPY_CLASS(wxWebRequestURLSession);
};
class WXDLLIMPEXP_NET wxWebSessionURLSession: public wxWebSession
{
public:
wxWebSessionURLSession();
wxWebSessionURLSession();
~wxWebSessionURLSession();
~wxWebSessionURLSession();
wxWebRequest* CreateRequest(const wxString& url, int id = wxID_ANY) wxOVERRIDE;
wxWebRequest* CreateRequest(const wxString& url, int id = wxID_ANY) wxOVERRIDE;
wxVersionInfo GetLibraryVersionInfo() wxOVERRIDE;
WX_NSURLSession GetSession() { return m_session; }
WX_wxWebSessionDelegte GetDelegate() { return m_delegate; }
private:
WX_NSURLSession m_session;
WX_NSURLSession m_session;
WX_wxWebSessionDelegte m_delegate;
wxDECLARE_NO_COPY_CLASS(wxWebSessionURLSession);
wxDECLARE_NO_COPY_CLASS(wxWebSessionURLSession);
};
class WXDLLIMPEXP_NET wxWebSessionFactoryURLSession: public wxWebSessionFactory
{
public:
wxWebSession* Create() wxOVERRIDE
{ return new wxWebSessionURLSession(); }
wxWebSession* Create() wxOVERRIDE
{ return new wxWebSessionURLSession(); }
};
#endif // wxUSE_WEBREQUEST_URLSESSION

View File

@@ -21,22 +21,230 @@
#import <Foundation/Foundation.h>
#include "wx/osx/webrequest_urlsession.h"
#include "wx/osx/private.h"
#ifndef WX_PRECOMP
#include "wx/log.h"
#include "wx/utils.h"
#endif
@interface wxWebSessionDelegte : NSObject <NSURLSessionDataDelegate>
{
wxWebSessionURLSession* m_session;
NSMapTable* m_requests;
}
@end
@implementation wxWebSessionDelegte
- initWithSession:(wxWebSessionURLSession*)session
{
m_session = session;
m_requests = [[NSMapTable weakToStrongObjectsMapTable] retain];
return self;
}
- (void)dealloc
{
[m_requests release];
[super dealloc];
}
- (void)registerRequest:(wxWebRequestURLSession*)request task:(NSURLSessionTask*)task
{
[m_requests setObject:[NSValue valueWithPointer:request] forKey:task];
}
- (wxWebRequestURLSession*)requestForTask:(NSURLSessionTask*)task
{
wxWebRequestURLSession* request = NULL;
NSValue* val = [m_requests objectForKey:task];
if (val)
request = static_cast<wxWebRequestURLSession*>(val.pointerValue);
return request;
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
wxWebRequestURLSession* request = [self requestForTask:dataTask];
if (request)
static_cast<wxWebResponseURLSession*>(request->GetResponse())->HandleData(data);
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
wxWebRequestURLSession* request = [self requestForTask:task];
if (error)
request->SetState(wxWebRequest::State_Failed, wxCFStringRef(error.localizedDescription).AsString());
else
request->HandleCompletion();
// After the task is completed it no longer needs to be mapped
[m_requests removeObjectForKey:task];
}
@end
//
// wxWebRequestURLSession
//
wxWebRequestURLSession::wxWebRequestURLSession(wxWebSessionURLSession& session, const wxString& url, int id):
wxWebRequest(session, id),
m_url(url)
{
}
wxWebRequestURLSession::~wxWebRequestURLSession()
{
[m_task release];
}
void wxWebRequestURLSession::Start()
{
wxWebSessionURLSession& session = static_cast<wxWebSessionURLSession&>(GetSession());
m_task = [[session.GetSession() dataTaskWithURL:
[NSURL URLWithString:wxCFStringRef(m_url).AsNSString()]] retain];
// The session delegate needs to know which task is wrapped in which request
[session.GetDelegate() registerRequest:this task:m_task];
m_response.reset(new wxWebResponseURLSession(*this, m_task));
m_response->Init();
SetState(State_Active);
[m_task resume];
}
void wxWebRequestURLSession::Cancel()
{
[m_task cancel];
}
void wxWebRequestURLSession::HandleCompletion()
{
if ( CheckServerStatus() )
SetState(State_Completed);
}
wxWebAuthChallenge* wxWebRequestURLSession::GetAuthChallenge() const
{
wxFAIL_MSG("not implemented");
return NULL;
}
wxFileOffset wxWebRequestURLSession::GetBytesSent() const
{
return m_task.countOfBytesSent;
}
wxFileOffset wxWebRequestURLSession::GetBytesExpectedToSend() const
{
return m_task.countOfBytesExpectedToSend;
}
wxFileOffset wxWebRequestURLSession::GetBytesReceived() const
{
return m_task.countOfBytesReceived;
}
wxFileOffset wxWebRequestURLSession::GetBytesExpectedToReceive() const
{
return m_task.countOfBytesExpectedToReceive;
}
//
// wxWebResponseURLSession
//
wxWebResponseURLSession::wxWebResponseURLSession(wxWebRequest& request, WX_NSURLSessionTask task):
wxWebResponse(request)
{
m_task = [task retain];
}
wxWebResponseURLSession::~wxWebResponseURLSession()
{
[m_task release];
}
void wxWebResponseURLSession::HandleData(WX_NSData data)
{
[data enumerateByteRangesUsingBlock:^(const void * _Nonnull bytes, NSRange byteRange, BOOL * _Nonnull stop) {
void* buf = GetDataBuffer(byteRange.length);
std::memcpy(buf, bytes, byteRange.length);
ReportDataReceived(byteRange.length);
}];
}
wxInt64 wxWebResponseURLSession::GetContentLength() const
{
return m_task.response.expectedContentLength;
}
wxString wxWebResponseURLSession::GetURL() const
{
return wxCFStringRef(m_task.response.URL.absoluteString).AsString();
}
wxString wxWebResponseURLSession::GetHeader(const wxString& name) const
{
NSHTTPURLResponse* httpResp = (NSHTTPURLResponse*) m_task.response;
NSString* value = [httpResp.allHeaderFields objectForKey:wxCFStringRef(name).AsNSString()];
if (value)
return wxCFStringRef(value).AsString();
else
return wxString();
}
int wxWebResponseURLSession::GetStatus() const
{
NSHTTPURLResponse* httpResp = (NSHTTPURLResponse*) m_task.response;
return httpResp.statusCode;
}
wxString wxWebResponseURLSession::GetStatusText() const
{
return wxCFStringRef([NSHTTPURLResponse localizedStringForStatusCode:GetStatus()]).AsString();
}
wxString wxWebResponseURLSession::GetSuggestedFileName() const
{
return wxCFStringRef(m_task.response.suggestedFilename).AsString();
}
//
// wxWebSessionURLSession
//
wxWebSessionURLSession::wxWebSessionURLSession()
{
m_session = [NSURLSession sessionWithConfiguration:
[NSURLSessionConfiguration defaultSessionConfiguration]];
m_delegate = [[wxWebSessionDelegte alloc] initWithSession:this];
m_session = [[NSURLSession sessionWithConfiguration:
[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:m_delegate delegateQueue:nil] retain];
}
wxWebSessionURLSession::~wxWebSessionURLSession()
{
[m_session release];
[m_session release];
[m_delegate release];
}
wxWebRequest* wxWebSessionURLSession::CreateRequest(const wxString& url, int id)
{
wxFAIL_MSG("not implemented");
return NULL;
return new wxWebRequestURLSession(*this, url, id);
}
wxVersionInfo wxWebSessionURLSession::GetLibraryVersionInfo()
{
int verMaj, verMin, verMicro;
wxGetOsVersion(&verMaj, &verMin, &verMicro);
return wxVersionInfo("URLSession", verMaj, verMin, verMicro);
}
#endif // wxUSE_WEBREQUEST_URLSESSION