| /* |
| * Copyright (C) 2019 Igalia S.L. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "config.h" |
| #include "WebKitUserMessage.h" |
| |
| #include "WebKitUserMessagePrivate.h" |
| #include <gio/gunixfdlist.h> |
| #include <glib/gi18n-lib.h> |
| #include <wtf/CompletionHandler.h> |
| #include <wtf/glib/WTFGType.h> |
| |
| using namespace WebKit; |
| |
| enum { |
| PROP_0, |
| |
| PROP_NAME, |
| PROP_PARAMETERS, |
| PROP_FD_LIST |
| }; |
| |
| /** |
| * SECTION: WebKitUserMessage |
| * @Short_description: A user message |
| * @Title: WebKitUserMessage |
| * @See_also: #WebKitWebContext, #WebKitWebView, #WebKitWebExtension, #WebKitWebPage |
| * |
| * A WebKitUserMessage is a message that can be used for the communication between the UI process |
| * and web extensions. A WebKitUserMessage always has a name, and it can also include parameters and |
| * UNIX file descriptors. Messages can be sent from a #WebKitWebContext to all #WebKitWebExtension<!-- -->s, |
| * from a #WebKitWebExtension to its corresponding #WebKitWebContext, and from a #WebKitWebView to its |
| * corresponding #WebKitWebPage (and vice versa). One to one messages can be replied to directly with |
| * webkit_user_message_send_reply(). |
| * |
| * Since: 2.28 |
| */ |
| struct _WebKitUserMessagePrivate { |
| UserMessage message; |
| CompletionHandler<void(UserMessage&&)> replyHandler; |
| }; |
| |
| WEBKIT_DEFINE_TYPE(WebKitUserMessage, webkit_user_message, G_TYPE_INITIALLY_UNOWNED) |
| |
| G_DEFINE_QUARK(WebKitUserMessageError, webkit_user_message_error) |
| |
| static void webkitUserMessageDispose(GObject* object) |
| { |
| WebKitUserMessage* message = WEBKIT_USER_MESSAGE(object); |
| |
| if (auto replyHandler = std::exchange(message->priv->replyHandler, nullptr)) |
| replyHandler(UserMessage(message->priv->message.name, WEBKIT_USER_MESSAGE_UNHANDLED_MESSAGE)); |
| |
| G_OBJECT_CLASS(webkit_user_message_parent_class)->dispose(object); |
| } |
| |
| static void webkitUserMessageGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) |
| { |
| WebKitUserMessage* message = WEBKIT_USER_MESSAGE(object); |
| |
| switch (propId) { |
| case PROP_NAME: |
| g_value_set_string(value, webkit_user_message_get_name(message)); |
| break; |
| case PROP_PARAMETERS: |
| g_value_set_variant(value, webkit_user_message_get_parameters(message)); |
| break; |
| case PROP_FD_LIST: |
| g_value_set_object(value, webkit_user_message_get_fd_list(message)); |
| break; |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); |
| } |
| } |
| |
| static void webkitUserMessageSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec) |
| { |
| WebKitUserMessage* message = WEBKIT_USER_MESSAGE(object); |
| |
| switch (propId) { |
| case PROP_NAME: |
| message->priv->message.name = g_value_get_string(value); |
| message->priv->message.type = UserMessage::Type::Message; |
| break; |
| case PROP_PARAMETERS: |
| message->priv->message.parameters = g_value_get_variant(value); |
| break; |
| case PROP_FD_LIST: |
| message->priv->message.fileDescriptors = G_UNIX_FD_LIST(g_value_get_object(value)); |
| break; |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); |
| } |
| } |
| |
| static void webkit_user_message_class_init(WebKitUserMessageClass* klass) |
| { |
| GObjectClass* gObjectClass = G_OBJECT_CLASS(klass); |
| |
| gObjectClass->dispose = webkitUserMessageDispose; |
| gObjectClass->get_property = webkitUserMessageGetProperty; |
| gObjectClass->set_property = webkitUserMessageSetProperty; |
| |
| /** |
| * WebKitUserMessage:name: |
| * |
| * The name of the user message. |
| * |
| * Since: 2.28 |
| */ |
| g_object_class_install_property( |
| gObjectClass, |
| PROP_NAME, |
| g_param_spec_string( |
| "name", |
| _("Name"), |
| _("The user message name"), |
| nullptr, |
| static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); |
| |
| /** |
| * WebKitUserMessage:parameters: |
| * |
| * The parameters of the user message as a #GVariant, or %NULL |
| * if the message doesn't include parameters. Note that only complete types are |
| * allowed. |
| * |
| * Since: 2.28 |
| */ |
| g_object_class_install_property( |
| gObjectClass, |
| PROP_PARAMETERS, |
| g_param_spec_variant( |
| "parameters", |
| _("Parameters"), |
| _("The user message parameters"), |
| G_VARIANT_TYPE_ANY, |
| nullptr, |
| static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); |
| |
| /** |
| * WebKitUserMessage:fd-list: |
| * |
| * The UNIX file descriptors of the user message. |
| * |
| * Since: 2.28 |
| */ |
| g_object_class_install_property( |
| gObjectClass, |
| PROP_FD_LIST, |
| g_param_spec_object( |
| "fd-list", |
| _("File Descriptor List"), |
| _("The user message list of file descriptors"), |
| G_TYPE_UNIX_FD_LIST, |
| static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); |
| } |
| |
| WebKitUserMessage* webkitUserMessageCreate(UserMessage&& message) |
| { |
| WebKitUserMessage* returnValue = WEBKIT_USER_MESSAGE(g_object_new(WEBKIT_TYPE_USER_MESSAGE, nullptr)); |
| returnValue->priv->message = WTFMove(message); |
| return returnValue; |
| } |
| |
| WebKitUserMessage* webkitUserMessageCreate(UserMessage&& message, CompletionHandler<void(UserMessage&&)>&& replyHandler) |
| { |
| WebKitUserMessage* returnValue = WEBKIT_USER_MESSAGE(g_object_new(WEBKIT_TYPE_USER_MESSAGE, nullptr)); |
| returnValue->priv->message = WTFMove(message); |
| returnValue->priv->replyHandler = WTFMove(replyHandler); |
| return returnValue; |
| } |
| |
| UserMessage& webkitUserMessageGetMessage(WebKitUserMessage* message) |
| { |
| return message->priv->message; |
| } |
| |
| /** |
| * webkit_user_message_new: |
| * @name: the message name |
| * @parameters: (nullable): the message parameters as a #GVariant, or %NULL |
| * |
| * Create a new #WebKitUserMessage with @name. |
| * |
| * Returns: the newly created #WebKitUserMessage object. |
| * |
| * Since: 2.28 |
| */ |
| WebKitUserMessage* webkit_user_message_new(const char* name, GVariant* parameters) |
| { |
| return webkit_user_message_new_with_fd_list(name, parameters, nullptr); |
| } |
| |
| /** |
| * webkit_user_message_new_with_fd_list: |
| * @name: the message name |
| * @parameters: (nullable): the message parameters as a #GVariant |
| * @fd_list: (nullable): the message file descriptors |
| * |
| * Create a new #WebKitUserMessage including also a list of UNIX file descriptors to be sent. |
| * |
| * Returns: the newly created #WebKitUserMessage object. |
| * |
| * Since: 2.28 |
| */ |
| WebKitUserMessage* webkit_user_message_new_with_fd_list(const char* name, GVariant* parameters, GUnixFDList* fdList) |
| { |
| g_return_val_if_fail(name, nullptr); |
| g_return_val_if_fail(!fdList || G_IS_UNIX_FD_LIST(fdList), nullptr); |
| |
| return WEBKIT_USER_MESSAGE(g_object_new(WEBKIT_TYPE_USER_MESSAGE, "name", name, "parameters", parameters, "fd-list", fdList, nullptr)); |
| } |
| |
| /** |
| * webkit_user_message_get_name: |
| * @message: a #WebKitUserMessage |
| * |
| * Get the @message name |
| * |
| * Returns: the message name |
| * |
| * Since: 2.28 |
| */ |
| const char* webkit_user_message_get_name(WebKitUserMessage* message) |
| { |
| g_return_val_if_fail(WEBKIT_IS_USER_MESSAGE(message), nullptr); |
| |
| return message->priv->message.name.data(); |
| } |
| |
| /** |
| * webkit_user_message_get_parameters: |
| * @message: a #WebKitUserMessage |
| * |
| * Get the @message parameters |
| * |
| * Returns: (transfer none): the message parameters |
| * |
| * Since: 2.28 |
| */ |
| GVariant* webkit_user_message_get_parameters(WebKitUserMessage* message) |
| { |
| g_return_val_if_fail(WEBKIT_IS_USER_MESSAGE(message), nullptr); |
| |
| return message->priv->message.parameters.get(); |
| } |
| |
| /** |
| * webkit_user_message_get_fd_list: |
| * @message: a #WebKitUserMessage |
| * |
| * Get the @message list of file descritpor |
| * |
| * Returns: (transfer none): the message list of file descriptors |
| * |
| * Since: 2.28 |
| */ |
| GUnixFDList* webkit_user_message_get_fd_list(WebKitUserMessage* message) |
| { |
| g_return_val_if_fail(WEBKIT_IS_USER_MESSAGE(message), nullptr); |
| |
| return message->priv->message.fileDescriptors.get(); |
| } |
| |
| /** |
| * webkit_user_message_send_reply: |
| * @message: a #WebKitUserMessage |
| * @reply: a #WebKitUserMessage to send as reply |
| * |
| * Send a reply to @message. If @reply is floating, it's consumed. |
| * You can only send a reply to a #WebKitUserMessage that has been |
| * received. |
| * |
| * Since: 2.28 |
| */ |
| void webkit_user_message_send_reply(WebKitUserMessage* message, WebKitUserMessage* reply) |
| { |
| g_return_if_fail(WEBKIT_IS_USER_MESSAGE(message)); |
| g_return_if_fail(WEBKIT_IS_USER_MESSAGE(reply)); |
| g_return_if_fail(message->priv->replyHandler); |
| |
| // We sink the reference in case of being floating. |
| GRefPtr<WebKitUserMessage> adoptedReply = reply; |
| if (auto replyHandler = std::exchange(message->priv->replyHandler, nullptr)) |
| replyHandler(reply ? reply->priv->message : UserMessage()); |
| } |