Fix custom scheme handling in wxWebView WebKit2 implementation
The custom scheme handling implementation had been inherited from the original WebKit1 implementation. It attempted to intercept navigation and resource load requests and then inject the resources. It seems that this method doesn't work in WebKit2, but fortunately, there is native support in WebKit2 for custom URI schemes through the webkit_web_context_register_uri_scheme() API. Also extend wxGtkError to allow creating it from an existing GError object as a side-effect of these changes. See https://github.com/wxWidgets/wxWidgets/pull/716
This commit is contained in:
committed by
Vadim Zeitlin
parent
aaf58e2b49
commit
1f2173b9be
@@ -209,6 +209,7 @@ wxGTK:
|
||||
- Implement ShowPosition() for single-line wxTextCtrl.
|
||||
- Improve wx{Client,Paint,Screen,Window}DC::GetPPI() (GTK+ 3).
|
||||
- Suppress focus loss events for wxChoice and wxComboBox on opening popup.
|
||||
- Make custom URI schemes work WebKit2-based wxWebView (Scott Talbert).
|
||||
|
||||
wxMSW:
|
||||
|
||||
|
@@ -21,6 +21,7 @@ class wxGtkError
|
||||
{
|
||||
public:
|
||||
wxGtkError() { m_error = NULL; }
|
||||
explicit wxGtkError(GError* error) { m_error = error; }
|
||||
~wxGtkError() { if ( m_error ) g_error_free(m_error); }
|
||||
|
||||
GError** Out()
|
||||
@@ -37,6 +38,11 @@ public:
|
||||
return m_error != NULL;
|
||||
}
|
||||
|
||||
operator GError*() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
wxString GetMessage() const
|
||||
{
|
||||
return wxString::FromUTF8(m_error->message);
|
||||
|
@@ -67,7 +67,7 @@ wxgtk_webview_webkit_load_changed(GtkWidget *,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wxgtk_webview_webkit_navigation(WebKitWebView *web_view,
|
||||
wxgtk_webview_webkit_navigation(WebKitWebView *,
|
||||
WebKitPolicyDecision *decision,
|
||||
wxWebViewWebKit *webKitCtrl)
|
||||
{
|
||||
@@ -93,16 +93,6 @@ wxgtk_webview_webkit_navigation(WebKitWebView *web_view,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if(webKitCtrl->m_guard)
|
||||
{
|
||||
webKitCtrl->m_guard = false;
|
||||
//We set this to make sure that we don't try to load the page again from
|
||||
//the resource request callback
|
||||
webKitCtrl->m_vfsurl = webkit_web_view_get_uri(web_view);
|
||||
webkit_policy_decision_use(decision);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
webKitCtrl->m_busy = true;
|
||||
|
||||
wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATING,
|
||||
@@ -120,32 +110,6 @@ wxgtk_webview_webkit_navigation(WebKitWebView *web_view,
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString wxuri = uri;
|
||||
wxSharedPtr<wxWebViewHandler> handler;
|
||||
wxVector<wxSharedPtr<wxWebViewHandler> > handlers = webKitCtrl->GetHandlers();
|
||||
//We are not vetoed so see if we match one of the additional handlers
|
||||
for(wxVector<wxSharedPtr<wxWebViewHandler> >::iterator it = handlers.begin();
|
||||
it != handlers.end(); ++it)
|
||||
{
|
||||
if(wxuri.substr(0, (*it)->GetName().length()) == (*it)->GetName())
|
||||
{
|
||||
handler = (*it);
|
||||
}
|
||||
}
|
||||
//If we found a handler we can then use it to load the file directly
|
||||
//ourselves
|
||||
if(handler)
|
||||
{
|
||||
webKitCtrl->m_guard = true;
|
||||
wxFSFile* file = handler->GetFile(wxuri);
|
||||
if(file)
|
||||
{
|
||||
webKitCtrl->SetPage(*file->GetStream(), wxuri);
|
||||
}
|
||||
//We need to throw some sort of error here if file is NULL
|
||||
webkit_policy_decision_ignore(decision);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -325,49 +289,53 @@ wxgtk_webview_webkit_title_changed(GtkWidget* widget,
|
||||
}
|
||||
|
||||
static void
|
||||
wxgtk_webview_webkit_resource_req(WebKitWebView *,
|
||||
WebKitWebResource *,
|
||||
WebKitURIRequest *request,
|
||||
wxWebViewWebKit *webKitCtrl)
|
||||
wxgtk_webview_webkit_uri_scheme_request_cb(WebKitURISchemeRequest *request,
|
||||
wxWebViewWebKit *webKitCtrl)
|
||||
{
|
||||
wxString uri = webkit_uri_request_get_uri(request);
|
||||
const wxString scheme = wxString::FromUTF8(webkit_uri_scheme_request_get_scheme(request));
|
||||
|
||||
wxSharedPtr<wxWebViewHandler> handler;
|
||||
wxVector<wxSharedPtr<wxWebViewHandler> > handlers = webKitCtrl->GetHandlers();
|
||||
|
||||
//We are not vetoed so see if we match one of the additional handlers
|
||||
for(wxVector<wxSharedPtr<wxWebViewHandler> >::iterator it = handlers.begin();
|
||||
it != handlers.end(); ++it)
|
||||
{
|
||||
if(uri.substr(0, (*it)->GetName().length()) == (*it)->GetName())
|
||||
if(scheme == (*it)->GetName())
|
||||
{
|
||||
handler = (*it);
|
||||
}
|
||||
}
|
||||
//If we found a handler we can then use it to load the file directly
|
||||
//ourselves
|
||||
|
||||
if(handler)
|
||||
{
|
||||
//If it is requsting the page itself then return as we have already
|
||||
//loaded it from the archive
|
||||
if(webKitCtrl->m_vfsurl == uri)
|
||||
return;
|
||||
const wxString uri = wxString::FromUTF8(webkit_uri_scheme_request_get_uri(request));
|
||||
|
||||
wxFSFile* file = handler->GetFile(uri);
|
||||
if(file)
|
||||
{
|
||||
//We load the data into a data url to save it being written out again
|
||||
size_t size = file->GetStream()->GetLength();
|
||||
char *buffer = new char[size];
|
||||
file->GetStream()->Read(buffer, size);
|
||||
wxString data = wxBase64Encode(buffer, size);
|
||||
delete[] buffer;
|
||||
gint64 length = file->GetStream()->GetLength();
|
||||
guint8 *data = g_new(guint8, length);
|
||||
file->GetStream()->Read(data, length);
|
||||
GInputStream *stream = g_memory_input_stream_new_from_data(data,
|
||||
length,
|
||||
g_free);
|
||||
wxString mime = file->GetMimeType();
|
||||
wxString path = "data:" + mime + ";base64," + data;
|
||||
//Then we can redirect the call
|
||||
webkit_uri_request_set_uri(request, path.utf8_str());
|
||||
webkit_uri_scheme_request_finish(request, stream, length, mime.utf8_str());
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
wxGtkError error(g_error_new(WEBKIT_NETWORK_ERROR,
|
||||
WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST,
|
||||
"File not found: %s", uri.utf8_str().data()));
|
||||
webkit_uri_scheme_request_finish_error(request, error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxGtkError error(g_error_new(WEBKIT_NETWORK_ERROR,
|
||||
WEBKIT_NETWORK_ERROR_UNKNOWN_PROTOCOL,
|
||||
"Unknown scheme: %s", scheme.utf8_str().data()));
|
||||
webkit_uri_scheme_request_finish_error(request, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,38 +537,35 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
|
||||
}
|
||||
|
||||
SetupWebExtensionServer();
|
||||
g_signal_connect_after(webkit_web_context_get_default(),
|
||||
"initialize-web-extensions",
|
||||
G_CALLBACK(wxgtk_initialize_web_extensions),
|
||||
m_dbusServer);
|
||||
g_signal_connect(webkit_web_context_get_default(),
|
||||
"initialize-web-extensions",
|
||||
G_CALLBACK(wxgtk_initialize_web_extensions),
|
||||
m_dbusServer);
|
||||
|
||||
m_web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
|
||||
GTKCreateScrolledWindowWith(GTK_WIDGET(m_web_view));
|
||||
g_object_ref(m_widget);
|
||||
|
||||
g_signal_connect_after(m_web_view, "decide-policy",
|
||||
G_CALLBACK(wxgtk_webview_webkit_decide_policy),
|
||||
this);
|
||||
g_signal_connect(m_web_view, "decide-policy",
|
||||
G_CALLBACK(wxgtk_webview_webkit_decide_policy),
|
||||
this);
|
||||
|
||||
g_signal_connect_after(m_web_view, "load-failed",
|
||||
G_CALLBACK(wxgtk_webview_webkit_load_failed), this);
|
||||
g_signal_connect(m_web_view, "load-failed",
|
||||
G_CALLBACK(wxgtk_webview_webkit_load_failed), this);
|
||||
|
||||
g_signal_connect_after(m_web_view, "notify::title",
|
||||
G_CALLBACK(wxgtk_webview_webkit_title_changed), this);
|
||||
g_signal_connect(m_web_view, "notify::title",
|
||||
G_CALLBACK(wxgtk_webview_webkit_title_changed), this);
|
||||
|
||||
g_signal_connect_after(m_web_view, "resource-load-started",
|
||||
G_CALLBACK(wxgtk_webview_webkit_resource_req), this);
|
||||
g_signal_connect(m_web_view, "context-menu",
|
||||
G_CALLBACK(wxgtk_webview_webkit_context_menu), this);
|
||||
|
||||
g_signal_connect_after(m_web_view, "context-menu",
|
||||
G_CALLBACK(wxgtk_webview_webkit_context_menu), this);
|
||||
|
||||
g_signal_connect_after(m_web_view, "create",
|
||||
G_CALLBACK(wxgtk_webview_webkit_create_webview), this);
|
||||
g_signal_connect(m_web_view, "create",
|
||||
G_CALLBACK(wxgtk_webview_webkit_create_webview), this);
|
||||
|
||||
WebKitFindController* findctrl = webkit_web_view_get_find_controller(m_web_view);
|
||||
g_signal_connect_after(findctrl, "counted-matches",
|
||||
G_CALLBACK(wxgtk_webview_webkit_counted_matches),
|
||||
&m_findCount);
|
||||
g_signal_connect(findctrl, "counted-matches",
|
||||
G_CALLBACK(wxgtk_webview_webkit_counted_matches),
|
||||
&m_findCount);
|
||||
|
||||
m_parent->DoAddChild( this );
|
||||
|
||||
@@ -610,9 +575,9 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
|
||||
webkit_web_view_load_uri(m_web_view, url.utf8_str());
|
||||
|
||||
// last to avoid getting signal too early
|
||||
g_signal_connect_after(m_web_view, "load-changed",
|
||||
G_CALLBACK(wxgtk_webview_webkit_load_changed),
|
||||
this);
|
||||
g_signal_connect(m_web_view, "load-changed",
|
||||
G_CALLBACK(wxgtk_webview_webkit_load_changed),
|
||||
this);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1279,6 +1244,10 @@ bool wxWebViewWebKit::RunScript(const wxString& javascript, wxString* output)
|
||||
void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
|
||||
{
|
||||
m_handlerList.push_back(handler);
|
||||
WebKitWebContext* context = webkit_web_context_get_default();
|
||||
webkit_web_context_register_uri_scheme(context, handler->GetName().utf8_str(),
|
||||
(WebKitURISchemeRequestCallback)wxgtk_webview_webkit_uri_scheme_request_cb,
|
||||
this, NULL);
|
||||
}
|
||||
|
||||
void wxWebViewWebKit::EnableContextMenu(bool enable)
|
||||
|
Reference in New Issue
Block a user