blob: 059688ef701db04b3319aad0d8ca8207e6e63152 [file] [log] [blame]
/*
* Copyright (C) 2009 Jan Michael C. Alonzo
*
* 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 "webkitwebdatasource.h"
#include "ArchiveResource.h"
#include "DocumentLoaderGtk.h"
#include "FrameLoaderClientGtk.h"
#include "FrameLoader.h"
#include "KURL.h"
#include "PlatformString.h"
#include "ResourceRequest.h"
#include "runtime/InitializeThreading.h"
#include "SharedBuffer.h"
#include "SubstituteData.h"
#include "webkitwebresource.h"
#include "webkitprivate.h"
#include "wtf/Assertions.h"
#include <glib.h>
/**
* SECTION:webkitwebdatasource
* @short_description: Encapsulates the content to be displayed in a #WebKitWebFrame.
* @see_also: #WebKitWebFrame
*
* Data source encapsulates the content of a #WebKitWebFrame. A
* #WebKitWebFrame has a main resource and subresources and the data source
* provides access to these resources. When a request gets loaded initially,
* it is set to a provisional state. The application can request for the
* request that initiated the load by asking for the provisional data source
* and invoking the webkit_web_data_source_get_initial_request method of
* #WebKitWebDataSource. This data source may not have enough data and some
* methods may return empty values. To get a "full" data source with the data
* and resources loaded, you need to get the non-provisional data source
* through #WebKitWebFrame's webkit_web_frame_get_data_source method. This
* data source will have the data after everything was loaded. Make sure that
* the data source was finished loading before using any of its methods. You
* can do this via webkit_web_data_source_is_loading.
*/
using namespace WebCore;
using namespace WebKit;
struct _WebKitWebDataSourcePrivate {
WebKit::DocumentLoader* loader;
WebKitNetworkRequest* initialRequest;
WebKitNetworkRequest* networkRequest;
WebKitWebResource* mainresource;
GString* data;
gchar* textEncoding;
gchar* unreachableURL;
};
#define WEBKIT_WEB_DATA_SOURCE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_WEB_DATA_SOURCE, WebKitWebDataSourcePrivate))
G_DEFINE_TYPE(WebKitWebDataSource, webkit_web_data_source, G_TYPE_OBJECT);
static void webkit_web_data_source_dispose(GObject* object)
{
WebKitWebDataSource* webDataSource = WEBKIT_WEB_DATA_SOURCE(object);
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
ASSERT(priv->loader);
ASSERT(!priv->loader->isLoading());
priv->loader->detachDataSource();
priv->loader->deref();
if (priv->initialRequest) {
g_object_unref(priv->initialRequest);
priv->initialRequest = NULL;
}
if (priv->networkRequest) {
g_object_unref(priv->networkRequest);
priv->networkRequest = NULL;
}
if (priv->mainresource) {
g_object_unref(priv->mainresource);
priv->mainresource = NULL;
}
G_OBJECT_CLASS(webkit_web_data_source_parent_class)->dispose(object);
}
static void webkit_web_data_source_finalize(GObject* object)
{
WebKitWebDataSource* dataSource = WEBKIT_WEB_DATA_SOURCE(object);
WebKitWebDataSourcePrivate* priv = dataSource->priv;
g_free(priv->unreachableURL);
g_free(priv->textEncoding);
if (priv->data) {
g_string_free(priv->data, TRUE);
priv->data = NULL;
}
G_OBJECT_CLASS(webkit_web_data_source_parent_class)->finalize(object);
}
static void webkit_web_data_source_class_init(WebKitWebDataSourceClass* klass)
{
GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
gobject_class->dispose = webkit_web_data_source_dispose;
gobject_class->finalize = webkit_web_data_source_finalize;
webkit_init();
g_type_class_add_private(gobject_class, sizeof(WebKitWebDataSourcePrivate));
}
static void webkit_web_data_source_init(WebKitWebDataSource* webDataSource)
{
webDataSource->priv = WEBKIT_WEB_DATA_SOURCE_GET_PRIVATE(webDataSource);
}
WebKitWebDataSource* webkit_web_data_source_new_with_loader(PassRefPtr<WebKit::DocumentLoader> loader)
{
WebKitWebDataSource* webDataSource = WEBKIT_WEB_DATA_SOURCE(g_object_new(WEBKIT_TYPE_WEB_DATA_SOURCE, NULL));
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
priv->loader = loader.releaseRef();
return webDataSource;
}
/**
* webkit_web_data_source_new:
*
* Creates a new #WebKitWebDataSource instance. The URL of the
* #WebKitWebDataSource will be set to "about:blank".
*
* Return: a new #WebKitWebDataSource.
*
* Since: 1.1.14
*/
WebKitWebDataSource* webkit_web_data_source_new()
{
WebKitNetworkRequest* request = webkit_network_request_new("about:blank");
WebKitWebDataSource* datasource = webkit_web_data_source_new_with_request(request);
g_object_unref(request);
return datasource;
}
/**
* webkit_web_data_source_new_with_request:
* @request: the #WebKitNetworkRequest to use to create this data source
*
* Creates a new #WebKitWebDataSource from a #WebKitNetworkRequest. Normally,
* #WebKitWebFrame objects create their data sources so you will almost never
* want to invoke this method directly.
*
* Returns: a new #WebKitWebDataSource
*
* Since: 1.1.14
*/
WebKitWebDataSource* webkit_web_data_source_new_with_request(WebKitNetworkRequest* request)
{
ASSERT(request);
const gchar* uri = webkit_network_request_get_uri(request);
WebKitWebDataSource* datasource;
datasource = webkit_web_data_source_new_with_loader(
WebKit::DocumentLoader::create(ResourceRequest(KURL(KURL(), String::fromUTF8(uri))),
SubstituteData()));
WebKitWebDataSourcePrivate* priv = datasource->priv;
priv->initialRequest = request;
return datasource;
}
/**
* webkit_web_data_source_get_web_frame
* @data_source: a #WebKitWebDataSource
*
* Returns the #WebKitWebFrame that represents this data source
*
* Return value: the #WebKitWebFrame that represents the @data_source. The
* #WebKitWebFrame is owned by WebKit and should not be freed or destroyed.
* This will return %NULL of the @data_source is not attached to a frame.
*
* Since: 1.1.14
*/
WebKitWebFrame* webkit_web_data_source_get_web_frame(WebKitWebDataSource* webDataSource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), NULL);
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
FrameLoader* frameLoader = priv->loader->frameLoader();
if (!frameLoader)
return NULL;
return static_cast<WebKit::FrameLoaderClient*>(frameLoader->client())->webFrame();
}
/**
* webkit_web_data_source_get_initial_request:
* @data_source: a #WebKitWebDataSource
*
* Returns a reference to the original request that was used to load the web
* content. The #WebKitNetworkRequest returned by this method is the request
* prior to the "committed" load state. See webkit_web_data_source_get_request
* for getting the "committed" request.
*
* Return value: the original #WebKitNetworkRequest
*
* Since: 1.1.14
*/
WebKitNetworkRequest* webkit_web_data_source_get_initial_request(WebKitWebDataSource* webDataSource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), NULL);
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
ResourceRequest request = priv->loader->originalRequest();
if (priv->initialRequest)
g_object_unref(priv->initialRequest);
priv->initialRequest = webkit_network_request_new_with_core_request(request);
return priv->initialRequest;
}
/**
* webkit_web_data_source_get_request:
* @data_source: a #WebKitWebDataSource
*
* Returns a #WebKitNetworkRequest that was used to create this
* #WebKitWebDataSource. The #WebKitNetworkRequest returned by this method is
* the request that was "committed", and hence, different from the request you
* get from the webkit_web_data_source_get_initial_request method.
*
* Return value: the #WebKitNetworkRequest that created the @data_source or
* %NULL if the @data_source is not attached to the frame or the frame hasn't
* been loaded.
*
* Since: 1.1.14
*/
WebKitNetworkRequest* webkit_web_data_source_get_request(WebKitWebDataSource* webDataSource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), NULL);
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
FrameLoader* frameLoader = priv->loader->frameLoader();
if (!frameLoader || !frameLoader->frameHasLoaded())
return NULL;
ResourceRequest request = priv->loader->request();
if (priv->networkRequest)
g_object_unref(priv->networkRequest);
priv->networkRequest = webkit_network_request_new_with_core_request(request);
return priv->networkRequest;
}
/**
* webkit_web_data_source_get_encoding:
* @data_source: a #WebKitWebDataSource
*
* Returns the text encoding name as set in the #WebKitWebView, or if not, the
* text encoding of the response.
*
* Return value: the encoding name of the #WebKitWebView or of the response.
*
* Since: 1.1.14
*/
G_CONST_RETURN gchar* webkit_web_data_source_get_encoding(WebKitWebDataSource* webDataSource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), NULL);
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
String textEncodingName = priv->loader->overrideEncoding();
if (!textEncodingName)
textEncodingName = priv->loader->response().textEncodingName();
CString encoding = textEncodingName.utf8();
g_free(priv->textEncoding);
priv->textEncoding = g_strdup(encoding.data());
return priv->textEncoding;
}
/**
* webkit_web_data_source_is_loading:
* @data_source: a #WebKitWebDataSource
*
* Determines whether the data source is in the process of loading its content.
*
* Return value: %TRUE if the @data_source is still loading, %FALSE otherwise
*
* Since: 1.1.14
*/
gboolean webkit_web_data_source_is_loading(WebKitWebDataSource* webDataSource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), NULL);
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
return priv->loader->isLoadingInAPISense();
}
/**
* webkit_web_data_source_get_data:
* @data_source: a #WebKitWebDataSource
*
* Returns the raw data that represents the the frame's content.The data will
* be incomplete until the data has finished loading. Returns %NULL if the web
* frame hasn't loaded any data. Use webkit_web_data_source_is_loading to test
* if data source is in the process of loading.
*
* Return value: a #GString which contains the raw data that represents the @data_source or %NULL if the
* @data_source hasn't loaded any data.
*
* Since: 1.1.14
*/
GString* webkit_web_data_source_get_data(WebKitWebDataSource* webDataSource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), NULL);
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
RefPtr<SharedBuffer> mainResourceData = priv->loader->mainResourceData();
if (!mainResourceData)
return NULL;
if (priv->data) {
g_string_free(priv->data, TRUE);
priv->data = NULL;
}
priv->data = g_string_new_len(mainResourceData->data(), mainResourceData->size());
return priv->data;
}
/**
* webkit_web_data_source_get_main_resource:
* @data_source: a #WebKitWebDataSource
*
* Returns the main resource of the @data_source
*
* Return value: a new #WebKitWebResource representing the main resource of
* the @data_source.
*
* Since: 1.1.14
*/
WebKitWebResource* webkit_web_data_source_get_main_resource(WebKitWebDataSource* webDataSource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), NULL);
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
if (priv->mainresource)
return priv->mainresource;
WebKitWebFrame* webFrame = webkit_web_data_source_get_web_frame(webDataSource);
WebKitWebView* webView = getViewFromFrame(webFrame);
priv->mainresource = WEBKIT_WEB_RESOURCE(g_object_ref(webkit_web_view_get_main_resource(webView)));
return priv->mainresource;
}
/**
* webkit_web_data_source_get_unreachable_uri:
* @data_source: a #WebKitWebDataSource
*
* Return the unreachable URI of @data_source. The @data_source will have an
* unreachable URL if it was created using #WebKitWebFrame's
* webkit_web_frame_load_alternate_html_string method.
*
* Return value: the unreachable URL of @data_source or %NULL if there is no unreachable URL.
*
* Since: 1.1.14
*/
G_CONST_RETURN gchar* webkit_web_data_source_get_unreachable_uri(WebKitWebDataSource* webDataSource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), NULL);
WebKitWebDataSourcePrivate* priv = webDataSource->priv;
const KURL& unreachableURL = priv->loader->unreachableURL();
if (unreachableURL.isEmpty())
return NULL;
g_free(priv->unreachableURL);
priv->unreachableURL = g_strdup(unreachableURL.string().utf8().data());
return priv->unreachableURL;
}
/**
* webkit_web_data_source_get_subresources
* @data_source: a #WebKitWebDataSource
*
* Gives you a #GList of #WebKitWebResource objects that compose the
* #WebView to which this #WebKitWebDataSource is attached.
*
* Return value: a #GList of #WebKitResource objects; the objects are
* owned by WebKit, but the GList must be freed.
*
* Since: 1.1.15
*/
GList* webkit_web_data_source_get_subresources(WebKitWebDataSource* webDataSource)
{
g_return_val_if_fail(WEBKIT_IS_WEB_DATA_SOURCE(webDataSource), NULL);
WebKitWebFrame* webFrame = webkit_web_data_source_get_web_frame(webDataSource);
WebKitWebView* webView = getViewFromFrame(webFrame);
return webkit_web_view_get_subresources(webView);
}