WebKitInstallMissingMediaPluginsPermissionRequest.cpp   [plain text]


/*
 * Copyright (C) 2015 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 "WebKitInstallMissingMediaPluginsPermissionRequest.h"

#include "WebKitInstallMissingMediaPluginsPermissionRequestPrivate.h"
#include "WebKitPermissionRequest.h"
#include "WebPageProxy.h"
#include <wtf/glib/WTFGType.h>

#if ENABLE(VIDEO)
#include <WebCore/PlatformDisplay.h>
#if PLATFORM(X11)
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#endif
#endif

using namespace WebKit;
using namespace WebCore;

/**
 * SECTION: WebKitInstallMissingMediaPluginsPermissionRequest
 * @Short_description: A permission request for installing missing media plugins
 * @Title: WebKitInstallMissingMediaPluginsPermissionRequest
 * @See_also: #WebKitPermissionRequest, #WebKitWebView
 *
 * WebKitInstallMissingMediaPluginsPermissionRequest represents a request for
 * permission to decide whether WebKit should try to start a helper application to
 * install missing media plugins when the media backend couldn't play a media because
 * the required plugins were not available.
 *
 * When a WebKitInstallMissingMediaPluginsPermissionRequest is not handled by the user,
 * it is allowed by default.
 *
 * Since: 2.10
 */

static void webkit_permission_request_interface_init(WebKitPermissionRequestIface*);

struct _WebKitInstallMissingMediaPluginsPermissionRequestPrivate {
#if ENABLE(VIDEO)
    RefPtr<InstallMissingMediaPluginsPermissionRequest> request;
#endif
    CString description;
    bool madeDecision;
};

WEBKIT_DEFINE_TYPE_WITH_CODE(
    WebKitInstallMissingMediaPluginsPermissionRequest, webkit_install_missing_media_plugins_permission_request, G_TYPE_OBJECT,
    G_IMPLEMENT_INTERFACE(WEBKIT_TYPE_PERMISSION_REQUEST, webkit_permission_request_interface_init))

#if ENABLE(VIDEO)
static GUniquePtr<GstInstallPluginsContext> createGstInstallPluginsContext(WebPageProxy& page)
{
#if PLATFORM(X11)
    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) {
        GUniquePtr<GstInstallPluginsContext> context(gst_install_plugins_context_new());
        gst_install_plugins_context_set_xid(context.get(), GDK_WINDOW_XID(gtk_widget_get_window(page.viewWidget())));
        return context;
    }
#endif

    return nullptr;
}
#endif

static void webkitInstallMissingMediaPluginsPermissionRequestAllow(WebKitPermissionRequest* request)
{
    ASSERT(WEBKIT_IS_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request));

    WebKitInstallMissingMediaPluginsPermissionRequestPrivate* priv = WEBKIT_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request)->priv;

    // Only one decision at a time.
    if (priv->madeDecision)
        return;
#if ENABLE(VIDEO)
    priv->request->allow(createGstInstallPluginsContext(priv->request->page()));
#endif
    priv->madeDecision = true;
}

static void webkitInstallMissingMediaPluginsPermissionRequestDeny(WebKitPermissionRequest* request)
{
    ASSERT(WEBKIT_IS_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request));

    WebKitInstallMissingMediaPluginsPermissionRequestPrivate* priv = WEBKIT_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request)->priv;

    // Only one decision at a time.
    if (priv->madeDecision)
        return;

#if ENABLE(VIDEO)
    priv->request->deny();
#endif
    priv->madeDecision = true;
}

static void webkit_permission_request_interface_init(WebKitPermissionRequestIface* iface)
{
    iface->allow = webkitInstallMissingMediaPluginsPermissionRequestAllow;
    iface->deny = webkitInstallMissingMediaPluginsPermissionRequestDeny;
}

static void webkitInstallMissingMediaPluginsPermissionRequestDispose(GObject* object)
{
    // Default behaviour when no decision has been made is allowing the request for backwards compatibility.
    webkitInstallMissingMediaPluginsPermissionRequestDeny(WEBKIT_PERMISSION_REQUEST(object));
    G_OBJECT_CLASS(webkit_install_missing_media_plugins_permission_request_parent_class)->dispose(object);
}

static void webkit_install_missing_media_plugins_permission_request_class_init(WebKitInstallMissingMediaPluginsPermissionRequestClass* klass)
{
    GObjectClass* objectClass = G_OBJECT_CLASS(klass);
    objectClass->dispose = webkitInstallMissingMediaPluginsPermissionRequestDispose;
}

#if ENABLE(VIDEO)
WebKitInstallMissingMediaPluginsPermissionRequest* webkitInstallMissingMediaPluginsPermissionRequestCreate(InstallMissingMediaPluginsPermissionRequest& request)
{
    WebKitInstallMissingMediaPluginsPermissionRequest* permissionRequest = WEBKIT_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(g_object_new(WEBKIT_TYPE_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST, nullptr));
    permissionRequest->priv->request = &request;
    return permissionRequest;
}
#endif

/**
 * webkit_install_missing_media_plugins_permission_request_get_description:
 * @request: a #WebKitInstallMissingMediaPluginsPermissionRequest
 *
 * Gets the description about the missing plugins provided by the media backend when a media couldn't be played.
 *
 * Returns: a string with the description provided by the media backend.
 *
 * Since: 2.10
 */
const char* webkit_install_missing_media_plugins_permission_request_get_description(WebKitInstallMissingMediaPluginsPermissionRequest* request)
{
    g_return_val_if_fail(WEBKIT_IS_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request), nullptr);

#if ENABLE(VIDEO)
    if (!request->priv->description.isNull())
        return request->priv->description.data();

    const auto& description = request->priv->request->description();
    ASSERT(!description.isEmpty());
    request->priv->description = description.utf8();
#endif
    return request->priv->description.data();
}