#include "config.h"
#include "WebKitWebView.h"
#include "WebKitBackForwardListPrivate.h"
#include "WebKitEnumTypes.h"
#include "WebKitError.h"
#include "WebKitFullscreenClient.h"
#include "WebKitHitTestResultPrivate.h"
#include "WebKitJavascriptResultPrivate.h"
#include "WebKitLoaderClient.h"
#include "WebKitMarshal.h"
#include "WebKitPolicyClient.h"
#include "WebKitPrintOperationPrivate.h"
#include "WebKitPrivate.h"
#include "WebKitResourceLoadClient.h"
#include "WebKitScriptDialogPrivate.h"
#include "WebKitSettingsPrivate.h"
#include "WebKitUIClient.h"
#include "WebKitWebContextPrivate.h"
#include "WebKitWebResourcePrivate.h"
#include "WebKitWebViewBasePrivate.h"
#include "WebKitWebViewPrivate.h"
#include "WebKitWindowPropertiesPrivate.h"
#include "WebPageProxy.h"
#include <JavaScriptCore/APICast.h>
#include <WebCore/DragIcon.h>
#include <WebCore/GtkUtilities.h>
#include <glib/gi18n-lib.h>
#include <wtf/gobject/GOwnPtr.h>
#include <wtf/gobject/GRefPtr.h>
#include <wtf/text/CString.h>
using namespace WebKit;
using namespace WebCore;
enum {
LOAD_CHANGED,
LOAD_FAILED,
CREATE,
READY_TO_SHOW,
CLOSE,
SCRIPT_DIALOG,
DECIDE_POLICY,
MOUSE_TARGET_CHANGED,
PRINT_REQUESTED,
RESOURCE_LOAD_STARTED,
ENTER_FULLSCREEN,
LEAVE_FULLSCREEN,
RUN_FILE_CHOOSER,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_WEB_CONTEXT,
PROP_TITLE,
PROP_ESTIMATED_LOAD_PROGRESS,
PROP_URI,
PROP_ZOOM_LEVEL
};
typedef enum {
NotReplacingContent,
WillReplaceContent,
ReplacingContent,
DidReplaceContent
} ReplaceContentStatus;
typedef HashMap<uint64_t, GRefPtr<WebKitWebResource> > LoadingResourcesMap;
typedef HashMap<String, GRefPtr<WebKitWebResource> > ResourcesMap;
struct _WebKitWebViewPrivate {
WebKitWebContext* context;
CString title;
CString customTextEncoding;
double estimatedLoadProgress;
CString activeURI;
ReplaceContentStatus replaceContentStatus;
GRefPtr<WebKitBackForwardList> backForwardList;
GRefPtr<WebKitSettings> settings;
GRefPtr<WebKitWindowProperties> windowProperties;
GRefPtr<WebKitHitTestResult> mouseTargetHitTestResult;
unsigned mouseTargetModifiers;
GRefPtr<WebKitFindController> findController;
JSGlobalContextRef javascriptGlobalContext;
GRefPtr<WebKitWebResource> mainResource;
LoadingResourcesMap loadingResourcesMap;
ResourcesMap subresourcesMap;
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE(WebKitWebView, webkit_web_view, WEBKIT_TYPE_WEB_VIEW_BASE)
static gboolean webkitWebViewLoadFail(WebKitWebView* webView, WebKitLoadEvent, const char* failingURI, GError* error)
{
if (g_error_matches(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)
|| g_error_matches(error, WEBKIT_POLICY_ERROR, WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE)
|| g_error_matches(error, WEBKIT_PLUGIN_ERROR, WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD))
return FALSE;
GOwnPtr<char> htmlString(g_strdup_printf("<html><body>%s</body></html>", error->message));
webkit_web_view_replace_content(webView, htmlString.get(), failingURI, 0);
return TRUE;
}
static GtkWidget* webkitWebViewCreate(WebKitWebView*)
{
return 0;
}
static GtkWidget* webkitWebViewCreateJavaScriptDialog(WebKitWebView* webView, GtkMessageType type, GtkButtonsType buttons, int defaultResponse, const char* message)
{
GtkWidget* parent = gtk_widget_get_toplevel(GTK_WIDGET(webView));
GtkWidget* dialog = gtk_message_dialog_new(widgetIsOnscreenToplevelWindow(parent) ? GTK_WINDOW(parent) : 0,
GTK_DIALOG_DESTROY_WITH_PARENT, type, buttons, "%s", message);
GOwnPtr<char> title(g_strdup_printf("JavaScript - %s", webkit_web_view_get_uri(webView)));
gtk_window_set_title(GTK_WINDOW(dialog), title.get());
gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse);
return dialog;
}
static gboolean webkitWebViewScriptDialog(WebKitWebView* webView, WebKitScriptDialog* scriptDialog)
{
GtkWidget* dialog = 0;
switch (scriptDialog->type) {
case WEBKIT_SCRIPT_DIALOG_ALERT:
dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, GTK_RESPONSE_CLOSE, scriptDialog->message.data());
gtk_dialog_run(GTK_DIALOG(dialog));
break;
case WEBKIT_SCRIPT_DIALOG_CONFIRM:
dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK, scriptDialog->message.data());
scriptDialog->confirmed = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK;
break;
case WEBKIT_SCRIPT_DIALOG_PROMPT:
dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK, scriptDialog->message.data());
GtkWidget* entry = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(entry), scriptDialog->defaultText.data());
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry);
gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
gtk_widget_show(entry);
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
scriptDialog->text = gtk_entry_get_text(GTK_ENTRY(entry));
break;
}
gtk_widget_destroy(dialog);
return TRUE;
}
static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* decision, WebKitPolicyDecisionType)
{
webkit_policy_decision_use(decision);
return TRUE;
}
static void zoomTextOnlyChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
{
WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
gboolean zoomTextOnly = webkit_settings_get_zoom_text_only(settings);
gdouble pageZoomLevel = zoomTextOnly ? 1 : WKPageGetTextZoomFactor(wkPage);
gdouble textZoomLevel = zoomTextOnly ? WKPageGetPageZoomFactor(wkPage) : 1;
WKPageSetPageAndTextZoomFactors(wkPage, pageZoomLevel, textZoomLevel);
}
static void webkitWebViewSetSettings(WebKitWebView* webView, WebKitSettings* settings, WKPageRef wkPage)
{
webView->priv->settings = settings;
webkitSettingsAttachSettingsToPage(webView->priv->settings.get(), wkPage);
g_signal_connect(settings, "notify::zoom-text-only", G_CALLBACK(zoomTextOnlyChanged), webView);
}
static void fileChooserDialogResponseCallback(GtkDialog* dialog, gint responseID, WebKitFileChooserRequest* request)
{
GRefPtr<WebKitFileChooserRequest> adoptedRequest = adoptGRef(request);
if (responseID == GTK_RESPONSE_ACCEPT) {
GOwnPtr<GSList> filesList(gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)));
GRefPtr<GPtrArray> filesArray = adoptGRef(g_ptr_array_new());
for (GSList* file = filesList.get(); file; file = g_slist_next(file))
g_ptr_array_add(filesArray.get(), file->data);
g_ptr_array_add(filesArray.get(), 0);
webkit_file_chooser_request_select_files(adoptedRequest.get(), reinterpret_cast<const gchar* const*>(filesArray->pdata));
} else
webkit_file_chooser_request_cancel(adoptedRequest.get());
gtk_widget_destroy(GTK_WIDGET(dialog));
}
static gboolean webkitWebViewRunFileChooser(WebKitWebView* webView, WebKitFileChooserRequest* request)
{
GtkWidget* toplevel = gtk_widget_get_toplevel(GTK_WIDGET(webView));
if (!widgetIsOnscreenToplevelWindow(toplevel))
toplevel = 0;
gboolean allowsMultipleSelection = webkit_file_chooser_request_get_select_multiple(request);
GtkWidget* dialog = gtk_file_chooser_dialog_new(allowsMultipleSelection ? _("Select Files") : _("Select File"),
toplevel ? GTK_WINDOW(toplevel) : 0,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
if (GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(request))
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), allowsMultipleSelection);
if (const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request))
gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(dialog), selectedFiles[0]);
g_signal_connect(dialog, "response", G_CALLBACK(fileChooserDialogResponseCallback), g_object_ref(request));
gtk_widget_show(dialog);
return TRUE;
}
static void webkitWebViewConstructed(GObject* object)
{
if (G_OBJECT_CLASS(webkit_web_view_parent_class)->constructed)
G_OBJECT_CLASS(webkit_web_view_parent_class)->constructed(object);
WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
WebKitWebViewPrivate* priv = webView->priv;
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView);
webkitWebViewBaseCreateWebPage(webViewBase, webkitWebContextGetWKContext(priv->context), 0);
attachLoaderClientToView(webView);
attachUIClientToView(webView);
attachPolicyClientToPage(webView);
attachResourceLoadClientToView(webView);
attachFullScreenClientToView(webView);
WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase);
priv->backForwardList = adoptGRef(webkitBackForwardListCreate(WKPageGetBackForwardList(toAPI(page))));
GRefPtr<WebKitSettings> settings = adoptGRef(webkit_settings_new());
webkitWebViewSetSettings(webView, settings.get(), toAPI(page));
}
static void webkitWebViewSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec)
{
WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
switch (propId) {
case PROP_WEB_CONTEXT: {
gpointer webContext = g_value_get_object(value);
webView->priv->context = webContext ? WEBKIT_WEB_CONTEXT(webContext) : webkit_web_context_get_default();
break;
}
case PROP_ZOOM_LEVEL:
webkit_web_view_set_zoom_level(webView, g_value_get_double(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
}
}
static void webkitWebViewGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
{
WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
switch (propId) {
case PROP_WEB_CONTEXT:
g_value_take_object(value, webView->priv->context);
break;
case PROP_TITLE:
g_value_set_string(value, webView->priv->title.data());
break;
case PROP_ESTIMATED_LOAD_PROGRESS:
g_value_set_double(value, webkit_web_view_get_estimated_load_progress(webView));
break;
case PROP_URI:
g_value_set_string(value, webkit_web_view_get_uri(webView));
break;
case PROP_ZOOM_LEVEL:
g_value_set_double(value, webkit_web_view_get_zoom_level(webView));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
}
}
static void webkitWebViewFinalize(GObject* object)
{
WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW(object)->priv;
if (priv->javascriptGlobalContext)
JSGlobalContextRelease(priv->javascriptGlobalContext);
priv->~WebKitWebViewPrivate();
G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
}
static void webkit_web_view_init(WebKitWebView* webView)
{
WebKitWebViewPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(webView, WEBKIT_TYPE_WEB_VIEW, WebKitWebViewPrivate);
webView->priv = priv;
new (priv) WebKitWebViewPrivate();
webView->priv->windowProperties = adoptGRef(webkitWindowPropertiesCreate());
}
static gboolean webkitWebViewAccumulatorObjectHandled(GSignalInvocationHint*, GValue* returnValue, const GValue* handlerReturn, gpointer)
{
void* object = g_value_get_object(handlerReturn);
if (object)
g_value_set_object(returnValue, object);
return !object;
}
static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
{
GObjectClass* gObjectClass = G_OBJECT_CLASS(webViewClass);
gObjectClass->constructed = webkitWebViewConstructed;
gObjectClass->set_property = webkitWebViewSetProperty;
gObjectClass->get_property = webkitWebViewGetProperty;
gObjectClass->finalize = webkitWebViewFinalize;
webViewClass->load_failed = webkitWebViewLoadFail;
webViewClass->create = webkitWebViewCreate;
webViewClass->script_dialog = webkitWebViewScriptDialog;
webViewClass->decide_policy = webkitWebViewDecidePolicy;
webViewClass->run_file_chooser = webkitWebViewRunFileChooser;
g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate));
g_object_class_install_property(gObjectClass,
PROP_WEB_CONTEXT,
g_param_spec_object("web-context",
_("Web Context"),
_("The web context for the view"),
WEBKIT_TYPE_WEB_CONTEXT,
static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
g_object_class_install_property(gObjectClass,
PROP_TITLE,
g_param_spec_string("title",
_("Title"),
_("Main frame document title"),
0,
WEBKIT_PARAM_READABLE));
g_object_class_install_property(gObjectClass,
PROP_ESTIMATED_LOAD_PROGRESS,
g_param_spec_double("estimated-load-progress",
_("Estimated Load Progress"),
_("An estimate of the percent completion for a document load"),
0.0, 1.0, 0.0,
WEBKIT_PARAM_READABLE));
g_object_class_install_property(gObjectClass,
PROP_URI,
g_param_spec_string("uri",
_("URI"),
_("The current active URI of the view"),
0,
WEBKIT_PARAM_READABLE));
signals[LOAD_CHANGED] =
g_signal_new("load-changed",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, load_changed),
0, 0,
g_cclosure_marshal_VOID__ENUM,
G_TYPE_NONE, 1,
WEBKIT_TYPE_LOAD_EVENT);
signals[LOAD_FAILED] =
g_signal_new("load-failed",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, load_failed),
g_signal_accumulator_true_handled, 0,
webkit_marshal_BOOLEAN__ENUM_STRING_POINTER,
G_TYPE_BOOLEAN, 3,
WEBKIT_TYPE_LOAD_EVENT,
G_TYPE_STRING,
G_TYPE_POINTER);
g_object_class_install_property(gObjectClass,
PROP_ZOOM_LEVEL,
g_param_spec_double("zoom-level",
"Zoom level",
"The zoom level of the view content",
0, G_MAXDOUBLE, 1,
WEBKIT_PARAM_READWRITE));
signals[CREATE] =
g_signal_new("create",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, create),
webkitWebViewAccumulatorObjectHandled, 0,
webkit_marshal_OBJECT__VOID,
GTK_TYPE_WIDGET, 0);
signals[READY_TO_SHOW] =
g_signal_new("ready-to-show",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, ready_to_show),
0, 0,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[CLOSE] =
g_signal_new("close",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, close),
0, 0,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[SCRIPT_DIALOG] =
g_signal_new("script-dialog",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, script_dialog),
g_signal_accumulator_true_handled, 0,
webkit_marshal_BOOLEAN__BOXED,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_SCRIPT_DIALOG | G_SIGNAL_TYPE_STATIC_SCOPE);
signals[DECIDE_POLICY] =
g_signal_new("decide-policy",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, decide_policy),
g_signal_accumulator_true_handled, 0 ,
webkit_marshal_BOOLEAN__OBJECT_ENUM,
G_TYPE_BOOLEAN, 2,
WEBKIT_TYPE_POLICY_DECISION,
WEBKIT_TYPE_POLICY_DECISION_TYPE);
signals[MOUSE_TARGET_CHANGED] =
g_signal_new("mouse-target-changed",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, mouse_target_changed),
0, 0,
webkit_marshal_VOID__OBJECT_UINT,
G_TYPE_NONE, 2,
WEBKIT_TYPE_HIT_TEST_RESULT,
G_TYPE_UINT);
signals[PRINT_REQUESTED] =
g_signal_new("print-requested",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, print_requested),
g_signal_accumulator_true_handled, 0,
webkit_marshal_BOOLEAN__OBJECT,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_PRINT_OPERATION);
signals[RESOURCE_LOAD_STARTED] =
g_signal_new("resource-load-started",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, resource_load_started),
0, 0,
webkit_marshal_VOID__OBJECT_OBJECT,
G_TYPE_NONE, 2,
WEBKIT_TYPE_WEB_RESOURCE,
WEBKIT_TYPE_URI_REQUEST);
signals[ENTER_FULLSCREEN] =
g_signal_new("enter-fullscreen",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, enter_fullscreen),
g_signal_accumulator_true_handled, 0,
webkit_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
signals[LEAVE_FULLSCREEN] =
g_signal_new("leave-fullscreen",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, leave_fullscreen),
g_signal_accumulator_true_handled, 0,
webkit_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
signals[RUN_FILE_CHOOSER] =
g_signal_new("run-file-chooser",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, run_file_chooser),
g_signal_accumulator_true_handled, 0 ,
webkit_marshal_BOOLEAN__OBJECT,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_FILE_CHOOSER_REQUEST);
}
static bool updateReplaceContentStatus(WebKitWebView* webView, WebKitLoadEvent loadEvent)
{
if (webView->priv->replaceContentStatus == ReplacingContent) {
if (loadEvent == WEBKIT_LOAD_FINISHED)
webView->priv->replaceContentStatus = DidReplaceContent;
return true;
}
if (loadEvent == WEBKIT_LOAD_STARTED) {
if (webView->priv->replaceContentStatus == WillReplaceContent) {
webView->priv->replaceContentStatus = ReplacingContent;
return true;
}
webView->priv->replaceContentStatus = NotReplacingContent;
}
return false;
}
void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
{
if (loadEvent == WEBKIT_LOAD_STARTED) {
webView->priv->loadingResourcesMap.clear();
webView->priv->mainResource = 0;
} else if (loadEvent == WEBKIT_LOAD_COMMITTED)
webView->priv->subresourcesMap.clear();
if (updateReplaceContentStatus(webView, loadEvent))
return;
if (loadEvent != WEBKIT_LOAD_FINISHED)
webkitWebViewUpdateURI(webView);
g_signal_emit(webView, signals[LOAD_CHANGED], 0, loadEvent);
}
void webkitWebViewLoadFailed(WebKitWebView* webView, WebKitLoadEvent loadEvent, const char* failingURI, GError *error)
{
if (webView->priv->replaceContentStatus == ReplacingContent)
return;
gboolean returnValue;
g_signal_emit(webView, signals[LOAD_FAILED], 0, loadEvent, failingURI, error, &returnValue);
g_signal_emit(webView, signals[LOAD_CHANGED], 0, WEBKIT_LOAD_FINISHED);
}
void webkitWebViewSetTitle(WebKitWebView* webView, const CString& title)
{
WebKitWebViewPrivate* priv = webView->priv;
if (priv->title == title)
return;
priv->title = title;
g_object_notify(G_OBJECT(webView), "title");
}
void webkitWebViewSetEstimatedLoadProgress(WebKitWebView* webView, double estimatedLoadProgress)
{
if (webView->priv->replaceContentStatus != NotReplacingContent)
return;
if (webView->priv->estimatedLoadProgress == estimatedLoadProgress)
return;
webView->priv->estimatedLoadProgress = estimatedLoadProgress;
g_object_notify(G_OBJECT(webView), "estimated-load-progress");
}
void webkitWebViewUpdateURI(WebKitWebView* webView)
{
WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKPageCopyActiveURL(toAPI(page)));
CString activeURI;
if (wkURL)
activeURI = toImpl(wkURL.get())->string().utf8();
if (webView->priv->activeURI == activeURI)
return;
webView->priv->activeURI = activeURI;
g_object_notify(G_OBJECT(webView), "uri");
}
WKPageRef webkitWebViewCreateNewPage(WebKitWebView* webView, WKDictionaryRef wkWindowFeatures)
{
WebKitWebView* newWebView;
g_signal_emit(webView, signals[CREATE], 0, &newWebView);
if (!newWebView)
return 0;
webkitWindowPropertiesUpdateFromWKWindowFeatures(newWebView->priv->windowProperties.get(), wkWindowFeatures);
return static_cast<WKPageRef>(WKRetain(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(newWebView)))));
}
void webkitWebViewReadyToShowPage(WebKitWebView* webView)
{
g_signal_emit(webView, signals[READY_TO_SHOW], 0, NULL);
}
void webkitWebViewClosePage(WebKitWebView* webView)
{
g_signal_emit(webView, signals[CLOSE], 0, NULL);
}
void webkitWebViewRunJavaScriptAlert(WebKitWebView* webView, const CString& message)
{
WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_ALERT, message);
gboolean returnValue;
g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
}
bool webkitWebViewRunJavaScriptConfirm(WebKitWebView* webView, const CString& message)
{
WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_CONFIRM, message);
gboolean returnValue;
g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
return dialog.confirmed;
}
WKStringRef webkitWebViewRunJavaScriptPrompt(WebKitWebView* webView, const CString& message, const CString& defaultText)
{
WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_PROMPT, message, defaultText);
gboolean returnValue;
g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
return dialog.text.isNull() ? 0 : WKStringCreateWithUTF8CString(dialog.text.data());
}
void webkitWebViewMakePolicyDecision(WebKitWebView* webView, WebKitPolicyDecisionType type, WebKitPolicyDecision* decision)
{
gboolean returnValue;
g_signal_emit(webView, signals[DECIDE_POLICY], 0, decision, type, &returnValue);
}
void webkitWebViewMouseTargetChanged(WebKitWebView* webView, WKHitTestResultRef wkHitTestResult, unsigned modifiers)
{
WebKitWebViewPrivate* priv = webView->priv;
if (priv->mouseTargetHitTestResult
&& priv->mouseTargetModifiers == modifiers
&& webkitHitTestResultCompare(priv->mouseTargetHitTestResult.get(), wkHitTestResult))
return;
priv->mouseTargetModifiers = modifiers;
priv->mouseTargetHitTestResult = adoptGRef(webkitHitTestResultCreate(wkHitTestResult));
g_signal_emit(webView, signals[MOUSE_TARGET_CHANGED], 0, priv->mouseTargetHitTestResult.get(), modifiers);
}
void webkitWebViewPrintFrame(WebKitWebView* webView, WKFrameRef wkFrame)
{
GRefPtr<WebKitPrintOperation> printOperation = adoptGRef(webkit_print_operation_new(webView));
gboolean returnValue;
g_signal_emit(webView, signals[PRINT_REQUESTED], 0, printOperation.get(), &returnValue);
if (returnValue)
return;
WebKitPrintOperationResponse response = webkitPrintOperationRunDialogForFrame(printOperation.get(), 0, toImpl(wkFrame));
if (response == WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL)
return;
g_signal_connect(printOperation.leakRef(), "finished", G_CALLBACK(g_object_unref), 0);
}
static inline bool webkitWebViewIsReplacingContentOrDidReplaceContent(WebKitWebView* webView)
{
return (webView->priv->replaceContentStatus == ReplacingContent || webView->priv->replaceContentStatus == DidReplaceContent);
}
void webkitWebViewResourceLoadStarted(WebKitWebView* webView, WKFrameRef wkFrame, uint64_t resourceIdentifier, WebKitURIRequest* request, bool isMainResource)
{
if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView))
return;
WebKitWebViewPrivate* priv = webView->priv;
WebKitWebResource* resource = webkitWebResourceCreate(wkFrame, request, isMainResource);
if (WKFrameIsMainFrame(wkFrame) && isMainResource)
priv->mainResource = resource;
priv->loadingResourcesMap.set(resourceIdentifier, adoptGRef(resource));
g_signal_emit(webView, signals[RESOURCE_LOAD_STARTED], 0, resource, request);
}
WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier)
{
if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView))
return 0;
GRefPtr<WebKitWebResource> resource = webView->priv->loadingResourcesMap.get(resourceIdentifier);
ASSERT(resource.get());
return resource.get();
}
void webkitWebViewRemoveLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier)
{
if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView))
return;
WebKitWebViewPrivate* priv = webView->priv;
ASSERT(priv->loadingResourcesMap.contains(resourceIdentifier));
priv->loadingResourcesMap.remove(resourceIdentifier);
}
WebKitWebResource* webkitWebViewResourceLoadFinished(WebKitWebView* webView, uint64_t resourceIdentifier)
{
if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView))
return 0;
WebKitWebViewPrivate* priv = webView->priv;
WebKitWebResource* resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier);
if (resource != priv->mainResource)
priv->subresourcesMap.set(String::fromUTF8(webkit_web_resource_get_uri(resource)), resource);
webkitWebViewRemoveLoadingWebResource(webView, resourceIdentifier);
return resource;
}
bool webkitWebViewEnterFullScreen(WebKitWebView* webView)
{
gboolean returnValue;
g_signal_emit(webView, signals[ENTER_FULLSCREEN], 0, &returnValue);
return !returnValue;
}
bool webkitWebViewLeaveFullScreen(WebKitWebView* webView)
{
gboolean returnValue;
g_signal_emit(webView, signals[LEAVE_FULLSCREEN], 0, &returnValue);
return !returnValue;
}
void webkitWebViewRunFileChooserRequest(WebKitWebView* webView, WebKitFileChooserRequest* request)
{
gboolean returnValue;
g_signal_emit(webView, signals[RUN_FILE_CHOOSER], 0, request, &returnValue);
}
GtkWidget* webkit_web_view_new()
{
return webkit_web_view_new_with_context(webkit_web_context_get_default());
}
GtkWidget* webkit_web_view_new_with_context(WebKitWebContext* context)
{
g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0);
return GTK_WIDGET(g_object_new(WEBKIT_TYPE_WEB_VIEW, "web-context", context, NULL));
}
WebKitWebContext* webkit_web_view_get_context(WebKitWebView *webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->context;
}
void webkit_web_view_load_uri(WebKitWebView* webView, const gchar* uri)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(uri);
WKRetainPtr<WKURLRef> url(AdoptWK, WKURLCreateWithUTF8CString(uri));
WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
WKPageLoadURL(toAPI(page), url.get());
webkitWebViewUpdateURI(webView);
}
void webkit_web_view_load_html(WebKitWebView* webView, const gchar* content, const gchar* baseURI)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(content);
WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
WKRetainPtr<WKStringRef> contentRef(AdoptWK, WKStringCreateWithUTF8CString(content));
WKRetainPtr<WKURLRef> baseURIRef = baseURI ? adoptWK(WKURLCreateWithUTF8CString(baseURI)) : 0;
WKPageLoadHTMLString(toAPI(page), contentRef.get(), baseURIRef.get());
}
void webkit_web_view_load_plain_text(WebKitWebView* webView, const gchar* plainText)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(plainText);
WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
WKRetainPtr<WKStringRef> plainTextRef(AdoptWK, WKStringCreateWithUTF8CString(plainText));
WKPageLoadPlainTextString(toAPI(page), plainTextRef.get());
}
void webkit_web_view_load_request(WebKitWebView* webView, WebKitURIRequest* request)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(WEBKIT_IS_URI_REQUEST(request));
WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKURLCreateWithUTF8CString(webkit_uri_request_get_uri(request)));
WKRetainPtr<WKURLRequestRef> wkRequest(AdoptWK, WKURLRequestCreateWithWKURL(wkURL.get()));
WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
WKPageLoadURLRequest(toAPI(page), wkRequest.get());
webkitWebViewUpdateURI(webView);
}
void webkit_web_view_replace_content(WebKitWebView* webView, const gchar* content, const gchar* contentURI, const gchar* baseURI)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(content);
g_return_if_fail(contentURI);
webView->priv->replaceContentStatus = WillReplaceContent;
WKRetainPtr<WKStringRef> htmlString(AdoptWK, WKStringCreateWithUTF8CString(content));
WKRetainPtr<WKURLRef> contentURL(AdoptWK, WKURLCreateWithUTF8CString(contentURI));
WKRetainPtr<WKURLRef> baseURL = baseURI ? adoptWK(WKURLCreateWithUTF8CString(baseURI)) : 0;
WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
WKPageLoadAlternateHTMLString(toAPI(page), htmlString.get(), baseURL.get(), contentURL.get());
webkitWebViewUpdateURI(webView);
}
const gchar* webkit_web_view_get_title(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->title.data();
}
void webkit_web_view_reload(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
WKPageReload(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
webkitWebViewUpdateURI(webView);
}
void webkit_web_view_reload_bypass_cache(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
WKPageReloadFromOrigin(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
webkitWebViewUpdateURI(webView);
}
void webkit_web_view_stop_loading(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
WKPageStopLoading(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
}
void webkit_web_view_go_back(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
WKPageGoBack(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
webkitWebViewUpdateURI(webView);
}
gboolean webkit_web_view_can_go_back(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
return WKPageCanGoBack(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
}
void webkit_web_view_go_forward(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
WKPageGoForward(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
webkitWebViewUpdateURI(webView);
}
gboolean webkit_web_view_can_go_forward(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
return WKPageCanGoForward(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
}
const gchar* webkit_web_view_get_uri(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->activeURI.data();
}
const gchar* webkit_web_view_get_custom_charset(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
WKRetainPtr<WKStringRef> wkCustomEncoding(AdoptWK, WKPageCopyCustomTextEncodingName(toAPI(page)));
if (WKStringIsEmpty(wkCustomEncoding.get()))
return 0;
webView->priv->customTextEncoding = toImpl(wkCustomEncoding.get())->string().utf8();
return webView->priv->customTextEncoding.data();
}
void webkit_web_view_set_custom_charset(WebKitWebView* webView, const gchar* charset)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
WKRetainPtr<WKStringRef> wkEncodingName = charset ? adoptWK(WKStringCreateWithUTF8CString(charset)) : 0;
WKPageSetCustomTextEncodingName(toAPI(page), wkEncodingName.get());
}
gdouble webkit_web_view_get_estimated_load_progress(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->estimatedLoadProgress;
}
WebKitBackForwardList* webkit_web_view_get_back_forward_list(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->backForwardList.get();
}
void webkit_web_view_go_to_back_forward_list_item(WebKitWebView* webView, WebKitBackForwardListItem* listItem)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(WEBKIT_IS_BACK_FORWARD_LIST_ITEM(listItem));
WKPageGoToBackForwardListItem(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))),
webkitBackForwardListItemGetWKItem(listItem));
webkitWebViewUpdateURI(webView);
}
void webkit_web_view_set_settings(WebKitWebView* webView, WebKitSettings* settings)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(WEBKIT_IS_SETTINGS(settings));
if (webView->priv->settings == settings)
return;
g_signal_handlers_disconnect_by_func(webView->priv->settings.get(), reinterpret_cast<gpointer>(zoomTextOnlyChanged), webView);
webkitWebViewSetSettings(webView, settings, toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
}
WebKitSettings* webkit_web_view_get_settings(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->settings.get();
}
WebKitWindowProperties* webkit_web_view_get_window_properties(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->windowProperties.get();
}
void webkit_web_view_set_zoom_level(WebKitWebView* webView, gdouble zoomLevel)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
if (webkit_web_view_get_zoom_level(webView) == zoomLevel)
return;
WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
if (webkit_settings_get_zoom_text_only(webView->priv->settings.get()))
WKPageSetTextZoomFactor(wkPage, zoomLevel);
else
WKPageSetPageZoomFactor(wkPage, zoomLevel);
g_object_notify(G_OBJECT(webView), "zoom-level");
}
gdouble webkit_web_view_get_zoom_level(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 1);
WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
gboolean zoomTextOnly = webkit_settings_get_zoom_text_only(webView->priv->settings.get());
return zoomTextOnly ? WKPageGetTextZoomFactor(wkPage) : WKPageGetPageZoomFactor(wkPage);
}
static void didValidateCommand(WKStringRef command, bool isEnabled, int32_t state, WKErrorRef, void* context)
{
GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context));
g_simple_async_result_set_op_res_gboolean(result.get(), isEnabled);
g_simple_async_result_complete(result.get());
}
void webkit_web_view_can_execute_editing_command(WebKitWebView* webView, const char* command, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(command);
GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData,
reinterpret_cast<gpointer>(webkit_web_view_can_execute_editing_command));
WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
WKRetainPtr<WKStringRef> wkCommand(AdoptWK, WKStringCreateWithUTF8CString(command));
WKPageValidateCommand(toAPI(page), wkCommand.get(), result, didValidateCommand);
}
gboolean webkit_web_view_can_execute_editing_command_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE);
GSimpleAsyncResult* simple = G_SIMPLE_ASYNC_RESULT(result);
g_warn_if_fail(g_simple_async_result_get_source_tag(simple) == webkit_web_view_can_execute_editing_command);
if (g_simple_async_result_propagate_error(simple, error))
return FALSE;
return g_simple_async_result_get_op_res_gboolean(simple);
}
void webkit_web_view_execute_editing_command(WebKitWebView* webView, const char* command)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(command);
WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
WKRetainPtr<WKStringRef> wkCommand(AdoptWK, WKStringCreateWithUTF8CString(command));
WKPageExecuteCommand(toAPI(page), wkCommand.get());
}
WebKitFindController* webkit_web_view_get_find_controller(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
if (!webView->priv->findController)
webView->priv->findController = adoptGRef(WEBKIT_FIND_CONTROLLER(g_object_new(WEBKIT_TYPE_FIND_CONTROLLER, "web-view", webView, NULL)));
return webView->priv->findController.get();
}
JSGlobalContextRef webkit_web_view_get_javascript_global_context(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
if (!webView->priv->javascriptGlobalContext)
webView->priv->javascriptGlobalContext = JSGlobalContextCreate(0);
return webView->priv->javascriptGlobalContext;
}
static void webkitWebViewRunJavaScriptCallback(WKSerializedScriptValueRef wkSerializedScriptValue, WKErrorRef, void* context)
{
GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context));
if (wkSerializedScriptValue) {
GRefPtr<WebKitWebView> webView = adoptGRef(WEBKIT_WEB_VIEW(g_async_result_get_source_object(G_ASYNC_RESULT(result.get()))));
WebKitJavascriptResult* scriptResult = webkitJavascriptResultCreate(webView.get(), wkSerializedScriptValue);
g_simple_async_result_set_op_res_gpointer(result.get(), scriptResult, reinterpret_cast<GDestroyNotify>(webkit_javascript_result_unref));
} else {
GError* error = 0;
g_set_error_literal(&error, WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED, _("An exception was raised in JavaScript"));
g_simple_async_result_take_error(result.get(), error);
}
g_simple_async_result_complete(result.get());
}
void webkit_web_view_run_javascript(WebKitWebView* webView, const gchar* script, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(script);
WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
WKRetainPtr<WKStringRef> wkScript = adoptWK(WKStringCreateWithUTF8CString(script));
GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData,
reinterpret_cast<gpointer>(webkit_web_view_run_javascript));
WKPageRunJavaScriptInMainFrame(wkPage, wkScript.get(), result, webkitWebViewRunJavaScriptCallback);
}
WebKitJavascriptResult* webkit_web_view_run_javascript_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0);
GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result);
g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_web_view_run_javascript);
if (g_simple_async_result_propagate_error(simpleResult, error))
return 0;
WebKitJavascriptResult* scriptResult = static_cast<WebKitJavascriptResult*>(g_simple_async_result_get_op_res_gpointer(simpleResult));
return scriptResult ? webkit_javascript_result_ref(scriptResult) : 0;
}
WebKitWebResource* webkit_web_view_get_main_resource(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->mainResource.get();
}
GList* webkit_web_view_get_subresources(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
GList* subresources = 0;
WebKitWebViewPrivate* priv = webView->priv;
ResourcesMap::const_iterator end = priv->subresourcesMap.end();
for (ResourcesMap::const_iterator it = priv->subresourcesMap.begin(); it != end; ++it)
subresources = g_list_prepend(subresources, it->second.get());
return g_list_reverse(subresources);
}