#include "config.h"
#include "WebKitWebPage.h"
#include "APIArray.h"
#include "APIDictionary.h"
#include "APIError.h"
#include "APINumber.h"
#include "APIString.h"
#include "APIURLRequest.h"
#include "APIURLResponse.h"
#include "ImageOptions.h"
#include "InjectedBundle.h"
#include "WebContextMenuItem.h"
#include "WebImage.h"
#include "WebKitConsoleMessagePrivate.h"
#include "WebKitContextMenuPrivate.h"
#include "WebKitDOMDocumentPrivate.h"
#include "WebKitDOMElementPrivate.h"
#include "WebKitDOMNodePrivate.h"
#include "WebKitFramePrivate.h"
#include "WebKitPrivate.h"
#include "WebKitScriptWorldPrivate.h"
#include "WebKitURIRequestPrivate.h"
#include "WebKitURIResponsePrivate.h"
#include "WebKitUserMessagePrivate.h"
#include "WebKitWebEditorPrivate.h"
#include "WebKitWebHitTestResultPrivate.h"
#include "WebKitWebPagePrivate.h"
#include "WebKitWebProcessEnumTypes.h"
#include "WebPageProxyMessages.h"
#include "WebProcess.h"
#include <WebCore/Document.h>
#include <WebCore/DocumentLoader.h>
#include <WebCore/Frame.h>
#include <WebCore/FrameDestructionObserver.h>
#include <WebCore/FrameLoader.h>
#include <WebCore/FrameView.h>
#include <WebCore/HTMLFormElement.h>
#include <glib/gi18n-lib.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/glib/WTFGType.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,
FORM_CONTROLS_ASSOCIATED,
FORM_CONTROLS_ASSOCIATED_FOR_FRAME,
WILL_SUBMIT_FORM,
USER_MESSAGE_RECEIVED,
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 {
WTF_MAKE_FAST_ALLOCATED;
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 = makeUnique<WebKitFrameWrapper>(*webFrame);
wrapperPtr = wrapper.get();
webFrameMap().set(webFrame, WTFMove(wrapper));
return wrapperPtr->webkitFrame();
}
static void webFrameDestroyed(WebFrame* webFrame)
{
webFrameMap().remove(webFrame);
}
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);
}
class PageLoaderClient final : public API::InjectedBundle::PageLoaderClient {
public:
explicit PageLoaderClient(WebKitWebPage* webPage)
: m_webPage(webPage)
{
}
private:
static CString getDocumentLoaderURL(DocumentLoader* documentLoader)
{
ASSERT(documentLoader);
if (!documentLoader->unreachableURL().isEmpty())
return documentLoader->unreachableURL().string().utf8();
return documentLoader->url().string().utf8();
}
void didStartProvisionalLoadForFrame(WebPage&, WebFrame& frame, RefPtr<API::Object>&) override
{
if (!frame.isMainFrame())
return;
webkitWebPageSetURI(m_webPage, getDocumentLoaderURL(frame.coreFrame()->loader().provisionalDocumentLoader()));
}
void didReceiveServerRedirectForProvisionalLoadForFrame(WebPage&, WebFrame& frame, RefPtr<API::Object>&) override
{
if (!frame.isMainFrame())
return;
webkitWebPageSetURI(m_webPage, getDocumentLoaderURL(frame.coreFrame()->loader().provisionalDocumentLoader()));
}
void didSameDocumentNavigationForFrame(WebPage&, WebFrame& frame, SameDocumentNavigationType, RefPtr<API::Object>&) override
{
if (!frame.isMainFrame())
return;
webkitWebPageSetURI(m_webPage, frame.coreFrame()->document()->url().string().utf8());
}
void didCommitLoadForFrame(WebPage&, WebFrame& frame, RefPtr<API::Object>&) override
{
if (!frame.isMainFrame())
return;
webkitWebPageSetURI(m_webPage, getDocumentLoaderURL(frame.coreFrame()->loader().documentLoader()));
}
void didFinishDocumentLoadForFrame(WebPage&, WebFrame& frame, RefPtr<API::Object>&) override
{
if (!frame.isMainFrame())
return;
g_signal_emit(m_webPage, signals[DOCUMENT_LOADED], 0);
}
void didClearWindowObjectForFrame(WebPage&, WebFrame& frame, DOMWrapperWorld& world) override
{
auto injectedWorld = InjectedBundleScriptWorld::getOrCreate(world);
if (auto* wkWorld = webkitScriptWorldGet(injectedWorld.ptr()))
webkitScriptWorldWindowObjectCleared(wkWorld, m_webPage, webkitFrameGetOrCreate(&frame));
}
WebKitWebPage* m_webPage;
};
class PageResourceLoadClient final : public API::InjectedBundle::ResourceLoadClient {
public:
explicit PageResourceLoadClient(WebKitWebPage* webPage)
: m_webPage(webPage)
{
}
private:
void didInitiateLoadForResource(WebPage& page, WebFrame& frame, uint64_t identifier, const ResourceRequest& request, bool) override
{
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), &page);
message.set(String::fromUTF8("Frame"), &frame);
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
message.set(String::fromUTF8("Request"), API::URLRequest::create(request));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidInitiateLoadForResource"), API::Dictionary::create(WTFMove(message)).ptr());
}
void willSendRequestForFrame(WebPage& page, WebFrame&, uint64_t identifier, ResourceRequest& resourceRequest, const ResourceResponse& redirectResourceResponse) override
{
GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(resourceRequest));
GRefPtr<WebKitURIResponse> redirectResponse = !redirectResourceResponse.isNull() ? adoptGRef(webkitURIResponseCreateForResourceResponse(redirectResourceResponse)) : nullptr;
gboolean returnValue;
g_signal_emit(m_webPage, signals[SEND_REQUEST], 0, request.get(), redirectResponse.get(), &returnValue);
if (returnValue) {
resourceRequest = { };
return;
}
webkitURIRequestGetResourceRequest(request.get(), resourceRequest);
resourceRequest.setInitiatingPageID(page.webPageProxyIdentifier().toUInt64());
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), &page);
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
message.set(String::fromUTF8("Request"), API::URLRequest::create(resourceRequest));
if (!redirectResourceResponse.isNull())
message.set(String::fromUTF8("RedirectResponse"), API::URLResponse::create(redirectResourceResponse));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidSendRequestForResource"), API::Dictionary::create(WTFMove(message)).ptr());
}
void didReceiveResponseForResource(WebPage& page, WebFrame&, uint64_t identifier, const ResourceResponse& response) override
{
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), &page);
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
message.set(String::fromUTF8("Response"), API::URLResponse::create(response));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidReceiveResponseForResource"), API::Dictionary::create(WTFMove(message)).ptr());
if (response.httpStatusCode() >= 400) {
StringBuilder errorMessage;
errorMessage.appendLiteral("Failed to load resource: the server responded with a status of ");
errorMessage.appendNumber(response.httpStatusCode());
errorMessage.appendLiteral(" (");
errorMessage.append(response.httpStatusText());
errorMessage.append(')');
webkitWebPageDidSendConsoleMessage(m_webPage, MessageSource::Network, MessageLevel::Error, errorMessage.toString(), 0, response.url().string());
}
}
void didReceiveContentLengthForResource(WebPage& page, WebFrame&, uint64_t identifier, uint64_t contentLength) override
{
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), &page);
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
message.set(String::fromUTF8("ContentLength"), API::UInt64::create(contentLength));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidReceiveContentLengthForResource"), API::Dictionary::create(WTFMove(message)).ptr());
}
void didFinishLoadForResource(WebPage& page, WebFrame&, uint64_t identifier) override
{
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), &page);
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidFinishLoadForResource"), API::Dictionary::create(WTFMove(message)).ptr());
}
void didFailLoadForResource(WebPage& page, WebFrame&, uint64_t identifier, const ResourceError& error) override
{
API::Dictionary::MapType message;
message.set(String::fromUTF8("Page"), &page);
message.set(String::fromUTF8("Identifier"), API::UInt64::create(identifier));
message.set(String::fromUTF8("Error"), API::Error::create(error));
WebProcess::singleton().injectedBundle()->postMessage(String::fromUTF8("WebPage.DidFailLoadForResource"), API::Dictionary::create(WTFMove(message)).ptr());
if (!error.isCancellation()) {
StringBuilder errorMessage;
errorMessage.appendLiteral("Failed to load resource");
if (!error.localizedDescription().isEmpty()) {
errorMessage.appendLiteral(": ");
errorMessage.append(error.localizedDescription());
}
webkitWebPageDidSendConsoleMessage(m_webPage, MessageSource::Network, MessageLevel::Error, errorMessage.toString(), 0, error.failingURL().string());
}
}
WebKitWebPage* m_webPage;
};
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 , const String& sourceID) override
{
webkitWebPageDidSendConsoleMessage(m_webPage, source, level, message, lineNumber, sourceID);
}
WebKitWebPage* m_webPage;
};
class PageFormClient final : public API::InjectedBundle::FormClient {
public:
explicit PageFormClient(WebKitWebPage* webPage)
: m_webPage(webPage)
{
}
void willSubmitForm(WebPage*, HTMLFormElement* formElement, WebFrame* frame, WebFrame* sourceFrame, const Vector<std::pair<String, String>>& values, RefPtr<API::Object>&) override
{
fireFormSubmissionEvent(WEBKIT_FORM_SUBMISSION_WILL_COMPLETE, formElement, frame, sourceFrame, values);
}
void willSendSubmitEvent(WebPage*, HTMLFormElement* formElement, WebFrame* frame, WebFrame* sourceFrame, const Vector<std::pair<String, String>>& values) override
{
fireFormSubmissionEvent(WEBKIT_FORM_SUBMISSION_WILL_SEND_DOM_EVENT, formElement, frame, sourceFrame, values);
}
void didAssociateFormControls(WebPage*, const Vector<RefPtr<Element>>& elements, WebFrame* frame) override
{
GRefPtr<GPtrArray> formElements = adoptGRef(g_ptr_array_sized_new(elements.size()));
for (size_t i = 0; i < elements.size(); ++i)
g_ptr_array_add(formElements.get(), WebKit::kit(elements[i].get()));
g_signal_emit(m_webPage, signals[FORM_CONTROLS_ASSOCIATED], 0, formElements.get());
g_signal_emit(m_webPage, signals[FORM_CONTROLS_ASSOCIATED_FOR_FRAME], 0, formElements.get(), webkitFrameGetOrCreate(frame));
}
bool shouldNotifyOnFormChanges(WebPage*) override { return true; }
private:
void fireFormSubmissionEvent(WebKitFormSubmissionStep step, HTMLFormElement* formElement, WebFrame* frame, WebFrame* sourceFrame, const Vector<std::pair<String, String>>& values)
{
WebKitFrame* webkitTargetFrame = webkitFrameGetOrCreate(frame);
WebKitFrame* webkitSourceFrame = webkitFrameGetOrCreate(sourceFrame);
GRefPtr<GPtrArray> textFieldNames = adoptGRef(g_ptr_array_new_full(values.size(), g_free));
GRefPtr<GPtrArray> textFieldValues = adoptGRef(g_ptr_array_new_full(values.size(), g_free));
for (auto& pair : values) {
g_ptr_array_add(textFieldNames.get(), g_strdup(pair.first.utf8().data()));
g_ptr_array_add(textFieldValues.get(), g_strdup(pair.second.utf8().data()));
}
g_signal_emit(m_webPage, signals[WILL_SUBMIT_FORM], 0, WEBKIT_DOM_ELEMENT(WebKit::kit(static_cast<Node*>(formElement))), step, webkitSourceFrame, webkitTargetFrame, textFieldNames.get(), textFieldValues.get());
}
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;
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));
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);
signals[SEND_REQUEST] = g_signal_new(
"send-request",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 2,
WEBKIT_TYPE_URI_REQUEST,
WEBKIT_TYPE_URI_RESPONSE);
signals[CONTEXT_MENU] = g_signal_new(
"context-menu",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 2,
WEBKIT_TYPE_CONTEXT_MENU,
WEBKIT_TYPE_WEB_HIT_TEST_RESULT);
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);
signals[FORM_CONTROLS_ASSOCIATED] = g_signal_new(
"form-controls-associated",
G_TYPE_FROM_CLASS(klass),
static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED),
0, 0, nullptr,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1,
G_TYPE_PTR_ARRAY);
signals[FORM_CONTROLS_ASSOCIATED_FOR_FRAME] = g_signal_new(
"form-controls-associated-for-frame",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
0, 0, nullptr,
g_cclosure_marshal_generic,
G_TYPE_NONE, 2,
G_TYPE_PTR_ARRAY,
WEBKIT_TYPE_FRAME);
signals[WILL_SUBMIT_FORM] = g_signal_new(
"will-submit-form",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
0, 0, nullptr,
g_cclosure_marshal_generic,
G_TYPE_NONE, 6,
WEBKIT_DOM_TYPE_ELEMENT,
WEBKIT_TYPE_FORM_SUBMISSION_STEP,
WEBKIT_TYPE_FRAME,
WEBKIT_TYPE_FRAME,
G_TYPE_PTR_ARRAY,
G_TYPE_PTR_ARRAY);
signals[USER_MESSAGE_RECEIVED] = g_signal_new(
"user-message-received",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_USER_MESSAGE);
}
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;
webPage->setInjectedBundleResourceLoadClient(makeUnique<PageResourceLoadClient>(page));
webPage->setInjectedBundlePageLoaderClient(makeUnique<PageLoaderClient>(page));
webPage->setInjectedBundleContextMenuClient(makeUnique<PageContextMenuClient>(page));
webPage->setInjectedBundleUIClient(makeUnique<PageUIClient>(page));
webPage->setInjectedBundleFormClient(makeUnique<PageFormClient>(page));
return page;
}
void webkitWebPageDidReceiveMessage(WebKitWebPage* page, const String& messageName, API::Dictionary& message)
{
#if PLATFORM(GTK)
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::transparentBlack);
}
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
#endif
ASSERT_NOT_REACHED();
}
void webkitWebPageDidReceiveUserMessage(WebKitWebPage* webPage, UserMessage&& message, CompletionHandler<void(UserMessage&&)>&& completionHandler)
{
GRefPtr<WebKitUserMessage> userMessage = webkitUserMessageCreate(WTFMove(message), WTFMove(completionHandler));
gboolean returnValue;
g_signal_emit(webPage, signals[USER_MESSAGE_RECEIVED], 0, userMessage.get(), &returnValue);
}
WebKitDOMDocument* webkit_web_page_get_dom_document(WebKitWebPage* webPage)
{
g_return_val_if_fail(WEBKIT_IS_WEB_PAGE(webPage), nullptr);
if (auto* coreFrame = webPage->priv->webPage->mainFrame())
return kit(coreFrame->document());
return nullptr;
}
guint64 webkit_web_page_get_id(WebKitWebPage* webPage)
{
g_return_val_if_fail(WEBKIT_IS_WEB_PAGE(webPage), 0);
return webPage->priv->webPage->identifier().toUInt64();
}
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();
}
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());
}
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();
}
void webkit_web_page_send_message_to_view(WebKitWebPage* webPage, WebKitUserMessage* message, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_PAGE(webPage));
g_return_if_fail(WEBKIT_IS_USER_MESSAGE(message));
GRefPtr<WebKitUserMessage> adoptedMessage = message;
if (!callback) {
webPage->priv->webPage->send(Messages::WebPageProxy::SendMessageToWebView(webkitUserMessageGetMessage(message)));
return;
}
GRefPtr<GTask> task = adoptGRef(g_task_new(webPage, cancellable, callback, userData));
CompletionHandler<void(UserMessage&&)> completionHandler = [task = WTFMove(task)](UserMessage&& replyMessage) {
switch (replyMessage.type) {
case UserMessage::Type::Null:
g_task_return_new_error(task.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED, _("Operation was cancelled"));
break;
case UserMessage::Type::Message:
g_task_return_pointer(task.get(), g_object_ref_sink(webkitUserMessageCreate(WTFMove(replyMessage))), static_cast<GDestroyNotify>(g_object_unref));
break;
case UserMessage::Type::Error:
g_task_return_new_error(task.get(), WEBKIT_USER_MESSAGE_ERROR, replyMessage.errorCode, _("Message %s was not handled"), replyMessage.name.data());
break;
}
};
webPage->priv->webPage->sendWithAsyncReply(Messages::WebPageProxy::SendMessageToWebViewWithReply(webkitUserMessageGetMessage(message)), WTFMove(completionHandler));
}
WebKitUserMessage* webkit_web_page_send_message_to_view_finish(WebKitWebPage* webPage, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_PAGE(webPage), nullptr);
g_return_val_if_fail(g_task_is_valid(result, webPage), nullptr);
return WEBKIT_USER_MESSAGE(g_task_propagate_pointer(G_TASK(result), error));
}