Title: [182523] trunk/Source/WebCore
Revision
182523
Author
[email protected]
Date
2015-04-08 00:09:30 -0700 (Wed, 08 Apr 2015)

Log Message

[GStreamer] extra-headers and keep-alive properties for HTTP source element
https://bugs.webkit.org/show_bug.cgi?id=143480

Reviewed by Carlos Garcia Campos.

Keep the resource loader around when persistent HTTP connection
support is enabled. The keep-alive property is set to false by
default. Also before sending the HTTP request we now check the
contents of the extra-headers GstStructure and set additional
headers based on the structure contents.

Patch inspired by GStreamer's souphttpsrc element.

* platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
(webkit_web_src_init):
(webKitWebSrcFinalize):
(webKitWebSrcSetProperty):
(webKitWebSrcGetProperty):
(webKitWebSrcStop): Clear resource loader only for non-persistent connections.
(webKitWebSrcSetExtraHeader): Utility function to append headers
to an existing request based on a GValue contents.
(webKitWebSrcProcessExtraHeaders): Parse a GValue and set headers
based on its contents.
(webKitWebSrcStart): Extra headers and persistent connection
support. The resource loader is now lazily initialized here.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (182522 => 182523)


--- trunk/Source/WebCore/ChangeLog	2015-04-08 06:41:03 UTC (rev 182522)
+++ trunk/Source/WebCore/ChangeLog	2015-04-08 07:09:30 UTC (rev 182523)
@@ -1,3 +1,31 @@
+2015-04-07  Philippe Normand  <[email protected]>
+
+        [GStreamer] extra-headers and keep-alive properties for HTTP source element
+        https://bugs.webkit.org/show_bug.cgi?id=143480
+
+        Reviewed by Carlos Garcia Campos.
+
+        Keep the resource loader around when persistent HTTP connection
+        support is enabled. The keep-alive property is set to false by
+        default. Also before sending the HTTP request we now check the
+        contents of the extra-headers GstStructure and set additional
+        headers based on the structure contents.
+
+        Patch inspired by GStreamer's souphttpsrc element.
+
+        * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
+        (webkit_web_src_init):
+        (webKitWebSrcFinalize):
+        (webKitWebSrcSetProperty):
+        (webKitWebSrcGetProperty):
+        (webKitWebSrcStop): Clear resource loader only for non-persistent connections.
+        (webKitWebSrcSetExtraHeader): Utility function to append headers
+        to an existing request based on a GValue contents.
+        (webKitWebSrcProcessExtraHeaders): Parse a GValue and set headers
+        based on its contents.
+        (webKitWebSrcStart): Extra headers and persistent connection
+        support. The resource loader is now lazily initialized here.
+
 2015-04-07  Simon Fraser  <[email protected]>
 
         Fix the build.

Added: trunk/Source/WebCore/platform/graphics/gstreamer/GUniquePtrGStreamer.h (0 => 182523)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GUniquePtrGStreamer.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GUniquePtrGStreamer.h	2015-04-08 07:09:30 UTC (rev 182523)
@@ -0,0 +1,34 @@
+/*
+ *  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.
+ */
+
+#ifndef GUniquePtrGStreamer_h
+#define GUniquePtrGStreamer_h
+#if USE(GSTREAMER)
+
+#include <gst/gststructure.h>
+#include <wtf/gobject/GUniquePtr.h>
+
+namespace WTF {
+
+WTF_DEFINE_GPTR_DELETER(GstStructure, gst_structure_free)
+
+}
+
+#endif // USE(GSTREAMER)
+#endif

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp (182522 => 182523)


--- trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp	2015-04-08 06:41:03 UTC (rev 182522)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp	2015-04-08 07:09:30 UTC (rev 182523)
@@ -24,6 +24,7 @@
 
 #include "GRefPtrGStreamer.h"
 #include "GStreamerUtilities.h"
+#include "GUniquePtrGStreamer.h"
 #include "HTTPHeaderNames.h"
 #include "MediaPlayer.h"
 #include "NotImplemented.h"
@@ -109,6 +110,8 @@
     GstAppSrc* appsrc;
     GstPad* srcpad;
     gchar* uri;
+    bool keepAlive;
+    GUniquePtr<GstStructure> extraHeaders;
 
     WebCore::MediaPlayer* player;
 
@@ -145,7 +148,9 @@
     PROP_IRADIO_GENRE,
     PROP_IRADIO_URL,
     PROP_IRADIO_TITLE,
-    PROP_LOCATION
+    PROP_LOCATION,
+    PROP_KEEP_ALIVE,
+    PROP_EXTRA_HEADERS
 };
 
 static GstStaticPadTemplate srcTemplate = GST_STATIC_PAD_TEMPLATE("src",
@@ -242,6 +247,15 @@
                                                         "Location to read from",
                                                         0,
                                                         (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+    g_object_class_install_property(oklass, PROP_KEEP_ALIVE,
+        g_param_spec_boolean("keep-alive", "keep-alive", "Use HTTP persistent connections",
+            FALSE, static_cast<GParamFlags>(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+    g_object_class_install_property(oklass, PROP_EXTRA_HEADERS,
+        g_param_spec_boxed("extra-headers", "Extra Headers", "Extra headers to append to the HTTP request",
+            GST_TYPE_STRUCTURE, static_cast<GParamFlags>(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
     eklass->change_state = webKitWebSrcChangeState;
 
     g_type_class_add_private(klass, sizeof(WebKitWebSrcPrivate));
@@ -327,6 +341,14 @@
     case PROP_LOCATION:
         gst_uri_handler_set_uri(reinterpret_cast<GstURIHandler*>(src), g_value_get_string(value), 0);
         break;
+    case PROP_KEEP_ALIVE:
+        src->priv->keepAlive = g_value_get_boolean(value);
+        break;
+    case PROP_EXTRA_HEADERS: {
+        const GstStructure* s = gst_value_get_structure(value);
+        src->priv->extraHeaders.reset(s ? gst_structure_copy(s) : nullptr);
+        break;
+    }
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, pspec);
         break;
@@ -355,6 +377,12 @@
     case PROP_LOCATION:
         g_value_set_string(value, priv->uri);
         break;
+    case PROP_KEEP_ALIVE:
+        g_value_set_boolean(value, priv->keepAlive);
+        break;
+    case PROP_EXTRA_HEADERS:
+        gst_value_set_structure(value, priv->extraHeaders.get());
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, pspec);
         break;
@@ -389,7 +417,8 @@
         priv->client = 0;
     }
 
-    priv->loader = nullptr;
+    if (!priv->keepAlive)
+        priv->loader = nullptr;
 
     if (priv->buffer) {
         unmapGstBuffer(priv->buffer.get());
@@ -430,6 +459,57 @@
     GST_DEBUG_OBJECT(src, "Stopped request");
 }
 
+static bool webKitWebSrcSetExtraHeader(GQuark fieldId, const GValue* value, gpointer userData)
+{
+    GUniquePtr<gchar> fieldContent;
+
+    if (G_VALUE_HOLDS_STRING(value))
+        fieldContent.reset(g_value_dup_string(value));
+    else {
+        GValue dest = G_VALUE_INIT;
+
+        g_value_init(&dest, G_TYPE_STRING);
+        if (g_value_transform(value, &dest))
+            fieldContent.reset(g_value_dup_string(&dest));
+    }
+
+    const gchar* fieldName = g_quark_to_string(fieldId);
+    if (!fieldContent.get()) {
+        GST_ERROR("extra-headers field '%s' contains no value or can't be converted to a string", fieldName);
+        return false;
+    }
+
+    GST_DEBUG("Appending extra header: \"%s: %s\"", fieldName, fieldContent.get());
+    ResourceRequest* request = static_cast<ResourceRequest*>(userData);
+    request->setHTTPHeaderField(fieldName, fieldContent.get());
+    return true;
+}
+
+static gboolean webKitWebSrcProcessExtraHeaders(GQuark fieldId, const GValue* value, gpointer userData)
+{
+    if (G_VALUE_TYPE(value) == GST_TYPE_ARRAY) {
+        unsigned size = gst_value_array_get_size(value);
+
+        for (unsigned i = 0; i < size; i++) {
+            if (!webKitWebSrcSetExtraHeader(fieldId, gst_value_array_get_value(value, i), userData))
+                return FALSE;
+        }
+        return TRUE;
+    }
+
+    if (G_VALUE_TYPE(value) == GST_TYPE_LIST) {
+        unsigned size = gst_value_list_get_size(value);
+
+        for (unsigned i = 0; i < size; i++) {
+            if (!webKitWebSrcSetExtraHeader(fieldId, gst_value_list_get_value(value, i), userData))
+                return FALSE;
+        }
+        return TRUE;
+    }
+
+    return webKitWebSrcSetExtraHeader(fieldId, value, userData);
+}
+
 static void webKitWebSrcStart(WebKitWebSrc* src)
 {
     WebKitWebSrcPrivate* priv = src->priv;
@@ -449,7 +529,6 @@
     }
 
     ASSERT(!priv->client);
-    ASSERT(!priv->loader);
 
     URL url = "" priv->uri);
 
@@ -457,6 +536,8 @@
     request.setAllowCookies(true);
     request.setFirstPartyForCookies(url);
 
+    priv->size = 0;
+
     if (priv->player)
         request.setHTTPReferrer(priv->player->referrer());
 
@@ -481,21 +562,27 @@
     }
     priv->offset = priv->requestedOffset;
 
+    if (!priv->keepAlive) {
+        GST_DEBUG_OBJECT(src, "Persistent connection support disabled");
+        request.setHTTPHeaderField(HTTPHeaderName::Connection, "close");
+    }
+
+    if (priv->extraHeaders)
+        gst_structure_foreach(priv->extraHeaders.get(), webKitWebSrcProcessExtraHeaders, &request);
+
     // We always request Icecast/Shoutcast metadata, just in case ...
     request.setHTTPHeaderField(HTTPHeaderName::IcyMetadata, "1");
 
     bool loadFailed = true;
-    if (priv->player) {
+    if (priv->player && !priv->loader)
         priv->loader = priv->player->createResourceLoader(std::make_unique<CachedResourceStreamingClient>(src));
-        if (priv->loader) {
-            PlatformMediaResourceLoader::LoadOptions loadOptions = 0;
-            if (request.url().protocolIs("blob"))
-                loadOptions |= PlatformMediaResourceLoader::LoadOption::BufferData;
-            loadFailed = !priv->loader->start(request, loadOptions);
-        }
-    }
 
-    if (!priv->loader) {
+    if (priv->loader) {
+        PlatformMediaResourceLoader::LoadOptions loadOptions = 0;
+        if (request.url().protocolIs("blob"))
+            loadOptions |= PlatformMediaResourceLoader::LoadOption::BufferData;
+        loadFailed = !priv->loader->start(request, loadOptions);
+    } else {
         priv->client = new ResourceHandleStreamingClient(src, request);
         loadFailed = priv->client->loadFailed();
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to