2011-09-28 Carlos Garcia Campos <cgarcia@igalia.com>
+ [GTK] Loader client implementation for WebKit2 GTK+ API
+ https://bugs.webkit.org/show_bug.cgi?id=68085
+
+ Reviewed by Martin Robinson.
+
+ Adds a new object, WebKitWebLoaderClient, that emits signals for
+ every page loader callback.
+
+ * GNUmakefile.am: Add new files to compilation.
+ * UIProcess/API/gtk/WebKitWebLoaderClient.cpp: Added.
+ (didStartProvisionalLoadForFrame):
+ (didReceiveServerRedirectForProvisionalLoadForFrame):
+ (didFailProvisionalLoadWithErrorForFrame):
+ (didCommitLoadForFrame):
+ (didFinishLoadForFrame):
+ (didFailLoadWithErrorForFrame):
+ (webkitWebLoaderClientConstructed):
+ (webkitWebLoaderClientSetProperty):
+ (webkitWebLoaderClientGetProperty):
+ (webkit_web_loader_client_init):
+ (webkit_web_loader_client_class_init):
+ * UIProcess/API/gtk/WebKitWebLoaderClient.h: Added.
+ * UIProcess/API/gtk/WebKitWebView.cpp:
+ (webkitWebViewConstructed): Create the loader client for the view.
+ (webkit_web_view_init):
+ (webkit_web_view_get_loader_client): Get the current loader client.
+ (webkit_web_view_set_loader_client): Set a new loader client.
+ * UIProcess/API/gtk/WebKitWebView.h:
+ * UIProcess/API/gtk/tests/testloading.c: Added.
+ (serverCallback):
+ (webLoadingFixtureSetup):
+ (webLoadingFixtureTeardown):
+ (getURIForPath):
+ (loadStatusProvisionalLoadStarted):
+ (loadStatusProvisionalLoadReceivedServerRedirect):
+ (loadStatusProvisionalLoadFailed):
+ (loadStatusLoadCommitted):
+ (loadStatusLoadFinished):
+ (loadStatusLoadFailed):
+ (testLoadingStatus):
+ (loadErrorProvisionalLoadStarted):
+ (loadErrorProvisionalLoadFailed):
+ (loadErrorLoadFinished):
+ (testLoadingError):
+ (main):
+ * UIProcess/API/gtk/webkit2marshal.list: Added.
+
+2011-09-28 Carlos Garcia Campos <cgarcia@igalia.com>
+
[GTK] Add WebKitError to GTK+ WebKit2 API
https://bugs.webkit.org/show_bug.cgi?id=68508
webkit2gtk_headers = \
$(WebKit2)/UIProcess/API/gtk/WebKitError.h \
$(WebKit2)/UIProcess/API/gtk/WebKitWebContext.h \
+ $(WebKit2)/UIProcess/API/gtk/WebKitWebLoaderClient.h \
$(WebKit2)/UIProcess/API/gtk/WebKitWebView.h \
$(WebKit2)/UIProcess/API/gtk/WebKitWebViewBase.h \
$(WebKit2)/UIProcess/API/gtk/webkit2.h
DerivedSources/WebKit2/WebProcessMessages.h \
DerivedSources/WebKit2/WebProcessProxyMessageReceiver.cpp \
DerivedSources/WebKit2/WebProcessProxyMessages.h
+
BUILT_SOURCES += $(webkit2_built_sources)
-nodist_libwebkit2gtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES =$(webkit2_built_sources)
+
+webkit2gtk_built_sources = \
+ DerivedSources/WebKit2/webkit2gtk/webkit2/WebKitEnumTypes.cpp \
+ DerivedSources/WebKit2/webkit2gtk/webkit2/WebKitEnumTypes.h \
+ DerivedSources/WebKit2/webkit2gtk/webkit2/WebKitMarshal.cpp \
+ DerivedSources/WebKit2/webkit2gtk/webkit2/WebKitMarshal.h
+
+BUILT_SOURCES += $(webkit2gtk_built_sources)
+
+nodist_libwebkit2gtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES = \
+ $(webkit2_built_sources) \
+ $(webkit2gtk_built_sources)
libwebkit2gtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES = \
Source/WebKit2/Platform/CoreIPC/ArgumentCoder.h \
Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h \
Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp \
Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h \
+ Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.h \
+ Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.cpp \
Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h \
Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp \
Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.h \
-I$(top_builddir)/DerivedSources/WebKit2/include \
-I$(top_builddir)/DerivedSources/WebKit2/webkit2gtk \
-I$(top_builddir)/DerivedSources/WebKit2/webkit2gtk/include \
+ -I$(top_builddir)/DerivedSources/WebKit2/webkit2gtk/webkit2 \
-I$(top_builddir)/DerivedSources/WebKit2/include/JavaScriptCore \
-I$(top_builddir)/DerivedSources/WebKit2/include/WebCore \
-I$(top_builddir)/DerivedSources/WebKit2/include/WebKit2 \
&& cp xgen-gtc $@ \
&& rm -f xgen-gtc
+WEBKIT2_MARSHAL_LIST = $(WebKit2)/UIProcess/API/gtk/webkit2marshal.list
-BUILT_SOURCES += \
- $(GENSOURCES_WEBKIT2)/webkit2gtk/webkit2/WebKitEnumTypes.cpp \
- $(GENSOURCES_WEBKIT2)/webkit2gtk/webkit2/WebKitEnumTypes.h
+$(GENSOURCES_WEBKIT2)/webkit2gtk/webkit2/WebKitMarshal.cpp: stamp-webkit2marshal.cpp
+ @true
+$(GENSOURCES_WEBKIT2)/webkit2gtk/webkit2/WebKitMarshal.h: stamp-webkit2marshal.h
+ @true
+
+stamp-webkit2marshal.cpp: $(WEBKIT2_MARSHAL_LIST)
+ $(AM_V_GEN) echo "extern \"C\" {" > $(webkit2gtk_built_headers_dir)/WebKitMarshal.cpp && \
+ $(GLIB_GENMARSHAL) --prefix=webkit_marshal $(WEBKIT2_MARSHAL_LIST) --body >> $(webkit2gtk_built_headers_dir)/WebKitMarshal.cpp && \
+ echo '}' >> $(webkit2gtk_built_headers_dir)/WebKitMarshal.cpp && \
+ echo timestamp > $(@F)
+
+stamp-webkit2marshal.h: $(WEBKIT2_MARSHAL_LIST)
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=webkit_marshal $(WEBKIT2_MARSHAL_LIST) --header > $(webkit2gtk_built_headers_dir)/WebKitMarshal.h && \
+ echo timestamp > $(@F)
CLEANFILES += \
$(BUILT_SOURCES) \
$(top_builddir)/stamp-webkit2enumtypes \
+ $(top_builddir)/stamp-webkit2marshal.cpp \
+ $(top_builddir)/stamp-webkit2marshal.h \
$(top_builddir)/Programs/WebKitWebProcess
DISTCLEANFILES += \
# Unit tests
TEST_PROGS += \
Programs/unittests/webkit2/testwebcontext \
- Programs/unittests/webkit2/testwebview
+ Programs/unittests/webkit2/testwebview \
+ Programs/unittests/webkit2/testloading
noinst_PROGRAMS += $(TEST_PROGS)
webkit2_tests_cflags = \
Programs_unittests_webkit2_testwebview_LDADD = $(webkit2_tests_ldadd)
Programs_unittests_webkit2_testwebview_LDFLAGS = $(webkit2_tests_ldflags)
+Programs_unittests_webkit2_testloading_SOURCES = Source/WebKit2/UIProcess/API/gtk/tests/testloading.c
+Programs_unittests_webkit2_testloading_CFLAGS = $(webkit2_tests_cflags)
+Programs_unittests_webkit2_testloading_LDADD = $(webkit2_tests_ldadd)
+Programs_unittests_webkit2_testloading_LDFLAGS = $(webkit2_tests_ldflags)
+
# WebKitWebProcess
libexec_PROGRAMS += \
Programs/WebKitWebProcess
--- /dev/null
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "WebKitWebLoaderClient.h"
+
+#include "WebKitMarshal.h"
+#include "WebKitPrivate.h"
+#include "WebKitWebView.h"
+#include "WebKitWebViewBasePrivate.h"
+#include <wtf/gobject/GOwnPtr.h>
+#include <wtf/gobject/GRefPtr.h>
+#include <wtf/text/CString.h>
+
+using namespace WebCore;
+
+enum {
+ PROVISIONAL_LOAD_STARTED,
+ PROVISIONAL_LOAD_RECEIVED_SERVER_REDIRECT,
+ PROVISIONAL_LOAD_FAILED,
+
+ LOAD_COMMITTED,
+ LOAD_FINISHED,
+ LOAD_FAILED,
+
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+
+ PROP_WEB_VIEW
+};
+
+struct _WebKitWebLoaderClientPrivate {
+ GRefPtr<WebKitWebView> view;
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE(WebKitWebLoaderClient, webkit_web_loader_client, G_TYPE_OBJECT)
+
+static void didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
+{
+ if (!WKFrameIsMainFrame(frame))
+ return;
+
+ gboolean returnValue;
+ g_signal_emit(WEBKIT_WEB_LOADER_CLIENT(clientInfo), signals[PROVISIONAL_LOAD_STARTED], 0, &returnValue);
+}
+
+static void didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
+{
+ if (!WKFrameIsMainFrame(frame))
+ return;
+
+ gboolean returnValue;
+ g_signal_emit(WEBKIT_WEB_LOADER_CLIENT(clientInfo), signals[PROVISIONAL_LOAD_RECEIVED_SERVER_REDIRECT], 0, &returnValue);
+}
+
+static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void* clientInfo)
+{
+ if (!WKFrameIsMainFrame(frame))
+ return;
+
+ const ResourceError& resourceError = toImpl(error)->platformError();
+ GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()),
+ resourceError.errorCode(),
+ resourceError.localizedDescription().utf8().data()));
+ gboolean returnValue;
+ g_signal_emit(WEBKIT_WEB_LOADER_CLIENT(clientInfo), signals[PROVISIONAL_LOAD_FAILED], 0, webError.get(), &returnValue);
+}
+
+static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
+{
+ if (!WKFrameIsMainFrame(frame))
+ return;
+
+ gboolean returnValue;
+ g_signal_emit(WEBKIT_WEB_LOADER_CLIENT(clientInfo), signals[LOAD_COMMITTED], 0, &returnValue);
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
+{
+ if (!WKFrameIsMainFrame(frame))
+ return;
+
+ gboolean returnValue;
+ g_signal_emit(WEBKIT_WEB_LOADER_CLIENT(clientInfo), signals[LOAD_FINISHED], 0, &returnValue);
+}
+
+static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef, const void* clientInfo)
+{
+ if (!WKFrameIsMainFrame(frame))
+ return;
+
+ const ResourceError& resourceError = toImpl(error)->platformError();
+ GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()),
+ resourceError.errorCode(),
+ resourceError.localizedDescription().utf8().data()));
+ gboolean returnValue;
+ g_signal_emit(WEBKIT_WEB_LOADER_CLIENT(clientInfo), signals[LOAD_FAILED], 0, webError.get(), &returnValue);
+}
+
+static void webkitWebLoaderClientConstructed(GObject* object)
+{
+ WebKitWebLoaderClient* client = WEBKIT_WEB_LOADER_CLIENT(object);
+ WebKitWebLoaderClientPrivate* priv = client->priv;
+
+ WKPageLoaderClient loaderClient = {
+ kWKPageLoaderClientCurrentVersion,
+ client, // clientInfo
+ didStartProvisionalLoadForFrame,
+ didReceiveServerRedirectForProvisionalLoadForFrame,
+ didFailProvisionalLoadWithErrorForFrame,
+ didCommitLoadForFrame,
+ 0, // didFinishDocumentLoadForFrame
+ didFinishLoadForFrame,
+ didFailLoadWithErrorForFrame,
+ 0, // didSameDocumentNavigationForFrame
+ 0, // didReceiveTitleForFrame
+ 0, // didFirstLayoutForFrame
+ 0, // didFirstVisuallyNonEmptyLayoutForFrame
+ 0, // didRemoveFrameFromHierarchy
+ 0, // didDisplayInsecureContentForFrame
+ 0, // didRunInsecureContentForFrame
+ 0, // canAuthenticateAgainstProtectionSpaceInFrame
+ 0, // didReceiveAuthenticationChallengeInFrame
+ 0, // didStartProgress
+ 0, // didChangeProgress
+ 0, // didFinishProgress
+ 0, // didBecomeUnresponsive
+ 0, // didBecomeResponsive
+ 0, // processDidCrash
+ 0, // didChangeBackForwardList
+ 0, // shouldGoToBackForwardListItem
+ 0 // didFailToInitializePlugin
+ };
+ WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(priv->view.get()));
+ WKPageSetPageLoaderClient(toAPI(page), &loaderClient);
+}
+
+static void webkitWebLoaderClientSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec)
+{
+ WebKitWebLoaderClient* client = WEBKIT_WEB_LOADER_CLIENT(object);
+
+ switch (propId) {
+ case PROP_WEB_VIEW:
+ client->priv->view = adoptGRef(WEBKIT_WEB_VIEW(g_value_dup_object(value)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
+ }
+}
+
+static void webkitWebLoaderClientGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
+{
+ WebKitWebLoaderClient* client = WEBKIT_WEB_LOADER_CLIENT(object);
+
+ switch (propId) {
+ case PROP_WEB_VIEW:
+ g_value_set_object(value, client->priv->view.get());
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
+ }
+}
+
+static void webkit_web_loader_client_init(WebKitWebLoaderClient* client)
+{
+ WebKitWebLoaderClientPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(client, WEBKIT_TYPE_WEB_LOADER_CLIENT, WebKitWebLoaderClientPrivate);
+ client->priv = priv;
+ new (priv) WebKitWebLoaderClientPrivate();
+}
+
+static void webkit_web_loader_client_class_init(WebKitWebLoaderClientClass* clientClass)
+{
+ GObjectClass* objectClass = G_OBJECT_CLASS(clientClass);
+
+ objectClass->set_property = webkitWebLoaderClientSetProperty;
+ objectClass->get_property = webkitWebLoaderClientGetProperty;
+ objectClass->constructed = webkitWebLoaderClientConstructed;
+
+ /**
+ * WebKitWebView:web-view:
+ *
+ * The #WebKitWebView of the loader client.
+ */
+ g_object_class_install_property(objectClass,
+ PROP_WEB_VIEW,
+ g_param_spec_object("web-view",
+ "Web View",
+ "The web view for the loader client",
+ WEBKIT_TYPE_WEB_VIEW,
+ static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
+
+ /**
+ * WebKitWebLoaderClient::provisional-load-started:
+ * @loader_client: the #WebKitWebLoader
+ *
+ * This signal is emitted when new load request is made.
+ * No data has been received yet, empty structures have
+ * been allocated to perform the load; the load may still
+ * fail for transport issues such as not being able to
+ * resolve a name, or connect to a port.
+ *
+ * Returns: %TRUE to stop other handlers from being invoked for the event.
+ * %FALSE to propagate the event further.
+ */
+ signals[PROVISIONAL_LOAD_STARTED] =
+ g_signal_new("provisional-load-started",
+ G_TYPE_FROM_CLASS(objectClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitWebLoaderClientClass, provisional_load_started),
+ g_signal_accumulator_true_handled, NULL,
+ webkit_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN, 0,
+ G_TYPE_NONE);
+
+ /**
+ * WebKitWebLoaderClient::provisional-load-received-server-redirect:
+ * @loader_client: the #WebKitWebLoader
+ *
+ * This signal is emitted when a provisional data source
+ * receives a server redirect.
+ *
+ * This signal is emitted after #WebKitWebLoaderClient::provisional-load-started.
+ *
+ * Returns: %TRUE to stop other handlers from being invoked for the event.
+ * %FALSE to propagate the event further.
+ */
+ signals[PROVISIONAL_LOAD_RECEIVED_SERVER_REDIRECT] =
+ g_signal_new("provisional-load-received-server-redirect",
+ G_TYPE_FROM_CLASS(objectClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitWebLoaderClientClass, provisional_load_received_server_redirect),
+ g_signal_accumulator_true_handled, NULL,
+ webkit_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN, 0,
+ G_TYPE_NONE);
+
+ /**
+ * WebKitWebLoaderClient::provisional-load-failed:
+ * @loader_client: the #WebKitWebLoader
+ * @error: the #GError that was triggered
+ *
+ * This signal is emitted when an error occurs when starting to
+ * load data for a page. By default, if the signal is not handled,
+ * a stock error page will be displayed. You need to handle the signal
+ * if you want to provide your own error page. This signal finishes the
+ * load so no other signals will be emitted after this one.
+ *
+ * This signal is emitted after #WebKitWebLoaderClient::provisional-load-started.
+ *
+ * Returns: %TRUE to stop other handlers from being invoked for the event.
+ * %FALSE to propagate the event further.
+ */
+ signals[PROVISIONAL_LOAD_FAILED] =
+ g_signal_new("provisional-load-failed",
+ G_TYPE_FROM_CLASS(objectClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitWebLoaderClientClass, provisional_load_failed),
+ g_signal_accumulator_true_handled, NULL,
+ webkit_marshal_BOOLEAN__POINTER,
+ G_TYPE_BOOLEAN, 1,
+ G_TYPE_POINTER);
+
+ /**
+ * WebKitWebLoaderClient::load-committed:
+ * @loader_client: the #WebKitWebLoader
+ *
+ * This signal is emitted when content starts arriving for a page load.
+ * The necessary transport requirements are stabilished, and the
+ * load is being performed.
+ *
+ * This signal is emitted after #WebKitWebLoaderClient::provisional-load-started.
+ *
+ * Returns: %TRUE to stop other handlers from being invoked for the event.
+ * %FALSE to propagate the event further.
+ */
+ signals[LOAD_COMMITTED] =
+ g_signal_new("load-committed",
+ G_TYPE_FROM_CLASS(objectClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitWebLoaderClientClass, load_committed),
+ g_signal_accumulator_true_handled, NULL,
+ webkit_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN, 0,
+ G_TYPE_NONE);
+ /**
+ * WebKitWebLoaderClient::load-finished:
+ * @loader_client: the #WebKitWebLoader
+ *
+ * This signal is emitted when a page load completes, that is, when all
+ * the resources are done loading with no error. In case of errors
+ * during loading, the load finishes when either
+ * #WebKitWebLoaderClient::provisional-load-failed or #WebKitWebLoaderClient::load-failed
+ * are emitted.
+ *
+ * This signal is emitted after #WebKitWebLoaderClient::load-committed.
+ *
+ * Returns: %TRUE to stop other handlers from being invoked for the event.
+ * %FALSE to propagate the event further.
+ */
+ signals[LOAD_FINISHED] =
+ g_signal_new("load-finished",
+ G_TYPE_FROM_CLASS(objectClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitWebLoaderClientClass, load_finished),
+ g_signal_accumulator_true_handled, NULL,
+ webkit_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN, 0,
+ G_TYPE_NONE);
+
+ /**
+ * WebKitWebLoaderClient::load-failed:
+ * @loader_client: the #WebKitWebLoader
+ * @error: the #GError that was triggered
+ *
+ * This signal is emitted when an error occurs loading a committed data source.
+ * By default, if the signal is not handled, a stock error page will be displayed.
+ * You need to handle the signal if you want to provide your own error page. This
+ * signal finishes the load so no other signals will be emitted after this one.
+ *
+ * This signal is emitted after #WebKitWebLoaderClient::load-committed.
+ *
+ * Returns: %TRUE to stop other handlers from being invoked for the event.
+ * %FALSE to propagate the event further.
+ */
+ signals[LOAD_FAILED] =
+ g_signal_new("load-failed",
+ G_TYPE_FROM_CLASS(objectClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitWebLoaderClientClass, load_failed),
+ g_signal_accumulator_true_handled, NULL,
+ webkit_marshal_BOOLEAN__POINTER,
+ G_TYPE_BOOLEAN, 1,
+ G_TYPE_POINTER);
+
+ g_type_class_add_private(clientClass, sizeof(WebKitWebLoaderClientPrivate));
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef WebKitWebLoaderClient_h
+#define WebKitWebLoaderClient_h
+
+#include <WebKit2/WKBase.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_WEB_LOADER_CLIENT (webkit_web_loader_client_get_type())
+#define WEBKIT_WEB_LOADER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_LOADER_CLIENT, WebKitWebLoaderClient))
+#define WEBKIT_WEB_LOADER_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_LOADER_CLIENT, WebKitWebLoaderClientClass))
+#define WEBKIT_IS_WEB_LOADER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_WEB_LOADER_CLIENT))
+#define WEBKIT_IS_WEB_LOADER_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_WEB_LOADER_CLIENT))
+#define WEBKIT_WEB_LOADER_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_WEB_LOADER_CLIENT, WebKitWebLoaderClientClass))
+
+typedef struct _WebKitWebLoaderClient WebKitWebLoaderClient;
+typedef struct _WebKitWebLoaderClientClass WebKitWebLoaderClientClass;
+typedef struct _WebKitWebLoaderClientPrivate WebKitWebLoaderClientPrivate;
+
+struct _WebKitWebLoaderClient {
+ GObject parent;
+
+ WebKitWebLoaderClientPrivate *priv;
+};
+
+struct _WebKitWebLoaderClientClass {
+ GObjectClass parent_class;
+
+ /* virtual table */
+ gboolean (* provisional_load_started) (WebKitWebLoaderClient *loader_client);
+ gboolean (* provisional_load_received_server_redirect) (WebKitWebLoaderClient *loader_client);
+ gboolean (* provisional_load_failed) (WebKitWebLoaderClient *loader_client,
+ GError *error);
+ gboolean (* load_committed) (WebKitWebLoaderClient *loader_client);
+ gboolean (* load_finished) (WebKitWebLoaderClient *loader_client);
+ gboolean (* load_failed) (WebKitWebLoaderClient *loader_client,
+ GError *error);
+};
+
+WK_EXPORT GType
+webkit_web_loader_client_get_type (void);
+
+G_END_DECLS
+
+#endif
#include "config.h"
#include "WebKitWebView.h"
-#include "NotImplemented.h"
#include "WebKitWebContextPrivate.h"
+#include "WebKitWebLoaderClient.h"
#include "WebKitWebViewBasePrivate.h"
#include "WebKitPrivate.h"
#include "WebPageProxy.h"
#include <WebKit2/WKBase.h>
#include <WebKit2/WKURL.h>
+#include <wtf/gobject/GRefPtr.h>
+#include <wtf/text/CString.h>
using namespace WebKit;
using namespace WebCore;
struct _WebKitWebViewPrivate {
WebKitWebContext* context;
+
+ GRefPtr<WebKitWebLoaderClient> loaderClient;
};
G_DEFINE_TYPE(WebKitWebView, webkit_web_view, WEBKIT_TYPE_WEB_VIEW_BASE)
static void webkitWebViewConstructed(GObject* object)
{
WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
+ WebKitWebViewPrivate* priv = webView->priv;
+
+ webkitWebViewBaseCreateWebPage(WEBKIT_WEB_VIEW_BASE(webView), webkitWebContextGetWKContext(priv->context), 0);
- webkitWebViewBaseCreateWebPage(WEBKIT_WEB_VIEW_BASE(webView),
- webkitWebContextGetWKContext(webView->priv->context), 0);
+ priv->loaderClient = adoptGRef(WEBKIT_WEB_LOADER_CLIENT(g_object_new(WEBKIT_TYPE_WEB_LOADER_CLIENT, "web-view", webView, NULL)));
}
static void webkitWebViewSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec)
static void webkit_web_view_init(WebKitWebView* webView)
{
- webView->priv = G_TYPE_INSTANCE_GET_PRIVATE(webView, WEBKIT_TYPE_WEB_VIEW, WebKitWebViewPrivate);
+ WebKitWebViewPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(webView, WEBKIT_TYPE_WEB_VIEW, WebKitWebViewPrivate);
+ webView->priv = priv;
+ new (priv) WebKitWebViewPrivate();
}
static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
return webView->priv->context;
}
+/**
+ * webkit_web_view_get_loader_client:
+ * @web_view: a #WebKitWebView
+ *
+ * Returns the #WebKitWebLoaderClient of @web_view. You can use it
+ * to monitor the status of load operations happening on @web_view.
+ *
+ * Returns: (trasnfer-none): the #WebKitWebLoaderClient of @web_view.
+ */
+WebKitWebLoaderClient* webkit_web_view_get_loader_client(WebKitWebView* webView)
+{
+ g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
+
+ return webView->priv->loaderClient.get();
+}
+
+/**
+ * webkit_web_view_set_loader_client:
+ * @web_view: a #WebKitWebView
+ * @loader_client: a #WebKitWebLoaderClient
+ *
+ * Sets the #WebKitWebLoaderClient that the view will use during
+ * load operations.
+ */
+void webkit_web_view_set_loader_client(WebKitWebView* webView, WebKitWebLoaderClient* loaderClient)
+{
+ g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
+ g_return_if_fail(WEBKIT_IS_WEB_LOADER_CLIENT(loaderClient));
+
+ WebKitWebViewPrivate* priv = webView->priv;
+ if (priv->loaderClient.get() == loaderClient)
+ return;
+
+ priv->loaderClient = loaderClient;
+}
+
+/**
+ * webkit_web_view_load_uri:
+ * @web_view: a #WebKitWebView
+ * @uri: an URI string
+ *
+ * Requests loading of the specified URI string.
+ * You can monitor the status of the load operation using the
+ * #WebKitWebLoaderClient of @web_view. See webkit_web_view_get_loader_client().
+ */
void webkit_web_view_load_uri(WebKitWebView* webView, const gchar* uri)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
WKPageLoadURL(toAPI(page), WKURLCreateWithUTF8CString(uri));
}
+/**
+ * webkit_web_view_go_back:
+ * @web_view: a #WebKitWebView
+ *
+ * Loads the previous history item.
+ * You can monitor the status of the load operation using the
+ * #WebKitWebLoaderClient of @web_view. See webkit_web_view_get_loader_client().
+ */
void webkit_web_view_go_back(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
WKPageGoBack(toAPI(page));
}
+/**
+ * webkit_web_view_go_forward:
+ * @web_view: a #WebKitWebView
+ *
+ * Loads the next history item.
+ * You can monitor the status of the load operation using the
+ * #WebKitWebLoaderClient of @web_view. See webkit_web_view_get_loader_client().
+ */
void webkit_web_view_go_forward(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
#define WebKitWebView_h
#include <webkit2/WebKitWebContext.h>
+#include <webkit2/WebKitWebLoaderClient.h>
#include <webkit2/WebKitWebViewBase.h>
G_BEGIN_DECLS
};
WK_EXPORT GType
-webkit_web_view_get_type (void);
+webkit_web_view_get_type (void);
WK_EXPORT GtkWidget *
-webkit_web_view_new (void);
+webkit_web_view_new (void);
WK_EXPORT GtkWidget *
-webkit_web_view_new_with_context (WebKitWebContext *context);
+webkit_web_view_new_with_context (WebKitWebContext *context);
WK_EXPORT WebKitWebContext *
-webkit_web_view_get_context (WebKitWebView *web_view);
+webkit_web_view_get_context (WebKitWebView *web_view);
+
+WK_EXPORT WebKitWebLoaderClient *
+webkit_web_view_get_loader_client (WebKitWebView *web_view);
+
+WK_EXPORT void
+webkit_web_view_set_loader_client (WebKitWebView *web_view,
+ WebKitWebLoaderClient *loader_client);
WK_EXPORT void
-webkit_web_view_load_uri (WebKitWebView *webView,
- const gchar *uri);
+webkit_web_view_load_uri (WebKitWebView *web_view,
+ const gchar *uri);
WK_EXPORT void
-webkit_web_view_go_back (WebKitWebView *webView);
+webkit_web_view_go_back (WebKitWebView *web_view);
WK_EXPORT void
-webkit_web_view_go_forward (WebKitWebView *webView);
+webkit_web_view_go_forward (WebKitWebView *web_view);
G_END_DECLS
--- /dev/null
+/*
+ * Copyright (C) 2009, 2010 Gustavo Noronha Silva
+ * Copyright (C) 2009, 2011 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <libsoup/soup.h>
+#include <string.h>
+#include <webkit2/webkit2.h>
+
+/* This string has to be rather big because of the cancelled test - it
+ * looks like soup refuses to send or receive a too small chunk */
+#define HTML_STRING "<html><body>Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!</body></html>"
+
+SoupURI *baseURI;
+
+/* For real request testing */
+static void serverCallback(SoupServer* server, SoupMessage* msg, const char* path, GHashTable* query, SoupClientContext* context, gpointer data)
+{
+ if (msg->method != SOUP_METHOD_GET) {
+ soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
+ return;
+ }
+
+ soup_message_set_status(msg, SOUP_STATUS_OK);
+
+ if (g_str_equal(path, "/")) {
+ soup_message_set_status(msg, SOUP_STATUS_MOVED_PERMANENTLY);
+ soup_message_headers_append(msg->response_headers, "Location", "/test_loading_status");
+ } else if (g_str_equal(path, "/test_loading_status") || g_str_equal(path, "/test_loading_status2"))
+ soup_message_body_append(msg->response_body, SOUP_MEMORY_STATIC, HTML_STRING, strlen(HTML_STRING));
+ else if (g_str_equal(path, "/test_load_error")) {
+ soup_message_set_status(msg, SOUP_STATUS_CANT_CONNECT);
+ } else if (g_str_equal(path, "/test_loading_cancelled")) {
+ soup_message_headers_set_encoding(msg->response_headers, SOUP_ENCODING_CHUNKED);
+ soup_message_body_append(msg->response_body, SOUP_MEMORY_STATIC, HTML_STRING, strlen(HTML_STRING));
+ soup_server_unpause_message(server, msg);
+ return;
+ }
+
+ soup_message_body_complete(msg->response_body);
+}
+
+typedef struct {
+ WebKitWebView *webView;
+ GMainLoop *loop;
+ gboolean hasBeenProvisional;
+ gboolean hasBeenRedirect;
+ gboolean hasBeenCommitted;
+ gboolean hasBeenFinished;
+ gboolean hasBeenFailed;
+} WebLoadingFixture;
+
+static void webLoadingFixtureSetup(WebLoadingFixture *fixture, gconstpointer data)
+{
+ fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ fixture->loop = g_main_loop_new(NULL, TRUE);
+ g_object_ref_sink(fixture->webView);
+ fixture->hasBeenProvisional = FALSE;
+ fixture->hasBeenRedirect = FALSE;
+ fixture->hasBeenCommitted = FALSE;
+ fixture->hasBeenFinished = FALSE;
+ fixture->hasBeenFailed = FALSE;
+}
+
+static void webLoadingFixtureTeardown(WebLoadingFixture *fixture, gconstpointer data)
+{
+ g_object_unref(fixture->webView);
+ g_main_loop_unref(fixture->loop);
+}
+
+static char *getURIForPath(const char* path)
+{
+ SoupURI *uri;
+ char *uriString;
+
+ uri = soup_uri_new_with_base(baseURI, path);
+ uriString = soup_uri_to_string(uri, FALSE);
+ soup_uri_free(uri);
+
+ return uriString;
+}
+
+/* Load Status */
+static gboolean loadStatusProvisionalLoadStarted(WebKitWebLoaderClient *client, WebLoadingFixture *fixture)
+{
+ g_assert(!fixture->hasBeenProvisional);
+ g_assert(!fixture->hasBeenRedirect);
+ g_assert(!fixture->hasBeenCommitted);
+ fixture->hasBeenProvisional = TRUE;
+
+ return TRUE;
+}
+
+static gboolean loadStatusProvisionalLoadReceivedServerRedirect(WebKitWebLoaderClient *client, WebLoadingFixture *fixture)
+{
+ g_assert(fixture->hasBeenProvisional);
+ g_assert(!fixture->hasBeenRedirect);
+ g_assert(!fixture->hasBeenCommitted);
+ fixture->hasBeenRedirect = TRUE;
+
+ return TRUE;
+}
+
+static gboolean loadStatusProvisionalLoadFailed(WebKitWebLoaderClient *client, GError *error, WebLoadingFixture *fixture)
+{
+ g_assert_not_reached();
+ return TRUE;
+}
+
+static gboolean loadStatusLoadCommitted(WebKitWebLoaderClient *client, WebLoadingFixture *fixture)
+{
+ g_assert(fixture->hasBeenProvisional);
+ g_assert(fixture->hasBeenRedirect);
+ g_assert(!fixture->hasBeenCommitted);
+ fixture->hasBeenCommitted = TRUE;
+
+ return TRUE;
+}
+
+static gboolean loadStatusLoadFinished(WebKitWebLoaderClient *client, WebLoadingFixture *fixture)
+{
+ g_assert(fixture->hasBeenProvisional);
+ g_assert(fixture->hasBeenRedirect);
+ g_assert(fixture->hasBeenCommitted);
+ g_assert(!fixture->hasBeenFinished);
+ fixture->hasBeenFinished = TRUE;
+
+ g_main_loop_quit(fixture->loop);
+
+ return TRUE;
+}
+
+static gboolean loadStatusLoadFailed(WebKitWebLoaderClient *client, GError *error, WebLoadingFixture *fixture)
+{
+ g_assert_not_reached();
+ return TRUE;
+}
+
+static void testLoadingStatus(WebLoadingFixture *fixture, gconstpointer data)
+{
+ char *uriString;
+ WebKitWebLoaderClient *client = webkit_web_view_get_loader_client(fixture->webView);
+
+ g_signal_connect(client, "provisional-load-started", G_CALLBACK(loadStatusProvisionalLoadStarted), fixture);
+ g_signal_connect(client, "provisional-load-received-server-redirect", G_CALLBACK(loadStatusProvisionalLoadReceivedServerRedirect), fixture);
+ g_signal_connect(client, "provisional-load-failed", G_CALLBACK(loadStatusProvisionalLoadFailed), fixture);
+ g_signal_connect(client, "load-committed", G_CALLBACK(loadStatusLoadCommitted), fixture);
+ g_signal_connect(client, "load-finished", G_CALLBACK(loadStatusLoadFinished), fixture);
+ g_signal_connect(client, "load-failed", G_CALLBACK(loadStatusLoadFailed), fixture);
+
+ uriString = getURIForPath("/");
+ webkit_web_view_load_uri(fixture->webView, uriString);
+ g_free(uriString);
+
+ g_main_loop_run(fixture->loop);
+
+ g_assert(fixture->hasBeenProvisional);
+ g_assert(fixture->hasBeenRedirect);
+ g_assert(fixture->hasBeenCommitted);
+ g_assert(fixture->hasBeenFinished);
+}
+
+/* Load Error */
+static gboolean loadErrorProvisionalLoadStarted(WebKitWebLoaderClient *client, WebLoadingFixture *fixture)
+{
+ g_assert(!fixture->hasBeenProvisional);
+ fixture->hasBeenProvisional = TRUE;
+
+ return TRUE;
+}
+
+static gboolean loadErrorProvisionalLoadFailed(WebKitWebLoaderClient *client, GError *error, WebLoadingFixture *fixture)
+{
+ g_assert(fixture->hasBeenProvisional);
+ g_assert(!fixture->hasBeenFailed);
+ fixture->hasBeenFailed = TRUE;
+
+ g_assert(error);
+
+ g_main_loop_quit(fixture->loop);
+
+ return TRUE;
+}
+
+static gboolean loadErrorLoadFinished(WebKitWebLoaderClient *client, WebLoadingFixture *fixture)
+{
+ g_assert_not_reached();
+ return TRUE;
+}
+
+static void testLoadingError(WebLoadingFixture *fixture, gconstpointer data)
+{
+ char *uriString;
+ WebKitWebLoaderClient *client = webkit_web_view_get_loader_client(fixture->webView);
+
+ g_signal_connect(client, "provisional-load-started", G_CALLBACK(loadErrorProvisionalLoadStarted), fixture);
+ g_signal_connect(client, "provisional-load-failed", G_CALLBACK(loadErrorProvisionalLoadFailed), fixture);
+ g_signal_connect(client, "load-finished", G_CALLBACK(loadErrorLoadFinished), fixture);
+
+ uriString = getURIForPath("/test_load_error");
+ webkit_web_view_load_uri(fixture->webView, uriString);
+ g_free(uriString);
+
+ g_main_loop_run(fixture->loop);
+
+ g_assert(fixture->hasBeenProvisional);
+ g_assert(fixture->hasBeenFailed);
+}
+
+int main(int argc, char **argv)
+{
+ SoupServer *server;
+
+ g_thread_init(NULL);
+ gtk_test_init(&argc, &argv, NULL);
+
+ g_setenv("WEBKIT_EXEC_PATH", WEBKIT_EXEC_PATH, FALSE);
+
+ server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
+ soup_server_run_async(server);
+
+ soup_server_add_handler(server, NULL, serverCallback, NULL, NULL);
+
+ baseURI = soup_uri_new("http://127.0.0.1/");
+ soup_uri_set_port(baseURI, soup_server_get_port(server));
+
+ g_test_bug_base("https://bugs.webkit.org/");
+ g_test_add("/webkit2/loading/status",
+ WebLoadingFixture, NULL,
+ webLoadingFixtureSetup,
+ testLoadingStatus,
+ webLoadingFixtureTeardown);
+ g_test_add("/webkit2/loading/error",
+ WebLoadingFixture, NULL,
+ webLoadingFixtureSetup,
+ testLoadingError,
+ webLoadingFixtureTeardown);
+
+ return g_test_run();
+}
+
--- /dev/null
+BOOLEAN:POINTER
+BOOLEAN:VOID
+