blob: c6c921a27689b29f11963fce3a2bec8468ad54c2 [file]
/*
* Copyright (C) 2012 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2,1 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 "WebKitWebPage.h"
#include "APIArray.h"
#include "APIDictionary.h"
#include "ImageOptions.h"
#include "InjectedBundle.h"
#include "WKBundleAPICast.h"
#include "WKBundleFrame.h"
#include "WebContextMenuItem.h"
#include "WebImage.h"
#include "WebKitConsoleMessagePrivate.h"
#include "WebKitContextMenuPrivate.h"
#include "WebKitDOMDocumentPrivate.h"
#include "WebKitFramePrivate.h"
#include "WebKitMarshal.h"
#include "WebKitPrivate.h"
#include "WebKitScriptWorldPrivate.h"
#include "WebKitURIRequestPrivate.h"
#include "WebKitURIResponsePrivate.h"
#include "WebKitWebEditorPrivate.h"
#include "WebKitWebHitTestResultPrivate.h"
#include "WebKitWebPagePrivate.h"
#include "WebProcess.h"
#include <WebCore/Document.h>
#include <WebCore/DocumentLoader.h>
#include <WebCore/Frame.h>
#include <WebCore/FrameDestructionObserver.h>
#include <WebCore/FrameView.h>
#include <WebCore/MainFrame.h>
#include <glib/gi18n-lib.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
using namespace WebKit;
using namespace WebCore;
enum {
DOCUMENT_LOADED,
SEND_REQUEST,
CONTEXT_MENU,
CONSOLE_MESSAGE_SENT,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_URI
};
struct _WebKitWebPagePrivate {
WebPage* webPage;
CString uri;
GRefPtr<WebKitWebEditor> webEditor;
};
static guint signals[LAST_SIGNAL] = { 0, };
WEBKIT_DEFINE_TYPE(WebKitWebPage, webkit_web_page, G_TYPE_OBJECT)
static void webFrameDestroyed(WebFrame*);
class WebKitFrameWrapper final: public FrameDestructionObserver {
public:
WebKitFrameWrapper(WebFrame& webFrame)
: FrameDestructionObserver(webFrame.coreFrame())
, m_webkitFrame(adoptGRef(webkitFrameCreate(&webFrame)))
{
}
WebKitFrame* webkitFrame() const { return m_webkitFrame.get(); }
private:
void frameDestroyed() override
{
FrameDestructionObserver::frameDestroyed();
webFrameDestroyed(webkitFrameGetWebFrame(m_webkitFrame.get()));
}
GRefPtr<WebKitFrame> m_webkitFrame;
};
typedef HashMap<WebFrame*, std::unique_ptr<WebKitFrameWrapper>> WebFrameMap;
static WebFrameMap& webFrameMap()
{
static NeverDestroyed<WebFrameMap> map;
return map;
}
static WebKitFrame* webkitFrameGetOrCreate(WebFrame* webFrame)
{
auto wrapperPtr = webFrameMap().get(webFrame);
if (wrapperPtr)
return wrapperPtr->webkitFrame();
std::unique_ptr<WebKitFrameWrapper> wrapper = std::make_unique<WebKitFrameWrapper>(*webFrame);
wrapperPtr = wrapper.get();
webFrameMap().set(webFrame, WTFMove(wrapper));
return wrapperPtr->webkitFrame();
}
static void webFrameDestroyed(WebFrame* webFrame)
{
webFrameMap().remove(webFrame);
}
static CString getProvisionalURLForFrame(WebFrame* webFrame)
{
DocumentLoader* documentLoader = webFrame->coreFrame()->loader().provisionalDocumentLoader();
if (!documentLoader->unreachableURL().isEmpty())
return documentLoader->unreachableURL().string().utf8();
return documentLoader->url().string().utf8();
}
static void webkitWebPageSetURI(WebKitWebPage* webPage, const CString& uri)
{
if (webPage->priv->uri == uri)
return;
webPage->priv->uri = uri;
g_object_notify(G_OBJECT(webPage), "uri");
}
static void webkitWebPageDidSendConsoleMessage(WebKitWebPage* webPage, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceID)
{
WebKitConsoleMessage consoleMessage(source, level, message, lineNumber, sourceID);
g_signal_emit(webPage, signals[CONSOLE_MESSAGE_SENT], 0, &consoleMessage);
}
static void didStartProvisionalLoadForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
{
if (!WKBundleFrameIsMainFrame(frame))
return;
webkitWebPageSetURI(WEBKIT_WEB_PAGE(clientInfo), getProvisionalURLForFrame(toImpl(frame)));
}
static void didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKTypeRef* /* userData */, const void *clientInfo)
{
if (!WKBundleFrameIsMainFrame(frame))
return;
webkitWebPageSetURI(WEBKIT_WEB_PAGE(clientInfo), getProvisionalURLForFrame(toImpl(frame)));
}
static void didSameDocumentNavigationForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKSameDocumentNavigationType, WKTypeRef* /* userData */, const void *clientInfo)
{
if (!WKBundleFrameIsMainFrame(frame))
return;
webkitWebPageSetURI(WEBKIT_WEB_PAGE(clientInfo), toImpl(frame)->coreFrame()->document()->url().string().utf8());
}
static void didFinishDocumentLoadForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKTypeRef*, const void *clientInfo)
{
if (!WKBundleFrameIsMainFrame(frame))
return;
g_signal_emit(WEBKIT_WEB_PAGE(clientInfo), signals[DOCUMENT_LOADED], 0);
}
static void didClearWindowObjectForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKBundleScriptWorldRef wkWorld, const void* clientInfo)
{
if (WebKitScriptWorld* world = webkitScriptWorldGet(toImpl(wkWorld)))
webkitScriptWorldWindowObjectCleared(world, WEBKIT_WEB_PAGE(clientInfo), webkitFrameGetOrCreate(toImpl(frame)));
}
static void didInitiateLoadForResource(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, bool /* pageLoadIsProvisional */, const void*)
{
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), toImpl(page));
message.set(String::fromUTF8("Frame"), toImpl(frame));
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
message.set(String::fromUTF8("Request"), toImpl(request));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidInitiateLoadForResource"), API::Dictionary::create(WTFMove(message)).ptr());
}
static WKURLRequestRef willSendRequestForFrame(WKBundlePageRef page, WKBundleFrameRef, uint64_t identifier, WKURLRequestRef wkRequest, WKURLResponseRef wkRedirectResponse, const void* clientInfo)
{
GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(wkRequest)->resourceRequest()));
const ResourceResponse& redirectResourceResponse = toImpl(wkRedirectResponse)->resourceResponse();
GRefPtr<WebKitURIResponse> redirectResponse = !redirectResourceResponse.isNull() ? adoptGRef(webkitURIResponseCreateForResourceResponse(redirectResourceResponse)) : nullptr;
gboolean returnValue;
g_signal_emit(WEBKIT_WEB_PAGE(clientInfo), signals[SEND_REQUEST], 0, request.get(), redirectResponse.get(), &returnValue);
if (returnValue)
return 0;
ResourceRequest resourceRequest;
webkitURIRequestGetResourceRequest(request.get(), resourceRequest);
resourceRequest.setInitiatingPageID(toImpl(page)->pageID());
Ref<API::URLRequest> newRequest = API::URLRequest::create(resourceRequest);
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), toImpl(page));
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
message.set(String::fromUTF8("Request"), newRequest.ptr());
if (!redirectResourceResponse.isNull())
message.set(String::fromUTF8("RedirectResponse"), toImpl(wkRedirectResponse));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidSendRequestForResource"), API::Dictionary::create(WTFMove(message)).ptr());
return toAPI(&newRequest.leakRef());
}
static void didReceiveResponseForResource(WKBundlePageRef page, WKBundleFrameRef, uint64_t identifier, WKURLResponseRef response, const void* clientInfo)
{
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), toImpl(page));
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
message.set(String::fromUTF8("Response"), toImpl(response));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidReceiveResponseForResource"), API::Dictionary::create(WTFMove(message)).ptr());
// Post on the console as well to be consistent with the inspector.
const ResourceResponse& resourceResponse = toImpl(response)->resourceResponse();
if (resourceResponse.httpStatusCode() >= 400) {
StringBuilder errorMessage;
errorMessage.appendLiteral("Failed to load resource: the server responded with a status of ");
errorMessage.appendNumber(resourceResponse.httpStatusCode());
errorMessage.appendLiteral(" (");
errorMessage.append(resourceResponse.httpStatusText());
errorMessage.append(')');
webkitWebPageDidSendConsoleMessage(WEBKIT_WEB_PAGE(clientInfo), MessageSource::Network, MessageLevel::Error, errorMessage.toString(), 0, resourceResponse.url().string());
}
}
static void didReceiveContentLengthForResource(WKBundlePageRef page, WKBundleFrameRef, uint64_t identifier, uint64_t length, const void*)
{
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), toImpl(page));
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
message.set(String::fromUTF8("ContentLength"), API::UInt64::create(length));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidReceiveContentLengthForResource"), API::Dictionary::create(WTFMove(message)).ptr());
}
static void didFinishLoadForResource(WKBundlePageRef page, WKBundleFrameRef, uint64_t identifier, const void*)
{
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), toImpl(page));
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidFinishLoadForResource"), API::Dictionary::create(WTFMove(message)).ptr());
}
static void didFailLoadForResource(WKBundlePageRef page, WKBundleFrameRef, uint64_t identifier, WKErrorRef error, const void* clientInfo)
{
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), toImpl(page));
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
message.set(String::fromUTF8("Error"), toImpl(error));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidFailLoadForResource"), API::Dictionary::create(WTFMove(message)).ptr());
// Post on the console as well to be consistent with the inspector.
const ResourceError& resourceError = toImpl(error)->platformError();
if (!resourceError.isCancellation()) {
StringBuilder errorMessage;
errorMessage.appendLiteral("Failed to load resource");
if (!resourceError.localizedDescription().isEmpty()) {
errorMessage.appendLiteral(": ");
errorMessage.append(resourceError.localizedDescription());
}
webkitWebPageDidSendConsoleMessage(WEBKIT_WEB_PAGE(clientInfo), MessageSource::Network, MessageLevel::Error, errorMessage.toString(), 0, resourceError.failingURL());
}
}
class PageContextMenuClient final : public API::InjectedBundle::PageContextMenuClient {
public:
explicit PageContextMenuClient(WebKitWebPage* webPage)
: m_webPage(webPage)
{
}
private:
bool getCustomMenuFromDefaultItems(WebPage&, const WebCore::HitTestResult& hitTestResult, const Vector<WebCore::ContextMenuItem>& defaultMenu, Vector<WebContextMenuItemData>& newMenu, RefPtr<API::Object>& userData) override
{
GRefPtr<WebKitContextMenu> contextMenu = adoptGRef(webkitContextMenuCreate(kitItems(defaultMenu)));
GRefPtr<WebKitWebHitTestResult> webHitTestResult = adoptGRef(webkitWebHitTestResultCreate(hitTestResult));
gboolean returnValue;
g_signal_emit(m_webPage, signals[CONTEXT_MENU], 0, contextMenu.get(), webHitTestResult.get(), &returnValue);
if (GVariant* variant = webkit_context_menu_get_user_data(contextMenu.get())) {
GUniquePtr<gchar> dataString(g_variant_print(variant, TRUE));
userData = API::String::create(String::fromUTF8(dataString.get()));
}
if (!returnValue)
return false;
webkitContextMenuPopulate(contextMenu.get(), newMenu);
return true;
}
WebKitWebPage* m_webPage;
};
class PageUIClient final : public API::InjectedBundle::PageUIClient {
public:
explicit PageUIClient(WebKitWebPage* webPage)
: m_webPage(webPage)
{
}
private:
void willAddMessageToConsole(WebPage*, MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, unsigned /*columnNumber*/, const String& sourceID) override
{
webkitWebPageDidSendConsoleMessage(m_webPage, source, level, message, lineNumber, sourceID);
}
WebKitWebPage* m_webPage;
};
static void webkitWebPageGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
{
WebKitWebPage* webPage = WEBKIT_WEB_PAGE(object);
switch (propId) {
case PROP_URI:
g_value_set_string(value, webkit_web_page_get_uri(webPage));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
}
}
static void webkit_web_page_class_init(WebKitWebPageClass* klass)
{
GObjectClass* gObjectClass = G_OBJECT_CLASS(klass);
gObjectClass->get_property = webkitWebPageGetProperty;
/**
* WebKitWebPage:uri:
*
* The current active URI of the #WebKitWebPage.
*/
g_object_class_install_property(
gObjectClass,
PROP_URI,
g_param_spec_string(
"uri",
_("URI"),
_("The current active URI of the web page"),
0,
WEBKIT_PARAM_READABLE));
/**
* WebKitWebPage::document-loaded:
* @web_page: the #WebKitWebPage on which the signal is emitted
*
* This signal is emitted when the DOM document of a #WebKitWebPage has been
* loaded.
*
* You can wait for this signal to get the DOM document with
* webkit_web_page_get_dom_document().
*/
signals[DOCUMENT_LOADED] = g_signal_new(
"document-loaded",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
0, 0, 0,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* WebKitWebPage::send-request:
* @web_page: the #WebKitWebPage on which the signal is emitted
* @request: a #WebKitURIRequest
* @redirected_response: a #WebKitURIResponse, or %NULL
*
* This signal is emitted when @request is about to be sent to
* the server. This signal can be used to modify the #WebKitURIRequest
* that will be sent to the server. You can also cancel the resource load
* operation by connecting to this signal and returning %TRUE.
*
* In case of a server redirection this signal is
* emitted again with the @request argument containing the new
* request to be sent to the server due to the redirection and the
* @redirected_response parameter containing the response
* received by the server for the initial request.
*
* Returns: %TRUE to stop other handlers from being invoked for the event.
* %FALSE to continue emission of the event.
*/
signals[SEND_REQUEST] = g_signal_new(
"send-request",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled, 0,
webkit_marshal_BOOLEAN__OBJECT_OBJECT,
G_TYPE_BOOLEAN, 2,
WEBKIT_TYPE_URI_REQUEST,
WEBKIT_TYPE_URI_RESPONSE);
/**
* WebKitWebPage::context-menu:
* @web_page: the #WebKitWebPage on which the signal is emitted
* @context_menu: the proposed #WebKitContextMenu
* @hit_test_result: a #WebKitWebHitTestResult
*
* Emmited before a context menu is displayed in the UI Process to
* give the application a chance to customize the proposed menu,
* build its own context menu or pass user data to the UI Process.
* This signal is useful when the information available in the UI Process
* is not enough to build or customize the context menu, for example, to
* add menu entries depending on the #WebKitDOMNode at the coordinates of the
* @hit_test_result. Otherwise, it's recommened to use #WebKitWebView::context-menu
* signal instead.
*
* Returns: %TRUE if the proposed @context_menu has been modified, or %FALSE otherwise.
*
* Since: 2.8
*/
signals[CONTEXT_MENU] = g_signal_new(
"context-menu",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled, 0,
webkit_marshal_BOOLEAN__OBJECT_OBJECT,
G_TYPE_BOOLEAN, 2,
WEBKIT_TYPE_CONTEXT_MENU,
WEBKIT_TYPE_WEB_HIT_TEST_RESULT);
/**
* WebKitWebPage::console-message-sent:
* @web_page: the #WebKitWebPage on which the signal is emitted
* @console_message: the #WebKitConsoleMessage
*
* Emmited when a message is sent to the console. This can be a message
* produced by the use of JavaScript console API, a javascript exception,
* a security error or other errors, warnings, debug or log messages.
* The @console_message contains information of the message.
*
* Since: 2.12
*/
signals[CONSOLE_MESSAGE_SENT] = g_signal_new(
"console-message-sent",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
0, 0, nullptr,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1,
WEBKIT_TYPE_CONSOLE_MESSAGE | G_SIGNAL_TYPE_STATIC_SCOPE);
}
WebPage* webkitWebPageGetPage(WebKitWebPage *webPage)
{
return webPage->priv->webPage;
}
WebKitWebPage* webkitWebPageCreate(WebPage* webPage)
{
WebKitWebPage* page = WEBKIT_WEB_PAGE(g_object_new(WEBKIT_TYPE_WEB_PAGE, NULL));
page->priv->webPage = webPage;
WKBundlePageLoaderClientV6 loaderClient = {
{
6, // version
page, // clientInfo
},
didStartProvisionalLoadForFrame,
didReceiveServerRedirectForProvisionalLoadForFrame,
0, // didFailProvisionalLoadWithErrorForFrame
0, // didCommitLoadForFrame
didFinishDocumentLoadForFrame,
0, // didFinishLoadForFrame
0, // didFailLoadWithErrorForFrame
didSameDocumentNavigationForFrame,
0, // didReceiveTitleForFrame
0, // didFirstLayoutForFrame
0, // didFirstVisuallyNonEmptyLayoutForFrame
0, // didRemoveFrameFromHierarchy,
0, // didDisplayInsecureContentForFrame
0, // didRunInsecureContentForFrame
didClearWindowObjectForFrame,
0, // didCancelClientRedirectForFrame
0, // willPerformClientRedirectForFrame
0, // didHandleOnloadEventsForFrame
0, // didLayoutForFrame
0, // didNewFirstVisuallyNonEmptyLayout
0, // didDetectXSSForFrame
0, // shouldGoToBackForwardListItem
0, // globalObjectIsAvailableForFrame
0, // willDisconnectDOMWindowExtensionFromGlobalObject
0, // didReconnectDOMWindowExtensionToGlobalObject
0, // willDestroyGlobalObjectForDOMWindowExtension
0, // didFinishProgress
0, // shouldForceUniversalAccessFromLocalURL
0, // didReceiveIntentForFrame_unavailable
0, // registerIntentServiceForFrame_unavailable
0, // didLayout
0, // featuresUsedInPage
0, // willLoadURLRequest
0, // willLoadDataRequest
};
WKBundlePageSetPageLoaderClient(toAPI(webPage), &loaderClient.base);
WKBundlePageResourceLoadClientV1 resourceLoadClient = {
{
1, // version
page, // clientInfo
},
didInitiateLoadForResource,
willSendRequestForFrame,
didReceiveResponseForResource,
didReceiveContentLengthForResource,
didFinishLoadForResource,
didFailLoadForResource,
0, // shouldCacheResponse
0 // shouldUseCredentialStorage
};
WKBundlePageSetResourceLoadClient(toAPI(webPage), &resourceLoadClient.base);
webPage->setInjectedBundleContextMenuClient(std::make_unique<PageContextMenuClient>(page));
webPage->setInjectedBundleUIClient(std::make_unique<PageUIClient>(page));
return page;
}
void webkitWebPageDidReceiveMessage(WebKitWebPage* page, const String& messageName, API::Dictionary& message)
{
if (messageName == String("GetSnapshot")) {
SnapshotOptions snapshotOptions = static_cast<SnapshotOptions>(static_cast<API::UInt64*>(message.get("SnapshotOptions"))->value());
uint64_t callbackID = static_cast<API::UInt64*>(message.get("CallbackID"))->value();
SnapshotRegion region = static_cast<SnapshotRegion>(static_cast<API::UInt64*>(message.get("SnapshotRegion"))->value());
bool transparentBackground = static_cast<API::Boolean*>(message.get("TransparentBackground"))->value();
RefPtr<WebImage> snapshotImage;
WebPage* webPage = page->priv->webPage;
if (WebCore::FrameView* frameView = webPage->mainFrameView()) {
WebCore::IntRect snapshotRect;
switch (region) {
case SnapshotRegionVisible:
snapshotRect = frameView->visibleContentRect();
break;
case SnapshotRegionFullDocument:
snapshotRect = WebCore::IntRect(WebCore::IntPoint(0, 0), frameView->contentsSize());
break;
default:
ASSERT_NOT_REACHED();
}
if (!snapshotRect.isEmpty()) {
Color savedBackgroundColor;
if (transparentBackground) {
savedBackgroundColor = frameView->baseBackgroundColor();
frameView->setBaseBackgroundColor(Color::transparent);
}
snapshotImage = webPage->scaledSnapshotWithOptions(snapshotRect, 1, snapshotOptions | SnapshotOptionsShareable);
if (transparentBackground)
frameView->setBaseBackgroundColor(savedBackgroundColor);
}
}
API::Dictionary::MapType messageReply;
messageReply.set("Page", webPage);
messageReply.set("CallbackID", API::UInt64::create(callbackID));
messageReply.set("Snapshot", snapshotImage);
WebProcess::singleton().injectedBundle()->postMessage("WebPage.DidGetSnapshot", API::Dictionary::create(WTFMove(messageReply)).ptr());
} else
ASSERT_NOT_REACHED();
}
/**
* webkit_web_page_get_dom_document:
* @web_page: a #WebKitWebPage
*
* Get the #WebKitDOMDocument currently loaded in @web_page
*
* Returns: (transfer none): the #WebKitDOMDocument currently loaded, or %NULL
* if no document is currently loaded.
*/
WebKitDOMDocument* webkit_web_page_get_dom_document(WebKitWebPage* webPage)
{
g_return_val_if_fail(WEBKIT_IS_WEB_PAGE(webPage), 0);
MainFrame* coreFrame = webPage->priv->webPage->mainFrame();
if (!coreFrame)
return 0;
return kit(coreFrame->document());
}
/**
* webkit_web_page_get_id:
* @web_page: a #WebKitWebPage
*
* Get the identifier of the #WebKitWebPage
*
* Returns: the identifier of @web_page
*/
guint64 webkit_web_page_get_id(WebKitWebPage* webPage)
{
g_return_val_if_fail(WEBKIT_IS_WEB_PAGE(webPage), 0);
return webPage->priv->webPage->pageID();
}
/**
* webkit_web_page_get_uri:
* @web_page: a #WebKitWebPage
*
* Returns the current active URI of @web_page.
*
* You can monitor the active URI by connecting to the notify::uri
* signal of @web_page.
*
* Returns: the current active URI of @web_view or %NULL if nothing has been
* loaded yet.
*/
const gchar* webkit_web_page_get_uri(WebKitWebPage* webPage)
{
g_return_val_if_fail(WEBKIT_IS_WEB_PAGE(webPage), 0);
return webPage->priv->uri.data();
}
/**
* webkit_web_page_get_main_frame:
* @web_page: a #WebKitWebPage
*
* Returns the main frame of a #WebKitWebPage.
*
* Returns: (transfer none): the #WebKitFrame that is the main frame of @web_page
*
* Since: 2.2
*/
WebKitFrame* webkit_web_page_get_main_frame(WebKitWebPage* webPage)
{
g_return_val_if_fail(WEBKIT_IS_WEB_PAGE(webPage), 0);
return webkitFrameGetOrCreate(webPage->priv->webPage->mainWebFrame());
}
/**
* webkit_web_page_get_editor:
* @web_page: a #WebKitWebPage
*
* Gets the #WebKitWebEditor of a #WebKitWebPage.
*
* Returns: (transfer none): the #WebKitWebEditor
*
* Since: 2.10
*/
WebKitWebEditor* webkit_web_page_get_editor(WebKitWebPage* webPage)
{
g_return_val_if_fail(WEBKIT_IS_WEB_PAGE(webPage), nullptr);
if (!webPage->priv->webEditor)
webPage->priv->webEditor = adoptGRef(webkitWebEditorCreate(webPage));
return webPage->priv->webEditor.get();
}