/* * 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 "WebKitDOMElementPrivate.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 #include #include #include #include #include #include #include #include #include using namespace WebKit; using namespace WebCore; enum { DOCUMENT_LOADED, SEND_REQUEST, CONTEXT_MENU, CONSOLE_MESSAGE_SENT, FORM_CONTROLS_ASSOCIATED, LAST_SIGNAL }; enum { PROP_0, PROP_URI }; struct _WebKitWebPagePrivate { WebPage* webPage; CString uri; GRefPtr 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 m_webkitFrame; }; typedef HashMap> WebFrameMap; static WebFrameMap& webFrameMap() { static NeverDestroyed map; return map; } static WebKitFrame* webkitFrameGetOrCreate(WebFrame* webFrame) { auto wrapperPtr = webFrameMap().get(webFrame); if (wrapperPtr) return wrapperPtr->webkitFrame(); std::unique_ptr wrapper = std::make_unique(*webFrame); wrapperPtr = wrapper.get(); webFrameMap().set(webFrame, WTFMove(wrapper)); return wrapperPtr->webkitFrame(); } static void webFrameDestroyed(WebFrame* webFrame) { webFrameMap().remove(webFrame); } static CString getDocumentLoaderURL(DocumentLoader* documentLoader) { ASSERT(documentLoader); 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), getDocumentLoaderURL(toImpl(frame)->coreFrame()->loader().provisionalDocumentLoader())); } static void didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKTypeRef* /* userData */, const void *clientInfo) { if (!WKBundleFrameIsMainFrame(frame)) return; webkitWebPageSetURI(WEBKIT_WEB_PAGE(clientInfo), getDocumentLoaderURL(toImpl(frame)->coreFrame()->loader().provisionalDocumentLoader())); } 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 didCommitLoadForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKTypeRef* /* userData */, const void* clientInfo) { if (!WKBundleFrameIsMainFrame(frame)) return; webkitWebPageSetURI(WEBKIT_WEB_PAGE(clientInfo), getDocumentLoaderURL(toImpl(frame)->coreFrame()->loader().documentLoader())); } 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 request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(wkRequest)->resourceRequest())); const ResourceResponse& redirectResourceResponse = toImpl(wkRedirectResponse)->resourceResponse(); GRefPtr 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 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& defaultMenu, Vector& newMenu, RefPtr& userData) override { GRefPtr contextMenu = adoptGRef(webkitContextMenuCreate(kitItems(defaultMenu))); GRefPtr 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 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; }; class FormClient final : public API::InjectedBundle::FormClient { public: explicit FormClient(WebKitWebPage* webPage) : m_webPage(webPage) { } void didAssociateFormControls(WebPage*, const Vector>& elements) override { GRefPtr 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()); } bool shouldNotifyOnFormChanges(WebPage*) override { return true; } private: 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); /** * WebKitWebPage::form-controls-associated: * @web_page: the #WebKitWebPage on which the signal is emitted * @elements: (element-type WebKitDOMElement) (transfer none): a #GPtrArray of * #WebKitDOMElement with the list of forms in the page * * Emitted after form elements (or form associated elements) are associated to a particular web * page. This is useful to implement form autofilling for web pages where form fields are added * dynamically. This signal might be emitted multiple times for the same web page. * * Note that this signal could be also emitted when form controls are moved between forms. In * that case, the @elements array carries the list of those elements which have moved. * * Clients should take a reference to the members of the @elements array if it is desired to * keep them alive after the signal handler returns. * * Since: 2.16 */ signals[FORM_CONTROLS_ASSOCIATED] = g_signal_new( "form-controls-associated", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, 0, nullptr, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_PTR_ARRAY); } 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 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(page)); webPage->setInjectedBundleUIClient(std::make_unique(page)); webPage->setInjectedBundleFormClient(std::make_unique(page)); return page; } void webkitWebPageDidReceiveMessage(WebKitWebPage* page, const String& messageName, API::Dictionary& message) { if (messageName == String("GetSnapshot")) { SnapshotOptions snapshotOptions = static_cast(static_cast(message.get("SnapshotOptions"))->value()); uint64_t callbackID = static_cast(message.get("CallbackID"))->value(); SnapshotRegion region = static_cast(static_cast(message.get("SnapshotRegion"))->value()); bool transparentBackground = static_cast(message.get("TransparentBackground"))->value(); RefPtr 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(); }