#include "config.h"
#include "WebKitWebView.h"
#include "APIData.h"
#include "APINavigation.h"
#include "APISerializedScriptValue.h"
#include "DataReference.h"
#include "ImageOptions.h"
#include "WebCertificateInfo.h"
#include "WebContextMenuItem.h"
#include "WebContextMenuItemData.h"
#include "WebKitAuthenticationRequestPrivate.h"
#include "WebKitBackForwardListPrivate.h"
#include "WebKitContextMenuClient.h"
#include "WebKitContextMenuItemPrivate.h"
#include "WebKitContextMenuPrivate.h"
#include "WebKitDownloadPrivate.h"
#include "WebKitEditingCommands.h"
#include "WebKitEditorStatePrivate.h"
#include "WebKitEnumTypes.h"
#include "WebKitError.h"
#include "WebKitFaviconDatabasePrivate.h"
#include "WebKitFormClient.h"
#include "WebKitHitTestResultPrivate.h"
#include "WebKitIconLoadingClient.h"
#include "WebKitInstallMissingMediaPluginsPermissionRequestPrivate.h"
#include "WebKitJavascriptResultPrivate.h"
#include "WebKitNavigationClient.h"
#include "WebKitNotificationPrivate.h"
#include "WebKitPrivate.h"
#include "WebKitResponsePolicyDecision.h"
#include "WebKitScriptDialogPrivate.h"
#include "WebKitSettingsPrivate.h"
#include "WebKitUIClient.h"
#include "WebKitURIRequestPrivate.h"
#include "WebKitURIResponsePrivate.h"
#include "WebKitWebContextPrivate.h"
#include "WebKitWebResourcePrivate.h"
#include "WebKitWebViewPrivate.h"
#include "WebKitWebViewSessionStatePrivate.h"
#include "WebKitWebsiteDataManagerPrivate.h"
#include "WebKitWindowPropertiesPrivate.h"
#include <JavaScriptCore/APICast.h>
#include <JavaScriptCore/JSRetainPtr.h>
#include <jsc/JSCContextPrivate.h>
#include <WebCore/CertificateInfo.h>
#include <WebCore/GUniquePtrSoup.h>
#include <WebCore/JSDOMExceptionHandling.h>
#include <WebCore/RefPtrCairo.h>
#include <WebCore/URLSoup.h>
#include <glib/gi18n-lib.h>
#include <wtf/SetForScope.h>
#include <wtf/URL.h>
#include <wtf/glib/GRefPtr.h>
#include <wtf/glib/WTFGType.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
#if PLATFORM(GTK)
#include "WebKitPrintOperationPrivate.h"
#include "WebKitWebInspectorPrivate.h"
#include "WebKitWebViewBasePrivate.h"
#include <WebCore/GUniquePtrGtk.h>
#endif
#if PLATFORM(WPE)
#include "APIViewClient.h"
#include "WPEView.h"
#include "WebKitWebViewBackendPrivate.h"
#endif
#if USE(LIBNOTIFY)
#include <libnotify/notify.h>
#endif
using namespace WebKit;
using namespace WebCore;
enum {
LOAD_CHANGED,
LOAD_FAILED,
LOAD_FAILED_WITH_TLS_ERRORS,
CREATE,
READY_TO_SHOW,
RUN_AS_MODAL,
CLOSE,
SCRIPT_DIALOG,
DECIDE_POLICY,
PERMISSION_REQUEST,
MOUSE_TARGET_CHANGED,
#if PLATFORM(GTK)
PRINT,
#endif
RESOURCE_LOAD_STARTED,
ENTER_FULLSCREEN,
LEAVE_FULLSCREEN,
RUN_FILE_CHOOSER,
CONTEXT_MENU,
CONTEXT_MENU_DISMISSED,
SUBMIT_FORM,
INSECURE_CONTENT_DETECTED,
#if PLATFORM(GTK)
WEB_PROCESS_CRASHED,
#endif
WEB_PROCESS_TERMINATED,
AUTHENTICATE,
SHOW_NOTIFICATION,
#if PLATFORM(GTK)
RUN_COLOR_CHOOSER,
SHOW_OPTION_MENU,
#endif
LAST_SIGNAL
};
enum {
PROP_0,
#if PLATFORM(WPE)
PROP_BACKEND,
#endif
PROP_WEB_CONTEXT,
PROP_RELATED_VIEW,
PROP_SETTINGS,
PROP_USER_CONTENT_MANAGER,
PROP_TITLE,
PROP_ESTIMATED_LOAD_PROGRESS,
#if PLATFORM(GTK)
PROP_FAVICON,
#endif
PROP_URI,
PROP_ZOOM_LEVEL,
PROP_IS_LOADING,
PROP_IS_PLAYING_AUDIO,
PROP_IS_EPHEMERAL,
PROP_IS_CONTROLLED_BY_AUTOMATION,
PROP_EDITABLE
};
typedef HashMap<uint64_t, GRefPtr<WebKitWebResource> > LoadingResourcesMap;
typedef HashMap<uint64_t, GRefPtr<GTask> > SnapshotResultsMap;
class PageLoadStateObserver;
#if PLATFORM(WPE)
static unsigned frameDisplayCallbackID;
struct FrameDisplayedCallback {
FrameDisplayedCallback(WebKitFrameDisplayedCallback callback, gpointer userData = nullptr, GDestroyNotify destroyNotifyFunction = nullptr)
: id(++frameDisplayCallbackID)
, callback(callback)
, userData(userData)
, destroyNotifyFunction(destroyNotifyFunction)
{
}
~FrameDisplayedCallback()
{
if (destroyNotifyFunction)
destroyNotifyFunction(userData);
}
FrameDisplayedCallback(FrameDisplayedCallback&&) = default;
FrameDisplayedCallback(const FrameDisplayedCallback&) = delete;
FrameDisplayedCallback& operator=(const FrameDisplayedCallback&) = delete;
unsigned id { 0 };
WebKitFrameDisplayedCallback callback { nullptr };
gpointer userData { nullptr };
GDestroyNotify destroyNotifyFunction { nullptr };
};
#endif // PLATFORM(WPE)
struct _WebKitWebViewPrivate {
~_WebKitWebViewPrivate()
{
if (modalLoop && g_main_loop_is_running(modalLoop.get()))
g_main_loop_quit(modalLoop.get());
}
#if PLATFORM(WPE)
GRefPtr<WebKitWebViewBackend> backend;
std::unique_ptr<WKWPE::View> view;
Vector<FrameDisplayedCallback> frameDisplayedCallbacks;
bool inFrameDisplayed;
HashSet<unsigned> frameDisplayedCallbacksToRemove;
#endif
WebKitWebView* relatedView;
CString title;
CString customTextEncoding;
CString activeURI;
bool isLoading;
bool isEphemeral;
bool isControlledByAutomation;
std::unique_ptr<PageLoadStateObserver> loadObserver;
GRefPtr<WebKitBackForwardList> backForwardList;
GRefPtr<WebKitSettings> settings;
GRefPtr<WebKitUserContentManager> userContentManager;
GRefPtr<WebKitWebContext> context;
GRefPtr<WebKitWindowProperties> windowProperties;
GRefPtr<WebKitEditorState> editorState;
GRefPtr<GMainLoop> modalLoop;
GRefPtr<WebKitHitTestResult> mouseTargetHitTestResult;
WebEvent::Modifiers mouseTargetModifiers;
GRefPtr<WebKitFindController> findController;
GRefPtr<WebKitWebResource> mainResource;
LoadingResourcesMap loadingResourcesMap;
WebKitScriptDialog* currentScriptDialog;
#if PLATFORM(GTK)
GRefPtr<JSCContext> jsContext;
GRefPtr<WebKitWebInspector> inspector;
RefPtr<cairo_surface_t> favicon;
GRefPtr<GCancellable> faviconCancellable;
CString faviconURI;
unsigned long faviconChangedHandlerID;
SnapshotResultsMap snapshotResultsMap;
#endif
GRefPtr<WebKitAuthenticationRequest> authenticationRequest;
GRefPtr<WebKitWebsiteDataManager> websiteDataManager;
};
static guint signals[LAST_SIGNAL] = { 0, };
#if PLATFORM(GTK)
WEBKIT_DEFINE_TYPE(WebKitWebView, webkit_web_view, WEBKIT_TYPE_WEB_VIEW_BASE)
#elif PLATFORM(WPE)
WEBKIT_DEFINE_TYPE(WebKitWebView, webkit_web_view, G_TYPE_OBJECT)
#endif
static inline WebPageProxy& getPage(WebKitWebView* webView)
{
#if PLATFORM(GTK)
auto* page = webkitWebViewBaseGetPage(reinterpret_cast<WebKitWebViewBase*>(webView));
ASSERT(page);
return *page;
#elif PLATFORM(WPE)
ASSERT(webView->priv->view);
return webView->priv->view->page();
#endif
}
static void webkitWebViewSetIsLoading(WebKitWebView* webView, bool isLoading)
{
if (webView->priv->isLoading == isLoading)
return;
webView->priv->isLoading = isLoading;
g_object_notify(G_OBJECT(webView), "is-loading");
}
void webkitWebViewIsPlayingAudioChanged(WebKitWebView* webView)
{
g_object_notify(G_OBJECT(webView), "is-playing-audio");
}
class PageLoadStateObserver final : public PageLoadState::Observer {
public:
PageLoadStateObserver(WebKitWebView* webView)
: m_webView(webView)
{
}
private:
void willChangeIsLoading() override
{
g_object_freeze_notify(G_OBJECT(m_webView));
}
void didChangeIsLoading() override
{
webkitWebViewSetIsLoading(m_webView, getPage(m_webView).pageLoadState().isLoading());
g_object_thaw_notify(G_OBJECT(m_webView));
}
void willChangeTitle() override
{
g_object_freeze_notify(G_OBJECT(m_webView));
}
void didChangeTitle() override
{
m_webView->priv->title = getPage(m_webView).pageLoadState().title().utf8();
g_object_notify(G_OBJECT(m_webView), "title");
g_object_thaw_notify(G_OBJECT(m_webView));
}
void willChangeActiveURL() override
{
g_object_freeze_notify(G_OBJECT(m_webView));
}
void didChangeActiveURL() override
{
m_webView->priv->activeURI = getPage(m_webView).pageLoadState().activeURL().utf8();
g_object_notify(G_OBJECT(m_webView), "uri");
g_object_thaw_notify(G_OBJECT(m_webView));
}
void willChangeHasOnlySecureContent() override { }
void didChangeHasOnlySecureContent() override { }
void willChangeEstimatedProgress() override
{
g_object_freeze_notify(G_OBJECT(m_webView));
}
void didChangeEstimatedProgress() override
{
g_object_notify(G_OBJECT(m_webView), "estimated-load-progress");
g_object_thaw_notify(G_OBJECT(m_webView));
}
void willChangeCanGoBack() override { }
void didChangeCanGoBack() override { }
void willChangeCanGoForward() override { }
void didChangeCanGoForward() override { }
void willChangeNetworkRequestsInProgress() override { }
void didChangeNetworkRequestsInProgress() override { }
void willChangeCertificateInfo() override { }
void didChangeCertificateInfo() override { }
void willChangeWebProcessIsResponsive() override { }
void didChangeWebProcessIsResponsive() override { }
void didSwapWebProcesses() override { };
WebKitWebView* m_webView;
};
#if PLATFORM(WPE)
class WebViewClient final : public API::ViewClient {
public:
explicit WebViewClient(WebKitWebView* webView)
: m_webView(webView)
{
}
private:
void handleDownloadRequest(WKWPE::View&, DownloadProxy& downloadProxy) override
{
webkitWebViewHandleDownloadRequest(m_webView, &downloadProxy);
}
void frameDisplayed(WKWPE::View&) override
{
{
SetForScope<bool> inFrameDisplayedGuard(m_webView->priv->inFrameDisplayed, true);
for (const auto& callback : m_webView->priv->frameDisplayedCallbacks) {
if (!m_webView->priv->frameDisplayedCallbacksToRemove.contains(callback.id))
callback.callback(m_webView, callback.userData);
}
}
while (!m_webView->priv->frameDisplayedCallbacksToRemove.isEmpty()) {
auto id = m_webView->priv->frameDisplayedCallbacksToRemove.takeAny();
m_webView->priv->frameDisplayedCallbacks.removeFirstMatching([id](const auto& item) {
return item.id == id;
});
}
}
WebKitWebView* m_webView;
};
#endif
static gboolean webkitWebViewLoadFail(WebKitWebView* webView, WebKitLoadEvent, const char* failingURI, GError* error)
{
if (g_error_matches(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)
|| g_error_matches(error, WEBKIT_POLICY_ERROR, WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE)
|| g_error_matches(error, WEBKIT_PLUGIN_ERROR, WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD))
return FALSE;
GUniquePtr<char> htmlString(g_strdup_printf("<html><body>%s</body></html>", error->message));
webkit_web_view_load_alternate_html(webView, htmlString.get(), failingURI, 0);
return TRUE;
}
#if PLATFORM(GTK)
static GtkWidget* webkitWebViewCreate(WebKitWebView*, WebKitNavigationAction*)
{
return nullptr;
}
#else
static WebKitWebView* webkitWebViewCreate(WebKitWebView*, WebKitNavigationAction*)
{
return nullptr;
}
#endif
static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* decision, WebKitPolicyDecisionType decisionType)
{
if (decisionType != WEBKIT_POLICY_DECISION_TYPE_RESPONSE) {
webkit_policy_decision_use(decision);
return TRUE;
}
WebKitURIResponse* response = webkit_response_policy_decision_get_response(WEBKIT_RESPONSE_POLICY_DECISION(decision));
const ResourceResponse& resourceResponse = webkitURIResponseGetResourceResponse(response);
if (resourceResponse.isAttachment()) {
webkit_policy_decision_download(decision);
return TRUE;
}
if (webkit_response_policy_decision_is_mime_type_supported(WEBKIT_RESPONSE_POLICY_DECISION(decision)))
webkit_policy_decision_use(decision);
else
webkit_policy_decision_ignore(decision);
return TRUE;
}
static gboolean webkitWebViewPermissionRequest(WebKitWebView*, WebKitPermissionRequest* request)
{
webkit_permission_request_deny(request);
return TRUE;
}
static void allowModalDialogsChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
{
getPage(webView).setCanRunModal(webkit_settings_get_allow_modal_dialogs(settings));
}
static void zoomTextOnlyChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
{
auto& page = getPage(webView);
gboolean zoomTextOnly = webkit_settings_get_zoom_text_only(settings);
gdouble pageZoomLevel = zoomTextOnly ? 1 : page.textZoomFactor();
gdouble textZoomLevel = zoomTextOnly ? page.pageZoomFactor() : 1;
page.setPageAndTextZoomFactors(pageZoomLevel, textZoomLevel);
}
static void userAgentChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
{
getPage(webView).setCustomUserAgent(String::fromUTF8(webkit_settings_get_user_agent(settings)));
}
#if PLATFORM(GTK)
static void webkitWebViewUpdateFavicon(WebKitWebView* webView, cairo_surface_t* favicon)
{
WebKitWebViewPrivate* priv = webView->priv;
if (priv->favicon.get() == favicon)
return;
priv->favicon = favicon;
g_object_notify(G_OBJECT(webView), "favicon");
}
static void webkitWebViewCancelFaviconRequest(WebKitWebView* webView)
{
if (!webView->priv->faviconCancellable)
return;
g_cancellable_cancel(webView->priv->faviconCancellable.get());
webView->priv->faviconCancellable = 0;
}
static void gotFaviconCallback(GObject* object, GAsyncResult* result, gpointer userData)
{
GUniqueOutPtr<GError> error;
RefPtr<cairo_surface_t> favicon = adoptRef(webkit_favicon_database_get_favicon_finish(WEBKIT_FAVICON_DATABASE(object), result, &error.outPtr()));
if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
WebKitWebView* webView = WEBKIT_WEB_VIEW(userData);
webkitWebViewUpdateFavicon(webView, favicon.get());
webView->priv->faviconCancellable = 0;
}
static void webkitWebViewRequestFavicon(WebKitWebView* webView)
{
webkitWebViewCancelFaviconRequest(webView);
WebKitWebViewPrivate* priv = webView->priv;
priv->faviconCancellable = adoptGRef(g_cancellable_new());
WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(priv->context.get());
webkit_favicon_database_get_favicon(database, priv->activeURI.data(), priv->faviconCancellable.get(), gotFaviconCallback, webView);
}
static void webkitWebViewUpdateFaviconURI(WebKitWebView* webView, const char* faviconURI)
{
if (webView->priv->faviconURI == faviconURI)
return;
webView->priv->faviconURI = faviconURI;
webkitWebViewRequestFavicon(webView);
}
static void faviconChangedCallback(WebKitFaviconDatabase*, const char* pageURI, const char* faviconURI, WebKitWebView* webView)
{
if (webView->priv->activeURI != pageURI)
return;
webkitWebViewUpdateFaviconURI(webView, faviconURI);
}
#endif
static bool webkitWebViewIsConstructed(WebKitWebView* webView)
{
return !!webView->priv->loadObserver;
}
static void webkitWebViewUpdateSettings(WebKitWebView* webView)
{
if (!webkitWebViewIsConstructed(webView))
return;
auto& page = getPage(webView);
WebKitSettings* settings = webView->priv->settings.get();
page.setPreferences(*webkitSettingsGetPreferences(settings));
page.setCanRunModal(webkit_settings_get_allow_modal_dialogs(settings));
page.setCustomUserAgent(String::fromUTF8(webkit_settings_get_user_agent(settings)));
g_signal_connect(settings, "notify::allow-modal-dialogs", G_CALLBACK(allowModalDialogsChanged), webView);
g_signal_connect(settings, "notify::zoom-text-only", G_CALLBACK(zoomTextOnlyChanged), webView);
g_signal_connect(settings, "notify::user-agent", G_CALLBACK(userAgentChanged), webView);
}
static void webkitWebViewDisconnectSettingsSignalHandlers(WebKitWebView* webView)
{
if (!webkitWebViewIsConstructed(webView))
return;
WebKitSettings* settings = webView->priv->settings.get();
g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(allowModalDialogsChanged), webView);
g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(zoomTextOnlyChanged), webView);
g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(userAgentChanged), webView);
}
#if PLATFORM(GTK)
static void webkitWebViewWatchForChangesInFavicon(WebKitWebView* webView)
{
WebKitWebViewPrivate* priv = webView->priv;
if (priv->faviconChangedHandlerID)
return;
WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(priv->context.get());
priv->faviconChangedHandlerID = g_signal_connect(database, "favicon-changed", G_CALLBACK(faviconChangedCallback), webView);
}
static void webkitWebViewDisconnectFaviconDatabaseSignalHandlers(WebKitWebView* webView)
{
WebKitWebViewPrivate* priv = webView->priv;
if (priv->faviconChangedHandlerID)
g_signal_handler_disconnect(webkit_web_context_get_favicon_database(priv->context.get()), priv->faviconChangedHandlerID);
priv->faviconChangedHandlerID = 0;
}
#endif
#if USE(LIBNOTIFY)
static const char* gNotifyNotificationID = "wk-notify-notification";
static void notifyNotificationClosed(NotifyNotification*, WebKitNotification* webNotification)
{
g_object_set_data(G_OBJECT(webNotification), gNotifyNotificationID, nullptr);
webkit_notification_close(webNotification);
}
static void notifyNotificationClicked(NotifyNotification*, char*, WebKitNotification* webNotification)
{
webkit_notification_clicked(webNotification);
}
static void webNotificationClosed(WebKitNotification* webNotification)
{
NotifyNotification* notification = NOTIFY_NOTIFICATION(g_object_get_data(G_OBJECT(webNotification), gNotifyNotificationID));
if (!notification)
return;
notify_notification_close(notification, nullptr);
g_object_set_data(G_OBJECT(webNotification), gNotifyNotificationID, nullptr);
}
#endif // USE(LIBNOTIFY)
static gboolean webkitWebViewShowNotification(WebKitWebView*, WebKitNotification* webNotification)
{
#if USE(LIBNOTIFY)
if (!notify_is_initted())
notify_init(g_get_prgname());
NotifyNotification* notification = NOTIFY_NOTIFICATION(g_object_get_data(G_OBJECT(webNotification), gNotifyNotificationID));
if (!notification) {
notification = notify_notification_new(webkit_notification_get_title(webNotification),
webkit_notification_get_body(webNotification), nullptr);
notify_notification_add_action(notification, "default", _("Acknowledge"), NOTIFY_ACTION_CALLBACK(notifyNotificationClicked), webNotification, nullptr);
g_signal_connect_object(notification, "closed", G_CALLBACK(notifyNotificationClosed), webNotification, static_cast<GConnectFlags>(0));
g_signal_connect(webNotification, "closed", G_CALLBACK(webNotificationClosed), nullptr);
g_object_set_data_full(G_OBJECT(webNotification), gNotifyNotificationID, notification, static_cast<GDestroyNotify>(g_object_unref));
} else {
notify_notification_update(notification, webkit_notification_get_title(webNotification),
webkit_notification_get_body(webNotification), nullptr);
}
notify_notification_show(notification, nullptr);
return TRUE;
#else
UNUSED_PARAM(webNotification);
return FALSE;
#endif
}
static void webkitWebViewConstructed(GObject* object)
{
G_OBJECT_CLASS(webkit_web_view_parent_class)->constructed(object);
WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
WebKitWebViewPrivate* priv = webView->priv;
if (priv->relatedView) {
priv->context = webkit_web_view_get_context(priv->relatedView);
priv->isEphemeral = webkit_web_view_is_ephemeral(priv->relatedView);
priv->isControlledByAutomation = webkit_web_view_is_controlled_by_automation(priv->relatedView);
} else if (!priv->context)
priv->context = webkit_web_context_get_default();
else if (!priv->isEphemeral)
priv->isEphemeral = webkit_web_context_is_ephemeral(priv->context.get());
if (!priv->settings)
priv->settings = adoptGRef(webkit_settings_new());
if (!priv->userContentManager)
priv->userContentManager = adoptGRef(webkit_user_content_manager_new());
if (priv->isEphemeral && !webkit_web_context_is_ephemeral(priv->context.get())) {
priv->websiteDataManager = adoptGRef(webkit_website_data_manager_new_ephemeral());
webkitWebsiteDataManagerAddProcessPool(priv->websiteDataManager.get(), webkitWebContextGetProcessPool(priv->context.get()));
}
webkitWebContextCreatePageForWebView(priv->context.get(), webView, priv->userContentManager.get(), priv->relatedView);
priv->loadObserver = std::make_unique<PageLoadStateObserver>(webView);
getPage(webView).pageLoadState().addObserver(*priv->loadObserver);
priv->relatedView = nullptr;
attachNavigationClientToView(webView);
attachUIClientToView(webView);
attachContextMenuClientToView(webView);
attachFormClientToView(webView);
#if PLATFORM(GTK)
attachIconLoadingClientToView(webView);
#endif
#if PLATFORM(WPE)
priv->view->setClient(std::make_unique<WebViewClient>(webView));
#endif
webkitWebViewUpdateSettings(webView);
priv->backForwardList = adoptGRef(webkitBackForwardListCreate(&getPage(webView).backForwardList()));
priv->windowProperties = adoptGRef(webkitWindowPropertiesCreate());
}
static void webkitWebViewSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec)
{
WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
switch (propId) {
#if PLATFORM(WPE)
case PROP_BACKEND: {
gpointer backend = g_value_get_boxed(value);
webView->priv->backend = backend ? adoptGRef(static_cast<WebKitWebViewBackend*>(backend)) : nullptr;
break;
}
#endif
case PROP_WEB_CONTEXT: {
gpointer webContext = g_value_get_object(value);
webView->priv->context = webContext ? WEBKIT_WEB_CONTEXT(webContext) : nullptr;
break;
}
case PROP_RELATED_VIEW: {
gpointer relatedView = g_value_get_object(value);
webView->priv->relatedView = relatedView ? WEBKIT_WEB_VIEW(relatedView) : nullptr;
break;
}
case PROP_SETTINGS: {
if (gpointer settings = g_value_get_object(value))
webkit_web_view_set_settings(webView, WEBKIT_SETTINGS(settings));
break;
}
case PROP_USER_CONTENT_MANAGER: {
gpointer userContentManager = g_value_get_object(value);
webView->priv->userContentManager = userContentManager ? WEBKIT_USER_CONTENT_MANAGER(userContentManager) : nullptr;
break;
}
case PROP_ZOOM_LEVEL:
webkit_web_view_set_zoom_level(webView, g_value_get_double(value));
break;
case PROP_IS_EPHEMERAL:
webView->priv->isEphemeral = g_value_get_boolean(value);
break;
case PROP_IS_CONTROLLED_BY_AUTOMATION:
webView->priv->isControlledByAutomation = g_value_get_boolean(value);
break;
case PROP_EDITABLE:
webkit_web_view_set_editable(webView, g_value_get_boolean(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
}
}
static void webkitWebViewGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
{
WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
switch (propId) {
#if PLATFORM(WPE)
case PROP_BACKEND:
g_value_set_static_boxed(value, webView->priv->backend.get());
break;
#endif
case PROP_WEB_CONTEXT:
g_value_set_object(value, webView->priv->context.get());
break;
case PROP_SETTINGS:
g_value_set_object(value, webkit_web_view_get_settings(webView));
break;
case PROP_USER_CONTENT_MANAGER:
g_value_set_object(value, webkit_web_view_get_user_content_manager(webView));
break;
case PROP_TITLE:
g_value_set_string(value, webView->priv->title.data());
break;
case PROP_ESTIMATED_LOAD_PROGRESS:
g_value_set_double(value, webkit_web_view_get_estimated_load_progress(webView));
break;
#if PLATFORM(GTK)
case PROP_FAVICON:
g_value_set_pointer(value, webkit_web_view_get_favicon(webView));
break;
#endif
case PROP_URI:
g_value_set_string(value, webkit_web_view_get_uri(webView));
break;
case PROP_ZOOM_LEVEL:
g_value_set_double(value, webkit_web_view_get_zoom_level(webView));
break;
case PROP_IS_LOADING:
g_value_set_boolean(value, webkit_web_view_is_loading(webView));
break;
case PROP_IS_PLAYING_AUDIO:
g_value_set_boolean(value, webkit_web_view_is_playing_audio(webView));
break;
case PROP_IS_EPHEMERAL:
g_value_set_boolean(value, webkit_web_view_is_ephemeral(webView));
break;
case PROP_IS_CONTROLLED_BY_AUTOMATION:
g_value_set_boolean(value, webkit_web_view_is_controlled_by_automation(webView));
break;
case PROP_EDITABLE:
g_value_set_boolean(value, webkit_web_view_is_editable(webView));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
}
}
static void webkitWebViewDispose(GObject* object)
{
WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
#if PLATFORM(GTK)
webkitWebViewCancelFaviconRequest(webView);
webkitWebViewDisconnectFaviconDatabaseSignalHandlers(webView);
#endif
webkitWebViewDisconnectSettingsSignalHandlers(webView);
if (webView->priv->loadObserver) {
getPage(webView).pageLoadState().removeObserver(*webView->priv->loadObserver);
webView->priv->loadObserver.reset();
webkitWebContextWebViewDestroyed(webView->priv->context.get(), webView);
}
if (webView->priv->websiteDataManager) {
webkitWebsiteDataManagerRemoveProcessPool(webView->priv->websiteDataManager.get(), webkitWebContextGetProcessPool(webView->priv->context.get()));
webView->priv->websiteDataManager = nullptr;
}
if (webView->priv->currentScriptDialog) {
webkit_script_dialog_close(webView->priv->currentScriptDialog);
ASSERT(!webView->priv->currentScriptDialog);
}
#if PLATFORM(WPE)
webView->priv->view->close();
#endif
G_OBJECT_CLASS(webkit_web_view_parent_class)->dispose(object);
}
static gboolean webkitWebViewAccumulatorObjectHandled(GSignalInvocationHint*, GValue* returnValue, const GValue* handlerReturn, gpointer)
{
void* object = g_value_get_object(handlerReturn);
if (object)
g_value_set_object(returnValue, object);
return !object;
}
static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
{
GObjectClass* gObjectClass = G_OBJECT_CLASS(webViewClass);
gObjectClass->constructed = webkitWebViewConstructed;
gObjectClass->set_property = webkitWebViewSetProperty;
gObjectClass->get_property = webkitWebViewGetProperty;
gObjectClass->dispose = webkitWebViewDispose;
webViewClass->load_failed = webkitWebViewLoadFail;
webViewClass->create = webkitWebViewCreate;
webViewClass->script_dialog = webkitWebViewScriptDialog;
webViewClass->decide_policy = webkitWebViewDecidePolicy;
webViewClass->permission_request = webkitWebViewPermissionRequest;
webViewClass->run_file_chooser = webkitWebViewRunFileChooser;
webViewClass->authenticate = webkitWebViewAuthenticate;
webViewClass->show_notification = webkitWebViewShowNotification;
#if PLATFORM(WPE)
g_object_class_install_property(
gObjectClass,
PROP_BACKEND,
g_param_spec_boxed(
"backend",
_("Backend"),
_("The backend for the web view"),
WEBKIT_TYPE_WEB_VIEW_BACKEND,
static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
#endif
g_object_class_install_property(gObjectClass,
PROP_WEB_CONTEXT,
g_param_spec_object("web-context",
_("Web Context"),
_("The web context for the view"),
WEBKIT_TYPE_WEB_CONTEXT,
static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
g_object_class_install_property(
gObjectClass,
PROP_RELATED_VIEW,
g_param_spec_object(
"related-view",
_("Related WebView"),
_("The related WebKitWebView used when creating the view to share the same web process"),
WEBKIT_TYPE_WEB_VIEW,
static_cast<GParamFlags>(WEBKIT_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
g_object_class_install_property(
gObjectClass,
PROP_SETTINGS,
g_param_spec_object(
"settings",
_("WebView settings"),
_("The WebKitSettings of the view"),
WEBKIT_TYPE_SETTINGS,
static_cast<GParamFlags>(WEBKIT_PARAM_WRITABLE | G_PARAM_CONSTRUCT)));
g_object_class_install_property(
gObjectClass,
PROP_USER_CONTENT_MANAGER,
g_param_spec_object(
"user-content-manager",
_("WebView user content manager"),
_("The WebKitUserContentManager of the view"),
WEBKIT_TYPE_USER_CONTENT_MANAGER,
static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
g_object_class_install_property(gObjectClass,
PROP_TITLE,
g_param_spec_string("title",
_("Title"),
_("Main frame document title"),
0,
WEBKIT_PARAM_READABLE));
g_object_class_install_property(gObjectClass,
PROP_ESTIMATED_LOAD_PROGRESS,
g_param_spec_double("estimated-load-progress",
_("Estimated Load Progress"),
_("An estimate of the percent completion for a document load"),
0.0, 1.0, 0.0,
WEBKIT_PARAM_READABLE));
#if PLATFORM(GTK)
g_object_class_install_property(gObjectClass,
PROP_FAVICON,
g_param_spec_pointer("favicon",
_("Favicon"),
_("The favicon associated to the view, if any"),
WEBKIT_PARAM_READABLE));
#endif
g_object_class_install_property(gObjectClass,
PROP_URI,
g_param_spec_string("uri",
_("URI"),
_("The current active URI of the view"),
0,
WEBKIT_PARAM_READABLE));
g_object_class_install_property(
gObjectClass,
PROP_ZOOM_LEVEL,
g_param_spec_double(
"zoom-level",
_("Zoom level"),
_("The zoom level of the view content"),
0, G_MAXDOUBLE, 1,
WEBKIT_PARAM_READWRITE));
g_object_class_install_property(
gObjectClass,
PROP_IS_LOADING,
g_param_spec_boolean(
"is-loading",
_("Is Loading"),
_("Whether the view is loading a page"),
FALSE,
WEBKIT_PARAM_READABLE));
g_object_class_install_property(
gObjectClass,
PROP_IS_PLAYING_AUDIO,
g_param_spec_boolean(
"is-playing-audio",
"Is Playing Audio",
_("Whether the view is playing audio"),
FALSE,
WEBKIT_PARAM_READABLE));
g_object_class_install_property(
gObjectClass,
PROP_IS_EPHEMERAL,
g_param_spec_boolean(
"is-ephemeral",
"Is Ephemeral",
_("Whether the web view is ephemeral"),
FALSE,
static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
g_object_class_install_property(
gObjectClass,
PROP_IS_CONTROLLED_BY_AUTOMATION,
g_param_spec_boolean(
"is-controlled-by-automation",
"Is Controlled By Automation",
_("Whether the web view is controlled by automation"),
FALSE,
static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
g_object_class_install_property(
gObjectClass,
PROP_EDITABLE,
g_param_spec_boolean(
"editable",
_("Editable"),
_("Whether the content can be modified by the user."),
FALSE,
WEBKIT_PARAM_READWRITE));
signals[LOAD_CHANGED] =
g_signal_new("load-changed",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, load_changed),
0, 0,
g_cclosure_marshal_VOID__ENUM,
G_TYPE_NONE, 1,
WEBKIT_TYPE_LOAD_EVENT);
signals[LOAD_FAILED] =
g_signal_new(
"load-failed",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, load_failed),
g_signal_accumulator_true_handled, 0,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 3,
WEBKIT_TYPE_LOAD_EVENT,
G_TYPE_STRING,
G_TYPE_ERROR | G_SIGNAL_TYPE_STATIC_SCOPE);
signals[LOAD_FAILED_WITH_TLS_ERRORS] =
g_signal_new("load-failed-with-tls-errors",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, load_failed_with_tls_errors),
g_signal_accumulator_true_handled, 0 ,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 3,
G_TYPE_STRING,
G_TYPE_TLS_CERTIFICATE,
G_TYPE_TLS_CERTIFICATE_FLAGS);
signals[CREATE] = g_signal_new(
"create",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, create),
webkitWebViewAccumulatorObjectHandled, 0,
g_cclosure_marshal_generic,
#if PLATFORM(GTK)
GTK_TYPE_WIDGET,
#else
WEBKIT_TYPE_WEB_VIEW,
#endif
1,
WEBKIT_TYPE_NAVIGATION_ACTION | G_SIGNAL_TYPE_STATIC_SCOPE);
signals[READY_TO_SHOW] =
g_signal_new("ready-to-show",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, ready_to_show),
0, 0,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[RUN_AS_MODAL] =
g_signal_new("run-as-modal",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, run_as_modal),
0, 0,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[CLOSE] =
g_signal_new("close",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, close),
0, 0,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[SCRIPT_DIALOG] = g_signal_new(
"script-dialog",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, script_dialog),
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_SCRIPT_DIALOG);
signals[DECIDE_POLICY] = g_signal_new(
"decide-policy",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, decide_policy),
g_signal_accumulator_true_handled, nullptr ,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 2,
WEBKIT_TYPE_POLICY_DECISION,
WEBKIT_TYPE_POLICY_DECISION_TYPE);
signals[PERMISSION_REQUEST] = g_signal_new(
"permission-request",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, permission_request),
g_signal_accumulator_true_handled, nullptr ,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_PERMISSION_REQUEST);
signals[MOUSE_TARGET_CHANGED] = g_signal_new(
"mouse-target-changed",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, mouse_target_changed),
nullptr, nullptr,
g_cclosure_marshal_generic,
G_TYPE_NONE, 2,
WEBKIT_TYPE_HIT_TEST_RESULT,
G_TYPE_UINT);
#if PLATFORM(GTK)
signals[PRINT] = g_signal_new(
"print",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, print),
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_PRINT_OPERATION);
#endif // PLATFORM(GTK)
signals[RESOURCE_LOAD_STARTED] = g_signal_new(
"resource-load-started",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, resource_load_started),
nullptr, nullptr,
g_cclosure_marshal_generic,
G_TYPE_NONE, 2,
WEBKIT_TYPE_WEB_RESOURCE,
WEBKIT_TYPE_URI_REQUEST);
signals[ENTER_FULLSCREEN] = g_signal_new(
"enter-fullscreen",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, enter_fullscreen),
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 0);
signals[LEAVE_FULLSCREEN] = g_signal_new(
"leave-fullscreen",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, leave_fullscreen),
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 0);
signals[RUN_FILE_CHOOSER] = g_signal_new(
"run-file-chooser",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, run_file_chooser),
g_signal_accumulator_true_handled, nullptr ,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_FILE_CHOOSER_REQUEST);
signals[CONTEXT_MENU] = g_signal_new(
"context-menu",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, context_menu),
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 3,
WEBKIT_TYPE_CONTEXT_MENU,
#if PLATFORM(GTK)
GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
#elif PLATFORM(WPE)
G_TYPE_POINTER, #endif
WEBKIT_TYPE_HIT_TEST_RESULT);
signals[CONTEXT_MENU_DISMISSED] =
g_signal_new("context-menu-dismissed",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, context_menu_dismissed),
0, 0,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[SUBMIT_FORM] =
g_signal_new("submit-form",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, submit_form),
0, 0,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
WEBKIT_TYPE_FORM_SUBMISSION_REQUEST);
signals[INSECURE_CONTENT_DETECTED] =
g_signal_new("insecure-content-detected",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, insecure_content_detected),
0, 0,
g_cclosure_marshal_VOID__ENUM,
G_TYPE_NONE, 1,
WEBKIT_TYPE_INSECURE_CONTENT_EVENT);
#if PLATFORM(GTK)
signals[WEB_PROCESS_CRASHED] = g_signal_new(
"web-process-crashed",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, web_process_crashed),
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 0);
#endif
signals[WEB_PROCESS_TERMINATED] = g_signal_new(
"web-process-terminated",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, web_process_terminated),
0, 0,
g_cclosure_marshal_VOID__ENUM,
G_TYPE_NONE, 1,
WEBKIT_TYPE_WEB_PROCESS_TERMINATION_REASON);
signals[AUTHENTICATE] = g_signal_new(
"authenticate",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, authenticate),
g_signal_accumulator_true_handled, nullptr ,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_AUTHENTICATION_REQUEST);
signals[SHOW_NOTIFICATION] = g_signal_new(
"show-notification",
G_TYPE_FROM_CLASS(gObjectClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, show_notification),
g_signal_accumulator_true_handled, nullptr ,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_NOTIFICATION);
#if PLATFORM(GTK)
signals[RUN_COLOR_CHOOSER] = g_signal_new(
"run-color-chooser",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, run_color_chooser),
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 1,
WEBKIT_TYPE_COLOR_CHOOSER_REQUEST);
signals[SHOW_OPTION_MENU] = g_signal_new(
"show-option-menu",
G_TYPE_FROM_CLASS(webViewClass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(WebKitWebViewClass, show_option_menu),
g_signal_accumulator_true_handled, nullptr,
g_cclosure_marshal_generic,
G_TYPE_BOOLEAN, 3,
WEBKIT_TYPE_OPTION_MENU,
GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
#endif // PLATFORM(GTK)
}
static void webkitWebViewCancelAuthenticationRequest(WebKitWebView* webView)
{
if (!webView->priv->authenticationRequest)
return;
webkit_authentication_request_cancel(webView->priv->authenticationRequest.get());
webView->priv->authenticationRequest.clear();
}
void webkitWebViewCreatePage(WebKitWebView* webView, Ref<API::PageConfiguration>&& configuration)
{
#if PLATFORM(GTK)
webkitWebViewBaseCreateWebPage(WEBKIT_WEB_VIEW_BASE(webView), WTFMove(configuration));
#elif PLATFORM(WPE)
webView->priv->view.reset(WKWPE::View::create(webkit_web_view_backend_get_wpe_backend(webView->priv->backend.get()), configuration.get()));
#endif
}
WebPageProxy& webkitWebViewGetPage(WebKitWebView* webView)
{
return getPage(webView);
}
void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
{
WebKitWebViewPrivate* priv = webView->priv;
switch (loadEvent) {
case WEBKIT_LOAD_STARTED:
#if PLATFORM(GTK)
webkitWebViewCancelFaviconRequest(webView);
webkitWebViewWatchForChangesInFavicon(webView);
#endif
webkitWebViewCancelAuthenticationRequest(webView);
priv->loadingResourcesMap.clear();
priv->mainResource = nullptr;
break;
#if PLATFORM(GTK)
case WEBKIT_LOAD_COMMITTED: {
WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(priv->context.get());
GUniquePtr<char> faviconURI(webkit_favicon_database_get_favicon_uri(database, priv->activeURI.data()));
webkitWebViewUpdateFaviconURI(webView, faviconURI.get());
break;
}
#endif
case WEBKIT_LOAD_FINISHED:
webkitWebViewCancelAuthenticationRequest(webView);
break;
default:
break;
}
g_signal_emit(webView, signals[LOAD_CHANGED], 0, loadEvent);
}
void webkitWebViewLoadFailed(WebKitWebView* webView, WebKitLoadEvent loadEvent, const char* failingURI, GError *error)
{
webkitWebViewCancelAuthenticationRequest(webView);
gboolean returnValue;
g_signal_emit(webView, signals[LOAD_FAILED], 0, loadEvent, failingURI, error, &returnValue);
g_signal_emit(webView, signals[LOAD_CHANGED], 0, WEBKIT_LOAD_FINISHED);
}
void webkitWebViewLoadFailedWithTLSErrors(WebKitWebView* webView, const char* failingURI, GError* error, GTlsCertificateFlags tlsErrors, GTlsCertificate* certificate)
{
webkitWebViewCancelAuthenticationRequest(webView);
WebKitTLSErrorsPolicy tlsErrorsPolicy = webkit_web_context_get_tls_errors_policy(webView->priv->context.get());
if (tlsErrorsPolicy == WEBKIT_TLS_ERRORS_POLICY_FAIL) {
gboolean returnValue;
g_signal_emit(webView, signals[LOAD_FAILED_WITH_TLS_ERRORS], 0, failingURI, certificate, tlsErrors, &returnValue);
if (!returnValue)
g_signal_emit(webView, signals[LOAD_FAILED], 0, WEBKIT_LOAD_STARTED, failingURI, error, &returnValue);
}
g_signal_emit(webView, signals[LOAD_CHANGED], 0, WEBKIT_LOAD_FINISHED);
}
#if PLATFORM(GTK)
void webkitWebViewGetLoadDecisionForIcon(WebKitWebView* webView, const LinkIcon& icon, Function<void(bool)>&& completionHandler)
{
WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(webView->priv->context.get());
webkitFaviconDatabaseGetLoadDecisionForIcon(database, icon, getPage(webView).pageLoadState().activeURL(), WTFMove(completionHandler));
}
void webkitWebViewSetIcon(WebKitWebView* webView, const LinkIcon& icon, API::Data& iconData)
{
WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(webView->priv->context.get());
webkitFaviconDatabaseSetIconForPageURL(database, icon, iconData, getPage(webView).pageLoadState().activeURL());
}
#endif
WebPageProxy* webkitWebViewCreateNewPage(WebKitWebView* webView, const WindowFeatures& windowFeatures, WebKitNavigationAction* navigationAction)
{
WebKitWebView* newWebView;
g_signal_emit(webView, signals[CREATE], 0, navigationAction, &newWebView);
if (!newWebView)
return 0;
webkitWindowPropertiesUpdateFromWebWindowFeatures(newWebView->priv->windowProperties.get(), windowFeatures);
RefPtr<WebPageProxy> newPage = &getPage(newWebView);
return newPage.leakRef();
}
void webkitWebViewReadyToShowPage(WebKitWebView* webView)
{
g_signal_emit(webView, signals[READY_TO_SHOW], 0, NULL);
}
void webkitWebViewRunAsModal(WebKitWebView* webView)
{
g_signal_emit(webView, signals[RUN_AS_MODAL], 0, NULL);
webView->priv->modalLoop = adoptGRef(g_main_loop_new(0, FALSE));
#if PLATFORM(GTK)
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
gdk_threads_leave();
#endif
g_main_loop_run(webView->priv->modalLoop.get());
#if PLATFORM(GTK)
gdk_threads_enter();
ALLOW_DEPRECATED_DECLARATIONS_END
#endif
}
void webkitWebViewClosePage(WebKitWebView* webView)
{
g_signal_emit(webView, signals[CLOSE], 0, NULL);
}
void webkitWebViewRunJavaScriptAlert(WebKitWebView* webView, const CString& message, Function<void()>&& completionHandler)
{
ASSERT(!webView->priv->currentScriptDialog);
webView->priv->currentScriptDialog = webkitScriptDialogCreate(WEBKIT_SCRIPT_DIALOG_ALERT, message, { }, [webView, completionHandler = WTFMove(completionHandler)](bool, const String&) {
completionHandler();
webView->priv->currentScriptDialog = nullptr;
});
gboolean returnValue;
g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, webView->priv->currentScriptDialog, &returnValue);
webkit_script_dialog_unref(webView->priv->currentScriptDialog);
}
void webkitWebViewRunJavaScriptConfirm(WebKitWebView* webView, const CString& message, Function<void(bool)>&& completionHandler)
{
ASSERT(!webView->priv->currentScriptDialog);
webView->priv->currentScriptDialog = webkitScriptDialogCreate(WEBKIT_SCRIPT_DIALOG_CONFIRM, message, { }, [webView, completionHandler = WTFMove(completionHandler)](bool result, const String&) {
completionHandler(result);
webView->priv->currentScriptDialog = nullptr;
});
gboolean returnValue;
g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, webView->priv->currentScriptDialog, &returnValue);
webkit_script_dialog_unref(webView->priv->currentScriptDialog);
}
void webkitWebViewRunJavaScriptPrompt(WebKitWebView* webView, const CString& message, const CString& defaultText, Function<void(const String&)>&& completionHandler)
{
ASSERT(!webView->priv->currentScriptDialog);
webView->priv->currentScriptDialog = webkitScriptDialogCreate(WEBKIT_SCRIPT_DIALOG_PROMPT, message, defaultText, [webView, completionHandler = WTFMove(completionHandler)](bool, const String& result) {
completionHandler(result);
webView->priv->currentScriptDialog = nullptr;
});
gboolean returnValue;
g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, webView->priv->currentScriptDialog, &returnValue);
webkit_script_dialog_unref(webView->priv->currentScriptDialog);
}
void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const CString& message, Function<void(bool)>&& completionHandler)
{
ASSERT(!webView->priv->currentScriptDialog);
webView->priv->currentScriptDialog = webkitScriptDialogCreate(WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM, message, { }, [webView, completionHandler = WTFMove(completionHandler)](bool result, const String&) {
completionHandler(result);
webView->priv->currentScriptDialog = nullptr;
});
gboolean returnValue;
g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, webView->priv->currentScriptDialog, &returnValue);
webkit_script_dialog_unref(webView->priv->currentScriptDialog);
}
bool webkitWebViewIsShowingScriptDialog(WebKitWebView* webView)
{
if (!webView->priv->currentScriptDialog)
return false;
return webkitScriptDialogIsRunning(webView->priv->currentScriptDialog);
}
String webkitWebViewGetCurrentScriptDialogMessage(WebKitWebView* webView)
{
if (!webView->priv->currentScriptDialog)
return { };
return String::fromUTF8(webView->priv->currentScriptDialog->message);
}
void webkitWebViewSetCurrentScriptDialogUserInput(WebKitWebView* webView, const String& userInput)
{
if (!webView->priv->currentScriptDialog)
return;
if (webkitScriptDialogIsRunning(webView->priv->currentScriptDialog))
webkitScriptDialogSetUserInput(webView->priv->currentScriptDialog, userInput);
}
void webkitWebViewAcceptCurrentScriptDialog(WebKitWebView* webView)
{
if (!webView->priv->currentScriptDialog)
return;
if (webkitScriptDialogIsRunning(webView->priv->currentScriptDialog))
webkitScriptDialogAccept(webView->priv->currentScriptDialog);
}
void webkitWebViewDismissCurrentScriptDialog(WebKitWebView* webView)
{
if (!webView->priv->currentScriptDialog)
return;
if (webkitScriptDialogIsRunning(webView->priv->currentScriptDialog))
webkitScriptDialogDismiss(webView->priv->currentScriptDialog);
}
Optional<WebKitScriptDialogType> webkitWebViewGetCurrentScriptDialogType(WebKitWebView* webView)
{
if (!webView->priv->currentScriptDialog)
return WTF::nullopt;
return static_cast<WebKitScriptDialogType>(webView->priv->currentScriptDialog->type);
}
void webkitWebViewMakePolicyDecision(WebKitWebView* webView, WebKitPolicyDecisionType type, WebKitPolicyDecision* decision)
{
gboolean returnValue;
g_signal_emit(webView, signals[DECIDE_POLICY], 0, decision, type, &returnValue);
}
void webkitWebViewMakePermissionRequest(WebKitWebView* webView, WebKitPermissionRequest* request)
{
gboolean returnValue;
g_signal_emit(webView, signals[PERMISSION_REQUEST], 0, request, &returnValue);
}
void webkitWebViewMouseTargetChanged(WebKitWebView* webView, const WebHitTestResultData& hitTestResult, WebEvent::Modifiers modifiers)
{
#if PLATFORM(GTK)
webkitWebViewBaseSetTooltipArea(WEBKIT_WEB_VIEW_BASE(webView), hitTestResult.elementBoundingBox);
#endif
WebKitWebViewPrivate* priv = webView->priv;
if (priv->mouseTargetHitTestResult
&& priv->mouseTargetModifiers == modifiers
&& webkitHitTestResultCompare(priv->mouseTargetHitTestResult.get(), hitTestResult))
return;
priv->mouseTargetModifiers = modifiers;
priv->mouseTargetHitTestResult = adoptGRef(webkitHitTestResultCreate(hitTestResult));
g_signal_emit(webView, signals[MOUSE_TARGET_CHANGED], 0, priv->mouseTargetHitTestResult.get(), toPlatformModifiers(modifiers));
}
void webkitWebViewHandleDownloadRequest(WebKitWebView* webView, DownloadProxy* downloadProxy)
{
ASSERT(downloadProxy);
GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(downloadProxy);
webkitDownloadSetWebView(download.get(), webView);
}
#if PLATFORM(GTK)
void webkitWebViewPrintFrame(WebKitWebView* webView, WebFrameProxy* frame)
{
auto printOperation = adoptGRef(webkit_print_operation_new(webView));
webkitPrintOperationSetPrintMode(printOperation.get(), PrintInfo::PrintModeSync);
gboolean returnValue;
g_signal_emit(webView, signals[PRINT], 0, printOperation.get(), &returnValue);
if (returnValue)
return;
WebKitPrintOperationResponse response = webkitPrintOperationRunDialogForFrame(printOperation.get(), 0, frame);
if (response == WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL)
return;
g_signal_connect(printOperation.leakRef(), "finished", G_CALLBACK(g_object_unref), 0);
}
#endif
void webkitWebViewResourceLoadStarted(WebKitWebView* webView, WebFrameProxy* frame, uint64_t resourceIdentifier, WebKitURIRequest* request)
{
WebKitWebViewPrivate* priv = webView->priv;
bool isMainResource = frame->isMainFrame() && !priv->mainResource;
WebKitWebResource* resource = webkitWebResourceCreate(frame, request, isMainResource);
if (isMainResource)
priv->mainResource = resource;
priv->loadingResourcesMap.set(resourceIdentifier, adoptGRef(resource));
g_signal_emit(webView, signals[RESOURCE_LOAD_STARTED], 0, resource, request);
}
WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier)
{
GRefPtr<WebKitWebResource> resource = webView->priv->loadingResourcesMap.get(resourceIdentifier);
return resource.get();
}
void webkitWebViewRemoveLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier)
{
WebKitWebViewPrivate* priv = webView->priv;
ASSERT(priv->loadingResourcesMap.contains(resourceIdentifier));
priv->loadingResourcesMap.remove(resourceIdentifier);
}
void webkitWebViewEnterFullScreen(WebKitWebView* webView)
{
#if ENABLE(FULLSCREEN_API)
gboolean returnValue;
g_signal_emit(webView, signals[ENTER_FULLSCREEN], 0, &returnValue);
#if PLATFORM(GTK)
if (!returnValue)
webkitWebViewBaseEnterFullScreen(WEBKIT_WEB_VIEW_BASE(webView));
#endif
#endif
}
void webkitWebViewExitFullScreen(WebKitWebView* webView)
{
#if ENABLE(FULLSCREEN_API)
gboolean returnValue;
g_signal_emit(webView, signals[LEAVE_FULLSCREEN], 0, &returnValue);
#if PLATFORM(GTK)
if (!returnValue)
webkitWebViewBaseExitFullScreen(WEBKIT_WEB_VIEW_BASE(webView));
#endif
#endif
}
void webkitWebViewRunFileChooserRequest(WebKitWebView* webView, WebKitFileChooserRequest* request)
{
gboolean returnValue;
g_signal_emit(webView, signals[RUN_FILE_CHOOSER], 0, request, &returnValue);
}
#if PLATFORM(GTK)
static void contextMenuDismissed(GtkMenuShell*, WebKitWebView* webView)
{
g_signal_emit(webView, signals[CONTEXT_MENU_DISMISSED], 0, NULL);
}
void webkitWebViewPopulateContextMenu(WebKitWebView* webView, const Vector<WebContextMenuItemData>& proposedMenu, const WebHitTestResultData& hitTestResultData, GVariant* userData)
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView);
WebContextMenuProxyGtk* contextMenuProxy = webkitWebViewBaseGetActiveContextMenuProxy(webViewBase);
ASSERT(contextMenuProxy);
GRefPtr<WebKitContextMenu> contextMenu = adoptGRef(webkitContextMenuCreate(proposedMenu));
if (userData)
webkit_context_menu_set_user_data(WEBKIT_CONTEXT_MENU(contextMenu.get()), userData);
GRefPtr<WebKitHitTestResult> hitTestResult = adoptGRef(webkitHitTestResultCreate(hitTestResultData));
GUniquePtr<GdkEvent> contextMenuEvent(webkitWebViewBaseTakeContextMenuEvent(webViewBase));
gboolean returnValue;
g_signal_emit(webView, signals[CONTEXT_MENU], 0, contextMenu.get(), contextMenuEvent.get(), hitTestResult.get(), &returnValue);
if (returnValue)
return;
Vector<WebContextMenuItemGlib> contextMenuItems;
webkitContextMenuPopulate(contextMenu.get(), contextMenuItems);
contextMenuProxy->populate(contextMenuItems);
g_signal_connect(contextMenuProxy->gtkMenu(), "deactivate", G_CALLBACK(contextMenuDismissed), webView);
webkit_context_menu_remove_all(contextMenu.get());
}
#elif PLATFORM(WPE)
void webkitWebViewPopulateContextMenu(WebKitWebView* webView, const Vector<WebContextMenuItemData>& proposedMenu, const WebHitTestResultData& hitTestResultData, GVariant* userData)
{
GRefPtr<WebKitContextMenu> contextMenu = adoptGRef(webkitContextMenuCreate(proposedMenu));
if (userData)
webkit_context_menu_set_user_data(WEBKIT_CONTEXT_MENU(contextMenu.get()), userData);
GRefPtr<WebKitHitTestResult> hitTestResult = adoptGRef(webkitHitTestResultCreate(hitTestResultData));
gboolean returnValue;
g_signal_emit(webView, signals[CONTEXT_MENU], 0, contextMenu.get(), nullptr, hitTestResult.get(), &returnValue);
}
#endif
void webkitWebViewSubmitFormRequest(WebKitWebView* webView, WebKitFormSubmissionRequest* request)
{
g_signal_emit(webView, signals[SUBMIT_FORM], 0, request);
}
void webkitWebViewHandleAuthenticationChallenge(WebKitWebView* webView, AuthenticationChallengeProxy* authenticationChallenge)
{
#if PLATFORM(GTK)
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
gboolean privateBrowsingEnabled = webView->priv->isEphemeral || webkit_settings_get_enable_private_browsing(webView->priv->settings.get());
G_GNUC_END_IGNORE_DEPRECATIONS;
#else
gboolean privateBrowsingEnabled = webView->priv->isEphemeral;
#endif
webView->priv->authenticationRequest = adoptGRef(webkitAuthenticationRequestCreate(authenticationChallenge, privateBrowsingEnabled));
gboolean returnValue;
g_signal_emit(webView, signals[AUTHENTICATE], 0, webView->priv->authenticationRequest.get(), &returnValue);
}
void webkitWebViewInsecureContentDetected(WebKitWebView* webView, WebKitInsecureContentEvent type)
{
g_signal_emit(webView, signals[INSECURE_CONTENT_DETECTED], 0, type);
}
bool webkitWebViewEmitShowNotification(WebKitWebView* webView, WebKitNotification* webNotification)
{
gboolean handled;
g_signal_emit(webView, signals[SHOW_NOTIFICATION], 0, webNotification, &handled);
return handled;
}
#if PLATFORM(GTK)
bool webkitWebViewEmitRunColorChooser(WebKitWebView* webView, WebKitColorChooserRequest* request)
{
gboolean handled;
g_signal_emit(webView, signals[RUN_COLOR_CHOOSER], 0, request, &handled);
return handled;
}
#endif
void webkitWebViewSelectionDidChange(WebKitWebView* webView)
{
if (!webView->priv->editorState)
return;
webkitEditorStateChanged(webView->priv->editorState.get(), getPage(webView).editorState());
}
void webkitWebViewRequestInstallMissingMediaPlugins(WebKitWebView* webView, InstallMissingMediaPluginsPermissionRequest& request)
{
#if ENABLE(VIDEO)
GRefPtr<WebKitInstallMissingMediaPluginsPermissionRequest> installMediaPluginsPermissionRequest = adoptGRef(webkitInstallMissingMediaPluginsPermissionRequestCreate(request));
webkitWebViewMakePermissionRequest(webView, WEBKIT_PERMISSION_REQUEST(installMediaPluginsPermissionRequest.get()));
#else
ASSERT_NOT_REACHED();
#endif
}
WebKitWebsiteDataManager* webkitWebViewGetWebsiteDataManager(WebKitWebView* webView)
{
return webView->priv->websiteDataManager.get();
}
#if PLATFORM(GTK)
bool webkitWebViewShowOptionMenu(WebKitWebView* webView, const IntRect& rect, WebKitOptionMenu* menu, const GdkEvent* event)
{
GdkRectangle menuRect = rect;
gboolean handled;
g_signal_emit(webView, signals[SHOW_OPTION_MENU], 0, menu, event, &menuRect, &handled);
return handled;
}
#endif
#if PLATFORM(WPE)
WebKitWebViewBackend* webkit_web_view_get_backend(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
return webView->priv->backend.get();
}
#endif
WebKitWebContext* webkit_web_view_get_context(WebKitWebView *webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->context.get();
}
WebKitUserContentManager* webkit_web_view_get_user_content_manager(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
return webView->priv->userContentManager.get();
}
gboolean webkit_web_view_is_ephemeral(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
return webView->priv->isEphemeral;
}
gboolean webkit_web_view_is_controlled_by_automation(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
return webView->priv->isControlledByAutomation;
}
WebKitWebsiteDataManager* webkit_web_view_get_website_data_manager(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
if (webView->priv->websiteDataManager)
return webView->priv->websiteDataManager.get();
return webkit_web_context_get_website_data_manager(webView->priv->context.get());
}
void webkit_web_view_try_close(WebKitWebView *webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
if (getPage(webView).tryClose())
webkitWebViewClosePage(webView);
}
void webkit_web_view_load_uri(WebKitWebView* webView, const gchar* uri)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(uri);
GUniquePtr<SoupURI> soupURI(soup_uri_new(uri));
getPage(webView).loadRequest(soupURIToURL(soupURI.get()));
}
void webkit_web_view_load_html(WebKitWebView* webView, const gchar* content, const gchar* baseURI)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(content);
getPage(webView).loadData({ reinterpret_cast<const uint8_t*>(content), content ? strlen(content) : 0 }, "text/html"_s, "UTF-8"_s, String::fromUTF8(baseURI));
}
void webkit_web_view_load_alternate_html(WebKitWebView* webView, const gchar* content, const gchar* contentURI, const gchar* baseURI)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(content);
g_return_if_fail(contentURI);
getPage(webView).loadAlternateHTML({ reinterpret_cast<const uint8_t*>(content), content ? strlen(content) : 0 }, "UTF-8"_s, URL(URL(), String::fromUTF8(baseURI)), URL(URL(), String::fromUTF8(contentURI)));
}
void webkit_web_view_load_plain_text(WebKitWebView* webView, const gchar* plainText)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(plainText);
getPage(webView).loadData({ reinterpret_cast<const uint8_t*>(plainText), plainText ? strlen(plainText) : 0 }, "text/plain"_s, "UTF-8"_s, WTF::blankURL().string());
}
void webkit_web_view_load_bytes(WebKitWebView* webView, GBytes* bytes, const char* mimeType, const char* encoding, const char* baseURI)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(bytes);
gsize bytesDataSize;
gconstpointer bytesData = g_bytes_get_data(bytes, &bytesDataSize);
g_return_if_fail(bytesDataSize);
getPage(webView).loadData({ reinterpret_cast<const uint8_t*>(bytesData), bytesDataSize }, mimeType ? String::fromUTF8(mimeType) : String::fromUTF8("text/html"),
encoding ? String::fromUTF8(encoding) : String::fromUTF8("UTF-8"), String::fromUTF8(baseURI));
}
void webkit_web_view_load_request(WebKitWebView* webView, WebKitURIRequest* request)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(WEBKIT_IS_URI_REQUEST(request));
ResourceRequest resourceRequest;
webkitURIRequestGetResourceRequest(request, resourceRequest);
getPage(webView).loadRequest(WTFMove(resourceRequest));
}
guint64 webkit_web_view_get_page_id(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return getPage(webView).pageID();
}
const gchar* webkit_web_view_get_title(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->title.data();
}
void webkit_web_view_reload(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
getPage(webView).reload({ });
}
void webkit_web_view_reload_bypass_cache(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
getPage(webView).reload(ReloadOption::FromOrigin);
}
void webkit_web_view_stop_loading(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
getPage(webView).stopLoading();
}
gboolean webkit_web_view_is_loading(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
return webView->priv->isLoading;
}
gboolean webkit_web_view_is_playing_audio(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
return getPage(webView).isPlayingAudio();
}
void webkit_web_view_go_back(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
getPage(webView).goBack();
}
gboolean webkit_web_view_can_go_back(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
return !!getPage(webView).backForwardList().backItem();
}
void webkit_web_view_go_forward(WebKitWebView* webView)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
getPage(webView).goForward();
}
gboolean webkit_web_view_can_go_forward(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
return !!getPage(webView).backForwardList().forwardItem();
}
const gchar* webkit_web_view_get_uri(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->activeURI.data();
}
#if PLATFORM(GTK)
cairo_surface_t* webkit_web_view_get_favicon(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
if (webView->priv->activeURI.isNull())
return 0;
return webView->priv->favicon.get();
}
#endif
const gchar* webkit_web_view_get_custom_charset(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
String customTextEncoding = getPage(webView).customTextEncodingName();
if (customTextEncoding.isEmpty())
return 0;
webView->priv->customTextEncoding = customTextEncoding.utf8();
return webView->priv->customTextEncoding.data();
}
void webkit_web_view_set_custom_charset(WebKitWebView* webView, const gchar* charset)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
getPage(webView).setCustomTextEncodingName(String::fromUTF8(charset));
}
gdouble webkit_web_view_get_estimated_load_progress(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return getPage(webView).pageLoadState().estimatedProgress();
}
WebKitBackForwardList* webkit_web_view_get_back_forward_list(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->backForwardList.get();
}
void webkit_web_view_go_to_back_forward_list_item(WebKitWebView* webView, WebKitBackForwardListItem* listItem)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(WEBKIT_IS_BACK_FORWARD_LIST_ITEM(listItem));
getPage(webView).goToBackForwardItem(*webkitBackForwardListItemGetItem(listItem));
}
void webkit_web_view_set_settings(WebKitWebView* webView, WebKitSettings* settings)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(WEBKIT_IS_SETTINGS(settings));
if (webView->priv->settings == settings)
return;
if (webView->priv->settings)
webkitWebViewDisconnectSettingsSignalHandlers(webView);
webView->priv->settings = settings;
webkitWebViewUpdateSettings(webView);
g_object_notify(G_OBJECT(webView), "settings");
}
WebKitSettings* webkit_web_view_get_settings(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
return webView->priv->settings.get();
}
WebKitWindowProperties* webkit_web_view_get_window_properties(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->windowProperties.get();
}
void webkit_web_view_set_zoom_level(WebKitWebView* webView, gdouble zoomLevel)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
if (webkit_web_view_get_zoom_level(webView) == zoomLevel)
return;
auto& page = getPage(webView);
page.scalePage(1.0, IntPoint()); if (webkit_settings_get_zoom_text_only(webView->priv->settings.get()))
page.setTextZoomFactor(zoomLevel);
else
page.setPageZoomFactor(zoomLevel);
g_object_notify(G_OBJECT(webView), "zoom-level");
}
gdouble webkit_web_view_get_zoom_level(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 1);
auto& page = getPage(webView);
gboolean zoomTextOnly = webkit_settings_get_zoom_text_only(webView->priv->settings.get());
return zoomTextOnly ? page.textZoomFactor() : page.pageZoomFactor();
}
void webkit_web_view_can_execute_editing_command(WebKitWebView* webView, const char* command, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(command);
GRefPtr<GTask> task = adoptGRef(g_task_new(webView, cancellable, callback, userData));
getPage(webView).validateCommand(String::fromUTF8(command), [task = WTFMove(task)](const String&, bool isEnabled, int32_t, WebKit::CallbackBase::Error) {
g_task_return_boolean(task.get(), isEnabled);
});
}
gboolean webkit_web_view_can_execute_editing_command_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
g_return_val_if_fail(g_task_is_valid(result, webView), FALSE);
return g_task_propagate_boolean(G_TASK(result), error);
}
void webkit_web_view_execute_editing_command(WebKitWebView* webView, const char* command)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(command);
getPage(webView).executeEditCommand(String::fromUTF8(command));
}
void webkit_web_view_execute_editing_command_with_argument(WebKitWebView* webView, const char* command, const char* argument)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(command);
g_return_if_fail(argument);
getPage(webView).executeEditCommand(String::fromUTF8(command), String::fromUTF8(argument));
}
WebKitFindController* webkit_web_view_get_find_controller(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
if (!webView->priv->findController)
webView->priv->findController = adoptGRef(WEBKIT_FIND_CONTROLLER(g_object_new(WEBKIT_TYPE_FIND_CONTROLLER, "web-view", webView, NULL)));
return webView->priv->findController.get();
}
#if PLATFORM(GTK)
JSGlobalContextRef webkit_web_view_get_javascript_global_context(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
if (!webView->priv->jsContext)
webView->priv->jsContext = SharedJavascriptContext::singleton().getOrCreateContext();
return jscContextGetJSContext(webView->priv->jsContext.get());
}
#endif
static void webkitWebViewRunJavaScriptCallback(API::SerializedScriptValue* wkSerializedScriptValue, const ExceptionDetails& exceptionDetails, GTask* task)
{
if (g_task_return_error_if_cancelled(task))
return;
if (!wkSerializedScriptValue) {
StringBuilder builder;
if (!exceptionDetails.sourceURL.isEmpty()) {
builder.append(exceptionDetails.sourceURL);
if (exceptionDetails.lineNumber > 0) {
builder.append(':');
builder.appendNumber(exceptionDetails.lineNumber);
}
if (exceptionDetails.columnNumber > 0) {
builder.append(':');
builder.appendNumber(exceptionDetails.columnNumber);
}
builder.appendLiteral(": ");
}
builder.append(exceptionDetails.message);
g_task_return_new_error(task, WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED,
"%s", builder.toString().utf8().data());
return;
}
g_task_return_pointer(task, webkitJavascriptResultCreate(wkSerializedScriptValue->internalRepresentation()),
reinterpret_cast<GDestroyNotify>(webkit_javascript_result_unref));
}
void webkit_web_view_run_javascript(WebKitWebView* webView, const gchar* script, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(script);
GRefPtr<GTask> task = adoptGRef(g_task_new(webView, cancellable, callback, userData));
getPage(webView).runJavaScriptInMainFrame(String::fromUTF8(script), true, [task = WTFMove(task)](API::SerializedScriptValue* serializedScriptValue, bool, const ExceptionDetails& exceptionDetails, WebKit::CallbackBase::Error) {
webkitWebViewRunJavaScriptCallback(serializedScriptValue, exceptionDetails, task.get());
});
}
WebKitJavascriptResult* webkit_web_view_run_javascript_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
g_return_val_if_fail(g_task_is_valid(result, webView), nullptr);
return static_cast<WebKitJavascriptResult*>(g_task_propagate_pointer(G_TASK(result), error));
}
void webkit_web_view_run_javascript_in_world(WebKitWebView* webView, const gchar* script, const char* worldName, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(script);
g_return_if_fail(worldName);
GRefPtr<GTask> task = adoptGRef(g_task_new(webView, cancellable, callback, userData));
getPage(webView).runJavaScriptInMainFrameScriptWorld(String::fromUTF8(script), true, String::fromUTF8(worldName), [task = WTFMove(task)](API::SerializedScriptValue* serializedScriptValue, bool, const ExceptionDetails& exceptionDetails, WebKit::CallbackBase::Error) {
webkitWebViewRunJavaScriptCallback(serializedScriptValue, exceptionDetails, task.get());
});
}
WebKitJavascriptResult* webkit_web_view_run_javascript_in_world_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
g_return_val_if_fail(g_task_is_valid(result, webView), nullptr);
return static_cast<WebKitJavascriptResult*>(g_task_propagate_pointer(G_TASK(result), error));
}
static void resourcesStreamReadCallback(GObject* object, GAsyncResult* result, gpointer userData)
{
GRefPtr<GTask> task = adoptGRef(G_TASK(userData));
GError* error = 0;
g_output_stream_splice_finish(G_OUTPUT_STREAM(object), result, &error);
if (error) {
g_task_return_error(task.get(), error);
return;
}
WebKitWebView* webView = WEBKIT_WEB_VIEW(g_task_get_source_object(task.get()));
gpointer outputStreamData = g_memory_output_stream_get_data(G_MEMORY_OUTPUT_STREAM(object));
getPage(webView).runJavaScriptInMainFrame(String::fromUTF8(reinterpret_cast<const gchar*>(outputStreamData)), true,
[task](API::SerializedScriptValue* serializedScriptValue, bool, const ExceptionDetails& exceptionDetails, WebKit::CallbackBase::Error) {
webkitWebViewRunJavaScriptCallback(serializedScriptValue, exceptionDetails, task.get());
});
}
void webkit_web_view_run_javascript_from_gresource(WebKitWebView* webView, const gchar* resource, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(resource);
GError* error = 0;
GRefPtr<GInputStream> inputStream = adoptGRef(g_resources_open_stream(resource, G_RESOURCE_LOOKUP_FLAGS_NONE, &error));
if (error) {
g_task_report_error(webView, callback, userData, 0, error);
return;
}
GTask* task = g_task_new(webView, cancellable, callback, userData);
GRefPtr<GOutputStream> outputStream = adoptGRef(g_memory_output_stream_new(0, 0, fastRealloc, fastFree));
g_output_stream_splice_async(outputStream.get(), inputStream.get(),
static_cast<GOutputStreamSpliceFlags>(G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET),
G_PRIORITY_DEFAULT, cancellable, resourcesStreamReadCallback, task);
}
WebKitJavascriptResult* webkit_web_view_run_javascript_from_gresource_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
g_return_val_if_fail(g_task_is_valid(result, webView), 0);
return static_cast<WebKitJavascriptResult*>(g_task_propagate_pointer(G_TASK(result), error));
}
WebKitWebResource* webkit_web_view_get_main_resource(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
return webView->priv->mainResource.get();
}
#if PLATFORM(GTK)
WebKitWebInspector* webkit_web_view_get_inspector(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
if (!webView->priv->inspector)
webView->priv->inspector = adoptGRef(webkitWebInspectorCreate(getPage(webView).inspector()));
return webView->priv->inspector.get();
}
#endif
gboolean webkit_web_view_can_show_mime_type(WebKitWebView* webView, const char* mimeType)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
g_return_val_if_fail(mimeType, FALSE);
return getPage(webView).canShowMIMEType(String::fromUTF8(mimeType));
}
struct ViewSaveAsyncData {
RefPtr<API::Data> webData;
GRefPtr<GFile> file;
};
WEBKIT_DEFINE_ASYNC_DATA_STRUCT(ViewSaveAsyncData)
static void fileReplaceContentsCallback(GObject* object, GAsyncResult* result, gpointer data)
{
GRefPtr<GTask> task = adoptGRef(G_TASK(data));
GError* error = 0;
if (!g_file_replace_contents_finish(G_FILE(object), result, 0, &error)) {
g_task_return_error(task.get(), error);
return;
}
g_task_return_boolean(task.get(), TRUE);
}
static void getContentsAsMHTMLDataCallback(API::Data* wkData, GTask* taskPtr)
{
auto task = adoptGRef(taskPtr);
if (g_task_return_error_if_cancelled(task.get()))
return;
ViewSaveAsyncData* data = static_cast<ViewSaveAsyncData*>(g_task_get_task_data(task.get()));
data->webData = wkData;
if (g_task_get_source_tag(task.get()) == webkit_web_view_save_to_file) {
ASSERT(G_IS_FILE(data->file.get()));
GCancellable* cancellable = g_task_get_cancellable(task.get());
g_file_replace_contents_async(data->file.get(), reinterpret_cast<const gchar*>(data->webData->bytes()), data->webData->size(),
0, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, cancellable, fileReplaceContentsCallback, task.leakRef());
return;
}
g_task_return_boolean(task.get(), TRUE);
}
void webkit_web_view_save(WebKitWebView* webView, WebKitSaveMode saveMode, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(saveMode == WEBKIT_SAVE_MODE_MHTML);
GTask* task = g_task_new(webView, cancellable, callback, userData);
g_task_set_source_tag(task, reinterpret_cast<gpointer>(webkit_web_view_save));
g_task_set_task_data(task, createViewSaveAsyncData(), reinterpret_cast<GDestroyNotify>(destroyViewSaveAsyncData));
getPage(webView).getContentsAsMHTMLData([task](API::Data* data, WebKit::CallbackBase::Error) {
getContentsAsMHTMLDataCallback(data, task);
});
}
GInputStream* webkit_web_view_save_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
g_return_val_if_fail(g_task_is_valid(result, webView), 0);
GTask* task = G_TASK(result);
if (!g_task_propagate_boolean(task, error))
return 0;
GInputStream* dataStream = g_memory_input_stream_new();
ViewSaveAsyncData* data = static_cast<ViewSaveAsyncData*>(g_task_get_task_data(task));
gsize length = data->webData->size();
if (length)
g_memory_input_stream_add_data(G_MEMORY_INPUT_STREAM(dataStream), g_memdup(data->webData->bytes(), length), length, g_free);
return dataStream;
}
void webkit_web_view_save_to_file(WebKitWebView* webView, GFile* file, WebKitSaveMode saveMode, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(G_IS_FILE(file));
g_return_if_fail(saveMode == WEBKIT_SAVE_MODE_MHTML);
GTask* task = g_task_new(webView, cancellable, callback, userData);
g_task_set_source_tag(task, reinterpret_cast<gpointer>(webkit_web_view_save_to_file));
ViewSaveAsyncData* data = createViewSaveAsyncData();
data->file = file;
g_task_set_task_data(task, data, reinterpret_cast<GDestroyNotify>(destroyViewSaveAsyncData));
getPage(webView).getContentsAsMHTMLData([task](API::Data* data, WebKit::CallbackBase::Error) {
getContentsAsMHTMLDataCallback(data, task);
});
}
gboolean webkit_web_view_save_to_file_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
g_return_val_if_fail(g_task_is_valid(result, webView), FALSE);
return g_task_propagate_boolean(G_TASK(result), error);
}
WebKitDownload* webkit_web_view_download_uri(WebKitWebView* webView, const char* uri)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
g_return_val_if_fail(uri, nullptr);
GRefPtr<WebKitDownload> download = webkitWebContextStartDownload(webView->priv->context.get(), uri, &getPage(webView));
return download.leakRef();
}
gboolean webkit_web_view_get_tls_info(WebKitWebView* webView, GTlsCertificate** certificate, GTlsCertificateFlags* errors)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
WebFrameProxy* mainFrame = getPage(webView).mainFrame();
if (!mainFrame)
return FALSE;
auto* wkCertificateInfo = mainFrame->certificateInfo();
g_return_val_if_fail(wkCertificateInfo, FALSE);
const auto& certificateInfo = wkCertificateInfo->certificateInfo();
if (certificate)
*certificate = certificateInfo.certificate();
if (errors)
*errors = certificateInfo.tlsErrors();
return !!certificateInfo.certificate();
}
#if PLATFORM(GTK)
void webKitWebViewDidReceiveSnapshot(WebKitWebView* webView, uint64_t callbackID, WebImage* webImage)
{
GRefPtr<GTask> task = webView->priv->snapshotResultsMap.take(callbackID);
if (g_task_return_error_if_cancelled(task.get()))
return;
if (!webImage) {
g_task_return_new_error(task.get(), WEBKIT_SNAPSHOT_ERROR, WEBKIT_SNAPSHOT_ERROR_FAILED_TO_CREATE,
_("There was an error creating the snapshot"));
return;
}
g_task_return_pointer(task.get(), webImage->bitmap().createCairoSurface().leakRef(), reinterpret_cast<GDestroyNotify>(cairo_surface_destroy));
}
static inline unsigned webKitSnapshotOptionsToSnapshotOptions(WebKitSnapshotOptions options)
{
SnapshotOptions snapshotOptions = 0;
if (!(options & WEBKIT_SNAPSHOT_OPTIONS_INCLUDE_SELECTION_HIGHLIGHTING))
snapshotOptions |= SnapshotOptionsExcludeSelectionHighlighting;
return snapshotOptions;
}
static inline SnapshotRegion toSnapshotRegion(WebKitSnapshotRegion region)
{
switch (region) {
case WEBKIT_SNAPSHOT_REGION_VISIBLE:
return SnapshotRegionVisible;
case WEBKIT_SNAPSHOT_REGION_FULL_DOCUMENT:
return SnapshotRegionFullDocument;
default:
ASSERT_NOT_REACHED();
return SnapshotRegionVisible;
}
}
static inline uint64_t generateSnapshotCallbackID()
{
static uint64_t uniqueCallbackID = 1;
return uniqueCallbackID++;
}
void webkit_web_view_get_snapshot(WebKitWebView* webView, WebKitSnapshotRegion region, WebKitSnapshotOptions options, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
API::Dictionary::MapType message;
uint64_t callbackID = generateSnapshotCallbackID();
message.set(String::fromUTF8("SnapshotOptions"), API::UInt64::create(static_cast<uint64_t>(webKitSnapshotOptionsToSnapshotOptions(options))));
message.set(String::fromUTF8("SnapshotRegion"), API::UInt64::create(static_cast<uint64_t>(toSnapshotRegion(region))));
message.set(String::fromUTF8("CallbackID"), API::UInt64::create(callbackID));
message.set(String::fromUTF8("TransparentBackground"), API::Boolean::create(options & WEBKIT_SNAPSHOT_OPTIONS_TRANSPARENT_BACKGROUND));
webView->priv->snapshotResultsMap.set(callbackID, adoptGRef(g_task_new(webView, cancellable, callback, userData)));
getPage(webView).postMessageToInjectedBundle(String::fromUTF8("GetSnapshot"), API::Dictionary::create(WTFMove(message)).ptr());
}
cairo_surface_t* webkit_web_view_get_snapshot_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
g_return_val_if_fail(g_task_is_valid(result, webView), 0);
return static_cast<cairo_surface_t*>(g_task_propagate_pointer(G_TASK(result), error));
}
#endif
void webkitWebViewWebProcessTerminated(WebKitWebView* webView, WebKitWebProcessTerminationReason reason)
{
#if PLATFORM(GTK)
if (reason == WEBKIT_WEB_PROCESS_CRASHED) {
gboolean returnValue;
g_signal_emit(webView, signals[WEB_PROCESS_CRASHED], 0, &returnValue);
}
#endif
g_signal_emit(webView, signals[WEB_PROCESS_TERMINATED], 0, reason);
}
#if PLATFORM(GTK)
void webkit_web_view_set_background_color(WebKitWebView* webView, const GdkRGBA* rgba)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(rgba);
Color color(*rgba);
auto& page = getPage(webView);
if (page.backgroundColor() == color)
return;
page.setBackgroundColor(color);
page.setDrawsBackground(color == Color::white);
}
void webkit_web_view_get_background_color(WebKitWebView* webView, GdkRGBA* rgba)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(rgba);
*rgba = getPage(webView).backgroundColor();
}
#endif // PLATFORM(GTK)
gboolean webkit_web_view_is_editable(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
return getPage(webView).isEditable();
}
void webkit_web_view_set_editable(WebKitWebView* webView, gboolean editable)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
if (editable == getPage(webView).isEditable())
return;
getPage(webView).setEditable(editable);
g_object_notify(G_OBJECT(webView), "editable");
}
WebKitEditorState* webkit_web_view_get_editor_state(WebKitWebView *webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
if (!webView->priv->editorState)
webView->priv->editorState = adoptGRef(webkitEditorStateCreate(getPage(webView)));
return webView->priv->editorState.get();
}
WebKitWebViewSessionState* webkit_web_view_get_session_state(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
SessionState sessionState = getPage(webView).sessionState(nullptr);
return webkitWebViewSessionStateCreate(WTFMove(sessionState));
}
void webkit_web_view_restore_session_state(WebKitWebView* webView, WebKitWebViewSessionState* state)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(state);
getPage(webView).restoreFromSessionState(webkitWebViewSessionStateGetSessionState(state), false);
}
#if PLATFORM(WPE)
unsigned webkit_web_view_add_frame_displayed_callback(WebKitWebView* webView, WebKitFrameDisplayedCallback callback, gpointer userData, GDestroyNotify destroyNotify)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
g_return_val_if_fail(callback, 0);
webView->priv->frameDisplayedCallbacks.append(FrameDisplayedCallback(callback, userData, destroyNotify));
return webView->priv->frameDisplayedCallbacks.last().id;
}
void webkit_web_view_remove_frame_displayed_callback(WebKitWebView* webView, unsigned id)
{
g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
g_return_if_fail(id);
Function<bool(const FrameDisplayedCallback&)> matchFunction = [id](const auto& item) {
return item.id == id;
};
if (webView->priv->inFrameDisplayed) {
auto index = webView->priv->frameDisplayedCallbacks.findMatching(matchFunction);
if (index != notFound)
webView->priv->frameDisplayedCallbacksToRemove.add(id);
} else
webView->priv->frameDisplayedCallbacks.removeFirstMatching(matchFunction);
}
#endif // PLATFORM(WPE)