WebKitWebResource.cpp [plain text]
#include "config.h"
#include "WebKitWebResource.h"
#include "APIData.h"
#include "WebFrameProxy.h"
#include "WebKitURIRequest.h"
#include "WebKitWebResourcePrivate.h"
#include <glib/gi18n-lib.h>
#include <wtf/glib/GRefPtr.h>
#include <wtf/glib/WTFGType.h>
#include <wtf/text/CString.h>
using namespace WebKit;
enum {
SENT_REQUEST,
RECEIVED_DATA,
FINISHED,
FAILED,
FAILED_WITH_TLS_ERRORS,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_URI,
PROP_RESPONSE
};
struct _WebKitWebResourcePrivate {
RefPtr<WebFrameProxy> frame;
CString uri;
GRefPtr<WebKitURIResponse> response;
bool isMainResource;
};
WEBKIT_DEFINE_TYPE(WebKitWebResource, webkit_web_resource, G_TYPE_OBJECT)
static guint signals[LAST_SIGNAL] = { 0, };
static void webkitWebResourceGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
{
WebKitWebResource* resource = WEBKIT_WEB_RESOURCE(object);
switch (propId) {
case PROP_URI:
g_value_set_string(value, webkit_web_resource_get_uri(resource));
break;
case PROP_RESPONSE:
g_value_set_object(value, webkit_web_resource_get_response(resource));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
}
}
static void webkit_web_resource_class_init(WebKitWebResourceClass* resourceClass)
{
GObjectClass* objectClass = G_OBJECT_CLASS(resourceClass);
objectClass->get_property = webkitWebResourceGetProperty;
g_object_class_install_property(objectClass,
PROP_URI,
g_param_spec_string("uri",
_("URI"),
_("The current active URI of the resource"),
0,
WEBKIT_PARAM_READABLE));
g_object_class_install_property(objectClass,
PROP_RESPONSE,
g_param_spec_object("response",
_("Response"),
_("The response of the resource"),
WEBKIT_TYPE_URI_RESPONSE,
WEBKIT_PARAM_READABLE));
signals[SENT_REQUEST] = g_signal_new(
"sent-request",
G_TYPE_FROM_CLASS(objectClass),
G_SIGNAL_RUN_LAST,
0, nullptr, nullptr,
g_cclosure_marshal_generic,
G_TYPE_NONE, 2,
WEBKIT_TYPE_URI_REQUEST,
WEBKIT_TYPE_URI_RESPONSE);
signals[RECEIVED_DATA] = g_signal_new(
"received-data",
G_TYPE_FROM_CLASS(objectClass),
G_SIGNAL_RUN_LAST,
0, nullptr, nullptr,
g_cclosure_marshal_generic,
G_TYPE_NONE, 1,
G_TYPE_UINT64);
signals[FINISHED] =
g_signal_new("finished",
G_TYPE_FROM_CLASS(objectClass),
G_SIGNAL_RUN_LAST,
0, 0, 0,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[FAILED] =
g_signal_new(
"failed",
G_TYPE_FROM_CLASS(objectClass),
G_SIGNAL_RUN_LAST,
0, 0, 0,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1,
G_TYPE_ERROR | G_SIGNAL_TYPE_STATIC_SCOPE);
signals[FAILED_WITH_TLS_ERRORS] =
g_signal_new("failed-with-tls-errors",
G_TYPE_FROM_CLASS(objectClass),
G_SIGNAL_RUN_LAST,
0, nullptr, nullptr,
g_cclosure_marshal_generic,
G_TYPE_NONE, 2,
G_TYPE_TLS_CERTIFICATE,
G_TYPE_TLS_CERTIFICATE_FLAGS);
}
static void webkitWebResourceUpdateURI(WebKitWebResource* resource, const CString& requestURI)
{
if (resource->priv->uri == requestURI)
return;
resource->priv->uri = requestURI;
g_object_notify(G_OBJECT(resource), "uri");
}
WebKitWebResource* webkitWebResourceCreate(WebFrameProxy* frame, WebKitURIRequest* request, bool isMainResource)
{
ASSERT(frame);
WebKitWebResource* resource = WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, NULL));
resource->priv->frame = frame;
resource->priv->uri = webkit_uri_request_get_uri(request);
resource->priv->isMainResource = isMainResource;
return resource;
}
void webkitWebResourceSentRequest(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse)
{
webkitWebResourceUpdateURI(resource, webkit_uri_request_get_uri(request));
g_signal_emit(resource, signals[SENT_REQUEST], 0, request, redirectResponse);
}
void webkitWebResourceSetResponse(WebKitWebResource* resource, WebKitURIResponse* response)
{
resource->priv->response = response;
g_object_notify(G_OBJECT(resource), "response");
}
void webkitWebResourceNotifyProgress(WebKitWebResource* resource, guint64 bytesReceived)
{
g_signal_emit(resource, signals[RECEIVED_DATA], 0, bytesReceived);
}
void webkitWebResourceFinished(WebKitWebResource* resource)
{
g_signal_emit(resource, signals[FINISHED], 0, NULL);
}
void webkitWebResourceFailed(WebKitWebResource* resource, GError* error)
{
g_signal_emit(resource, signals[FAILED], 0, error);
g_signal_emit(resource, signals[FINISHED], 0, NULL);
}
void webkitWebResourceFailedWithTLSErrors(WebKitWebResource* resource, GTlsCertificateFlags tlsErrors, GTlsCertificate* certificate)
{
g_signal_emit(resource, signals[FAILED_WITH_TLS_ERRORS], 0, certificate, tlsErrors);
g_signal_emit(resource, signals[FINISHED], 0, nullptr);
}
WebFrameProxy* webkitWebResourceGetFrame(WebKitWebResource* resource)
{
return resource->priv->frame.get();
}
const char* webkit_web_resource_get_uri(WebKitWebResource* resource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_RESOURCE(resource), 0);
return resource->priv->uri.data();
}
WebKitURIResponse* webkit_web_resource_get_response(WebKitWebResource* resource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_RESOURCE(resource), 0);
return resource->priv->response.get();
}
struct ResourceGetDataAsyncData {
RefPtr<API::Data> webData;
};
WEBKIT_DEFINE_ASYNC_DATA_STRUCT(ResourceGetDataAsyncData)
static void resourceDataCallback(API::Data* wkData, CallbackBase::Error error, GTask* task)
{
if (error != CallbackBase::Error::None) {
g_task_return_new_error(task, G_IO_ERROR, G_IO_ERROR_CANCELLED, _("Operation was cancelled"));
return;
}
ResourceGetDataAsyncData* data = static_cast<ResourceGetDataAsyncData*>(g_task_get_task_data(task));
data->webData = wkData;
g_task_return_boolean(task, TRUE);
}
void webkit_web_resource_get_data(WebKitWebResource* resource, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_RESOURCE(resource));
GRefPtr<GTask> task = adoptGRef(g_task_new(resource, cancellable, callback, userData));
g_task_set_task_data(task.get(), createResourceGetDataAsyncData(), reinterpret_cast<GDestroyNotify>(destroyResourceGetDataAsyncData));
if (resource->priv->isMainResource)
resource->priv->frame->getMainResourceData([task = WTFMove(task)](API::Data* data, CallbackBase::Error error) {
resourceDataCallback(data, error, task.get());
});
else {
String url = String::fromUTF8(resource->priv->uri.data());
resource->priv->frame->getResourceData(API::URL::create(url).ptr(), [task = WTFMove(task)](API::Data* data, CallbackBase::Error error) {
resourceDataCallback(data, error, task.get());
});
}
}
guchar* webkit_web_resource_get_data_finish(WebKitWebResource* resource, GAsyncResult* result, gsize* length, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_RESOURCE(resource), 0);
g_return_val_if_fail(g_task_is_valid(result, resource), 0);
GTask* task = G_TASK(result);
if (!g_task_propagate_boolean(task, error))
return 0;
ResourceGetDataAsyncData* data = static_cast<ResourceGetDataAsyncData*>(g_task_get_task_data(task));
if (length)
*length = data->webData->size();
return static_cast<guchar*>(g_memdup(data->webData->bytes(), data->webData->size()));
}