X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1680c3561bc4f44c63a026e0d1a5324a39336156..2712275c88c78af135489c22d306ed6ad2ad5b1f:/src/osx/webview_webkit.mm diff --git a/src/osx/webview_webkit.mm b/src/osx/webview_webkit.mm index b99504e125..74e23a63cc 100644 --- a/src/osx/webview_webkit.mm +++ b/src/osx/webview_webkit.mm @@ -14,8 +14,8 @@ #include "wx/osx/webview_webkit.h" -#if wxUSE_WEBVIEW_WEBKIT && (defined(__WXOSX_COCOA__) \ - || defined(__WXOSX_CARBON__)) +#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT && (defined(__WXOSX_COCOA__) \ + || defined(__WXOSX_CARBON__)) // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -26,6 +26,8 @@ #include "wx/osx/private.h" #include "wx/cocoa/string.h" +#include "wx/hashmap.h" +#include "wx/filesys.h" #include #include @@ -295,7 +297,7 @@ DEFINE_ONE_SHOT_HANDLER_GETTER( wxWebViewWebKitEventHandler ) #endif -@interface MyFrameLoadMonitor : NSObject +@interface WebViewLoadDelegate : NSObject { wxWebViewWebKit* webKitWindow; } @@ -304,7 +306,7 @@ DEFINE_ONE_SHOT_HANDLER_GETTER( wxWebViewWebKitEventHandler ) @end -@interface MyPolicyDelegate : NSObject +@interface WebViewPolicyDelegate : NSObject { wxWebViewWebKit* webKitWindow; } @@ -313,6 +315,16 @@ DEFINE_ONE_SHOT_HANDLER_GETTER( wxWebViewWebKitEventHandler ) @end +//We use a hash to map scheme names to wxWebViewHandler +WX_DECLARE_STRING_HASH_MAP(wxSharedPtr, wxStringToWebHandlerMap); + +static wxStringToWebHandlerMap g_stringHandlerMap; + +@interface WebViewCustomProtocol : NSURLProtocol +{ +} +@end + // ---------------------------------------------------------------------------- // creation/destruction // ---------------------------------------------------------------------------- @@ -326,75 +338,80 @@ bool wxWebViewWebKit::Create(wxWindow *parent, { m_busy = false; + DontCreatePeer(); wxControl::Create(parent, winID, pos, size, style, wxDefaultValidator, name); #if wxOSX_USE_CARBON - m_peer = new wxMacControl(this); + wxMacControl* peer = new wxMacControl(this); WebInitForCarbon(); - HIWebViewCreate( m_peer->GetControlRefAddr() ); + HIWebViewCreate( peer->GetControlRefAddr() ); - m_webView = (WebView*) HIWebViewGetWebView( m_peer->GetControlRef() ); + m_webView = (WebView*) HIWebViewGetWebView( peer->GetControlRef() ); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 if ( UMAGetSystemVersion() >= 0x1030 ) - HIViewChangeFeatures( m_peer->GetControlRef() , kHIViewIsOpaque , 0 ) ; + HIViewChangeFeatures( peer->GetControlRef() , kHIViewIsOpaque , 0 ) ; #endif - InstallControlEventHandler(m_peer->GetControlRef(), + InstallControlEventHandler(peer->GetControlRef(), GetwxWebViewWebKitEventHandlerUPP(), GetEventTypeCount(eventList), eventList, this, (EventHandlerRef *)&m_webKitCtrlEventHandler); + SetPeer(peer); #else NSRect r = wxOSXGetFrameForControl( this, pos , size ) ; m_webView = [[WebView alloc] initWithFrame:r frameName:@"webkitFrame" groupName:@"webkitGroup"]; - m_peer = new wxWidgetCocoaImpl( this, m_webView ); + SetPeer(new wxWidgetCocoaImpl( this, m_webView )); #endif MacPostControlCreate(pos, size); #if wxOSX_USE_CARBON - HIViewSetVisible( m_peer->GetControlRef(), true ); + HIViewSetVisible( GetPeer()->GetControlRef(), true ); #endif [m_webView setHidden:false]; // Register event listener interfaces - MyFrameLoadMonitor* myFrameLoadMonitor = - [[MyFrameLoadMonitor alloc] initWithWxWindow: this]; + WebViewLoadDelegate* loadDelegate = + [[WebViewLoadDelegate alloc] initWithWxWindow: this]; - [m_webView setFrameLoadDelegate:myFrameLoadMonitor]; + [m_webView setFrameLoadDelegate:loadDelegate]; // this is used to veto page loads, etc. - MyPolicyDelegate* myPolicyDelegate = - [[MyPolicyDelegate alloc] initWithWxWindow: this]; + WebViewPolicyDelegate* policyDelegate = + [[WebViewPolicyDelegate alloc] initWithWxWindow: this]; - [m_webView setPolicyDelegate:myPolicyDelegate]; + [m_webView setPolicyDelegate:policyDelegate]; - LoadUrl(strURL); + //Register our own class for custom scheme handling + [NSURLProtocol registerClass:[WebViewCustomProtocol class]]; + + LoadURL(strURL); return true; } wxWebViewWebKit::~wxWebViewWebKit() { - MyFrameLoadMonitor* myFrameLoadMonitor = [m_webView frameLoadDelegate]; - MyPolicyDelegate* myPolicyDelegate = [m_webView policyDelegate]; + WebViewLoadDelegate* loadDelegate = [m_webView frameLoadDelegate]; + WebViewPolicyDelegate* policyDelegate = [m_webView policyDelegate]; [m_webView setFrameLoadDelegate: nil]; [m_webView setPolicyDelegate: nil]; - if (myFrameLoadMonitor) - [myFrameLoadMonitor release]; + if (loadDelegate) + [loadDelegate release]; - if (myPolicyDelegate) - [myPolicyDelegate release]; + if (policyDelegate) + [policyDelegate release]; } // ---------------------------------------------------------------------------- // public methods // ---------------------------------------------------------------------------- -bool wxWebViewWebKit::CanGoBack() +bool wxWebViewWebKit::CanGoBack() const { if ( !m_webView ) return false; @@ -402,7 +419,7 @@ bool wxWebViewWebKit::CanGoBack() return [m_webView canGoBack]; } -bool wxWebViewWebKit::CanGoForward() +bool wxWebViewWebKit::CanGoForward() const { if ( !m_webView ) return false; @@ -452,7 +469,7 @@ void wxWebViewWebKit::Stop() [[m_webView mainFrame] stopLoading]; } -bool wxWebViewWebKit::CanGetPageSource() +bool wxWebViewWebKit::CanGetPageSource() const { if ( !m_webView ) return false; @@ -461,7 +478,7 @@ bool wxWebViewWebKit::CanGetPageSource() return ( [[dataSource representation] canProvideDocumentSource] ); } -wxString wxWebViewWebKit::GetPageSource() +wxString wxWebViewWebKit::GetPageSource() const { if (CanGetPageSource()) @@ -484,7 +501,7 @@ wxString wxWebViewWebKit::GetPageSource() return wxEmptyString; } -bool wxWebViewWebKit::CanIncreaseTextSize() +bool wxWebViewWebKit::CanIncreaseTextSize() const { if ( !m_webView ) return false; @@ -504,7 +521,7 @@ void wxWebViewWebKit::IncreaseTextSize() [m_webView makeTextLarger:(WebView*)m_webView]; } -bool wxWebViewWebKit::CanDecreaseTextSize() +bool wxWebViewWebKit::CanDecreaseTextSize() const { if ( !m_webView ) return false; @@ -556,7 +573,7 @@ void wxWebViewWebKit::SetEditable(bool enable) [m_webView setEditable:enable ]; } -bool wxWebViewWebKit::IsEditable() +bool wxWebViewWebKit::IsEditable() const { if ( !m_webView ) return false; @@ -612,7 +629,7 @@ void wxWebViewWebKit::SetScrollPos(int pos) (NSString*)wxNSStringWithWxString( javascript )]; } -wxString wxWebViewWebKit::GetSelectedText() +wxString wxWebViewWebKit::GetSelectedText() const { NSString* selection = [[m_webView selectedDOMRange] markupString]; if (!selection) return wxEmptyString; @@ -710,7 +727,7 @@ void wxWebViewWebKit::OnSize(wxSizeEvent &event) void wxWebViewWebKit::MacVisibilityChanged(){ #if defined(__WXMAC__) && wxOSX_USE_CARBON - bool isHidden = !IsControlVisible( m_peer->GetControlRef()); + bool isHidden = !IsControlVisible( GetPeer()->GetControlRef()); if (!isHidden) [(WebView*)m_webView display]; @@ -718,23 +735,23 @@ void wxWebViewWebKit::MacVisibilityChanged(){ #endif } -void wxWebViewWebKit::LoadUrl(const wxString& url) +void wxWebViewWebKit::LoadURL(const wxString& url) { [[m_webView mainFrame] loadRequest:[NSURLRequest requestWithURL: [NSURL URLWithString:wxNSStringWithWxString(url)]]]; } -wxString wxWebViewWebKit::GetCurrentURL() +wxString wxWebViewWebKit::GetCurrentURL() const { return wxStringWithNSString([m_webView mainFrameURL]); } -wxString wxWebViewWebKit::GetCurrentTitle() +wxString wxWebViewWebKit::GetCurrentTitle() const { return wxStringWithNSString([m_webView mainFrameTitle]); } -float wxWebViewWebKit::GetWebkitZoom() +float wxWebViewWebKit::GetWebkitZoom() const { return [m_webView textSizeMultiplier]; } @@ -744,7 +761,7 @@ void wxWebViewWebKit::SetWebkitZoom(float zoom) [m_webView setTextSizeMultiplier:zoom]; } -wxWebViewZoom wxWebViewWebKit::GetZoom() +wxWebViewZoom wxWebViewWebKit::GetZoom() const { float zoom = GetWebkitZoom(); @@ -848,7 +865,7 @@ void wxWebViewWebKit::DeleteSelection() [(WebView*)m_webView deleteSelection]; } -bool wxWebViewWebKit::HasSelection() +bool wxWebViewWebKit::HasSelection() const { DOMRange* range = [m_webView selectedDOMRange]; if(!range) @@ -872,7 +889,7 @@ void wxWebViewWebKit::SelectAll() RunScript("window.getSelection().selectAllChildren(document.body);"); } -wxString wxWebViewWebKit::GetSelectedSource() +wxString wxWebViewWebKit::GetSelectedSource() const { wxString script = ("var range = window.getSelection().getRangeAt(0);" "var element = document.createElement('div');" @@ -883,7 +900,7 @@ wxString wxWebViewWebKit::GetSelectedSource() return wxStringWithNSString([result stringValue]); } -wxString wxWebViewWebKit::GetPageText() +wxString wxWebViewWebKit::GetPageText() const { id result = [[m_webView windowScriptObject] evaluateWebScript:@"document.body.textContent"]; @@ -904,9 +921,9 @@ void wxWebViewWebKit::ClearHistory() [m_webView setMaintainsBackForwardList:YES]; } -wxVector > wxWebViewWebKit::GetBackwardHistory() +wxVector > wxWebViewWebKit::GetBackwardHistory() { - wxVector > backhist; + wxVector > backhist; WebBackForwardList* history = [m_webView backForwardList]; int count = [history backListCount]; for(int i = -count; i < 0; i++) @@ -914,17 +931,17 @@ wxVector > wxWebViewWebKit::GetBackwardHistory() WebHistoryItem* item = [history itemAtIndex:i]; wxString url = wxStringWithNSString([item URLString]); wxString title = wxStringWithNSString([item title]); - wxWebHistoryItem* wxitem = new wxWebHistoryItem(url, title); + wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem(url, title); wxitem->m_histItem = item; - wxSharedPtr itemptr(wxitem); + wxSharedPtr itemptr(wxitem); backhist.push_back(itemptr); } return backhist; } -wxVector > wxWebViewWebKit::GetForwardHistory() +wxVector > wxWebViewWebKit::GetForwardHistory() { - wxVector > forwardhist; + wxVector > forwardhist; WebBackForwardList* history = [m_webView backForwardList]; int count = [history forwardListCount]; for(int i = 1; i <= count; i++) @@ -932,25 +949,25 @@ wxVector > wxWebViewWebKit::GetForwardHistory() WebHistoryItem* item = [history itemAtIndex:i]; wxString url = wxStringWithNSString([item URLString]); wxString title = wxStringWithNSString([item title]); - wxWebHistoryItem* wxitem = new wxWebHistoryItem(url, title); + wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem(url, title); wxitem->m_histItem = item; - wxSharedPtr itemptr(wxitem); + wxSharedPtr itemptr(wxitem); forwardhist.push_back(itemptr); } return forwardhist; } -void wxWebViewWebKit::LoadHistoryItem(wxSharedPtr item) +void wxWebViewWebKit::LoadHistoryItem(wxSharedPtr item) { [m_webView goToBackForwardItem:item->m_histItem]; } -bool wxWebViewWebKit::CanUndo() +bool wxWebViewWebKit::CanUndo() const { return [[m_webView undoManager] canUndo]; } -bool wxWebViewWebKit::CanRedo() +bool wxWebViewWebKit::CanRedo() const { return [[m_webView undoManager] canRedo]; } @@ -965,6 +982,11 @@ void wxWebViewWebKit::Redo() [[m_webView undoManager] redo]; } +void wxWebViewWebKit::RegisterHandler(wxSharedPtr handler) +{ + g_stringHandlerMap[handler->GetName()] = handler; +} + //------------------------------------------------------------ // Listener interfaces //------------------------------------------------------------ @@ -974,7 +996,7 @@ void wxWebViewWebKit::Redo() // destroyed. Therefore, we must be careful to check both the existence // of the Carbon control and the event handler before firing events. -@implementation MyFrameLoadMonitor +@implementation WebViewLoadDelegate - initWithWxWindow: (wxWebViewWebKit*)inWindow { @@ -996,13 +1018,13 @@ void wxWebViewWebKit::Redo() if (webKitWindow && frame == [sender mainFrame]){ NSString *url = [[[[frame dataSource] request] URL] absoluteString]; wxString target = wxStringWithNSString([frame name]); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, - webKitWindow->GetId(), - wxStringWithNSString( url ), - target, false); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, + webKitWindow->GetId(), + wxStringWithNSString( url ), + target); if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); } } @@ -1014,17 +1036,17 @@ void wxWebViewWebKit::Redo() NSString *url = [[[[frame dataSource] request] URL] absoluteString]; wxString target = wxStringWithNSString([frame name]); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_LOADED, - webKitWindow->GetId(), - wxStringWithNSString( url ), - target, false); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, + webKitWindow->GetId(), + wxStringWithNSString( url ), + target); if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); } } -wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) +wxString nsErrorToWxHtmlError(NSError* error, wxWebViewNavigationError* out) { *out = wxWEB_NAV_ERR_OTHER; @@ -1040,7 +1062,9 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) case NSURLErrorResourceUnavailable: case NSURLErrorHTTPTooManyRedirects: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 case NSURLErrorDataLengthExceedsMaximum: +#endif case NSURLErrorBadURL: case NSURLErrorFileIsDirectory: *out = wxWEB_NAV_ERR_REQUEST; @@ -1062,16 +1086,20 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) *out = wxWEB_NAV_ERR_USER_CANCELLED; break; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 case NSURLErrorCannotDecodeRawData: case NSURLErrorCannotDecodeContentData: - case NSURLErrorBadServerResponse: case NSURLErrorCannotParseResponse: +#endif + case NSURLErrorBadServerResponse: *out = wxWEB_NAV_ERR_REQUEST; break; case NSURLErrorUserAuthenticationRequired: case NSURLErrorSecureConnectionFailed: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 case NSURLErrorClientCertificateRequired: +#endif *out = wxWEB_NAV_ERR_AUTH; break; @@ -1106,18 +1134,18 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) if (webKitWindow && frame == [sender mainFrame]){ NSString *url = [[[[frame dataSource] request] URL] absoluteString]; - wxWebNavigationError type; + wxWebViewNavigationError type; wxString description = nsErrorToWxHtmlError(error, &type); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_ERROR, - webKitWindow->GetId(), - wxStringWithNSString( url ), - wxEmptyString, false); - thisEvent.SetString(description); - thisEvent.SetInt(type); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, + webKitWindow->GetId(), + wxStringWithNSString( url ), + wxEmptyString); + event.SetString(description); + event.SetInt(type); if (webKitWindow && webKitWindow->GetEventHandler()) { - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); } } } @@ -1132,17 +1160,17 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) NSString *url = [[[[frame provisionalDataSource] request] URL] absoluteString]; - wxWebNavigationError type; + wxWebViewNavigationError type; wxString description = nsErrorToWxHtmlError(error, &type); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_ERROR, - webKitWindow->GetId(), - wxStringWithNSString( url ), - wxEmptyString, false); - thisEvent.SetString(description); - thisEvent.SetInt(type); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, + webKitWindow->GetId(), + wxStringWithNSString( url ), + wxEmptyString); + event.SetString(description); + event.SetInt(type); if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); } } @@ -1150,19 +1178,19 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) forFrame:(WebFrame *)frame { wxString target = wxStringWithNSString([frame name]); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED, - webKitWindow->GetId(), - webKitWindow->GetCurrentURL(), - target, true); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED, + webKitWindow->GetId(), + webKitWindow->GetCurrentURL(), + target); - thisEvent.SetString(wxStringWithNSString(title)); + event.SetString(wxStringWithNSString(title)); if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); } @end -@implementation MyPolicyDelegate +@implementation WebViewPolicyDelegate - initWithWxWindow: (wxWebViewWebKit*)inWindow { @@ -1182,14 +1210,14 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) webKitWindow->m_busy = true; NSString *url = [[request URL] absoluteString]; wxString target = wxStringWithNSString([frame name]); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, - webKitWindow->GetId(), - wxStringWithNSString( url ), target, true); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, + webKitWindow->GetId(), + wxStringWithNSString( url ), target); if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); - if (thisEvent.IsVetoed()) + if (!event.IsAllowed()) { webKitWindow->m_busy = false; [listener ignore]; @@ -1209,15 +1237,82 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) wxUnusedVar(actionInformation); NSString *url = [[request URL] absoluteString]; - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW, - webKitWindow->GetId(), - wxStringWithNSString( url ), "", true); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW, + webKitWindow->GetId(), + wxStringWithNSString( url ), ""); if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); [listener ignore]; } @end -#endif //wxUSE_WEBVIEW_WEBKIT +@implementation WebViewCustomProtocol + ++ (BOOL)canInitWithRequest:(NSURLRequest *)request +{ + NSString *scheme = [[request URL] scheme]; + + wxStringToWebHandlerMap::const_iterator it; + for( it = g_stringHandlerMap.begin(); it != g_stringHandlerMap.end(); ++it ) + { + if(it->first.IsSameAs(wxStringWithNSString(scheme))) + { + return YES; + } + } + + return NO; +} + ++ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request +{ + //We don't do any processing here as the wxWebViewHandler classes do it + return request; +} + +- (void)startLoading +{ + NSURLRequest *request = [self request]; + NSString* path = [[request URL] absoluteString]; + + wxString wxpath = wxStringWithNSString(path); + wxString scheme = wxStringWithNSString([[request URL] scheme]); + wxFSFile* file = g_stringHandlerMap[scheme]->GetFile(wxpath); + size_t length = file->GetStream()->GetLength(); + + + NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[request URL] + MIMEType:wxNSStringWithWxString(file->GetMimeType()) + 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]; + + id client = [self client]; + + //We do not support caching anything yet + [client URLProtocol:self didReceiveResponse:response + cacheStoragePolicy:NSURLCacheStorageNotAllowed]; + + //Set the data + [client URLProtocol:self didLoadData:data]; + + //Notify that we have finished + [client URLProtocolDidFinishLoading:self]; + + [response release]; +} + +- (void)stopLoading +{ + +} + +@end + +#endif //wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT