Modified: trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp (216066 => 216067)
--- trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp 2017-05-02 08:55:43 UTC (rev 216066)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp 2017-05-02 10:05:58 UTC (rev 216067)
@@ -53,77 +53,78 @@
using namespace WebCore;
class StreamingClient {
- public:
- StreamingClient(WebKitWebSrc*);
- virtual ~StreamingClient();
+public:
+ StreamingClient(WebKitWebSrc*, ResourceRequest&&);
+ virtual ~StreamingClient();
- protected:
- char* createReadBuffer(size_t requestedSize, size_t& actualSize);
- void handleResponseReceived(const ResourceResponse&);
- void handleDataReceived(const char*, int);
- void handleNotifyFinished();
+protected:
+ char* createReadBuffer(size_t requestedSize, size_t& actualSize);
+ void handleResponseReceived(const ResourceResponse&);
+ void handleDataReceived(const char*, int);
+ void handleNotifyFinished();
- GstElement* m_src;
+ GRefPtr<GstElement> m_src;
+ ResourceRequest m_request;
};
class CachedResourceStreamingClient final : public PlatformMediaResourceClient, public StreamingClient {
WTF_MAKE_NONCOPYABLE(CachedResourceStreamingClient);
- public:
- CachedResourceStreamingClient(WebKitWebSrc*);
- virtual ~CachedResourceStreamingClient();
+public:
+ CachedResourceStreamingClient(WebKitWebSrc*, ResourceRequest&&);
+ virtual ~CachedResourceStreamingClient();
- private:
- // PlatformMediaResourceClient virtual methods.
+private:
+ // PlatformMediaResourceClient virtual methods.
#if USE(SOUP)
- char* getOrCreateReadBuffer(PlatformMediaResource&, size_t requestedSize, size_t& actualSize) override;
+ char* getOrCreateReadBuffer(PlatformMediaResource&, size_t requestedSize, size_t& actualSize) override;
#endif
- void responseReceived(PlatformMediaResource&, const ResourceResponse&) override;
- void dataReceived(PlatformMediaResource&, const char*, int) override;
- void accessControlCheckFailed(PlatformMediaResource&, const ResourceError&) override;
- void loadFailed(PlatformMediaResource&, const ResourceError&) override;
- void loadFinished(PlatformMediaResource&) override;
+ void responseReceived(PlatformMediaResource&, const ResourceResponse&) override;
+ void dataReceived(PlatformMediaResource&, const char*, int) override;
+ void accessControlCheckFailed(PlatformMediaResource&, const ResourceError&) override;
+ void loadFailed(PlatformMediaResource&, const ResourceError&) override;
+ void loadFinished(PlatformMediaResource&) override;
};
class ResourceHandleStreamingClient : public ThreadSafeRefCounted<ResourceHandleStreamingClient>, public ResourceHandleClient, public StreamingClient {
- public:
- static Ref<ResourceHandleStreamingClient> create(WebKitWebSrc* src, ResourceRequest&& request)
- {
- return adoptRef(*new ResourceHandleStreamingClient(src, WTFMove(request)));
- }
- virtual ~ResourceHandleStreamingClient();
+public:
+ static Ref<ResourceHandleStreamingClient> create(WebKitWebSrc* src, ResourceRequest&& request)
+ {
+ return adoptRef(*new ResourceHandleStreamingClient(src, WTFMove(request)));
+ }
+ virtual ~ResourceHandleStreamingClient();
- void invalidate();
+ void invalidate();
- // StreamingClient virtual methods.
- bool loadFailed() const;
- void setDefersLoading(bool);
+ // StreamingClient virtual methods.
+ bool loadFailed() const;
+ void setDefersLoading(bool);
- private:
- ResourceHandleStreamingClient(WebKitWebSrc*, ResourceRequest&&);
- void cleanupAndStopRunLoop();
+private:
+ ResourceHandleStreamingClient(WebKitWebSrc*, ResourceRequest&&);
+ void cleanupAndStopRunLoop();
- // ResourceHandleClient virtual methods.
+ // ResourceHandleClient virtual methods.
#if USE(SOUP)
- char* getOrCreateReadBuffer(size_t requestedSize, size_t& actualSize) override;
+ char* getOrCreateReadBuffer(size_t requestedSize, size_t& actualSize) override;
#endif
- ResourceRequest willSendRequest(ResourceHandle*, ResourceRequest&&, ResourceResponse&&) override;
- void didReceiveResponse(ResourceHandle*, ResourceResponse&&) override;
- void didReceiveData(ResourceHandle*, const char*, unsigned, int) override;
- void didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&&, int encodedLength) override;
- void didFinishLoading(ResourceHandle*) override;
- void didFail(ResourceHandle*, const ResourceError&) override;
- void wasBlocked(ResourceHandle*) override;
- void cannotShowURL(ResourceHandle*) override;
+ ResourceRequest willSendRequest(ResourceHandle*, ResourceRequest&&, ResourceResponse&&) override;
+ void didReceiveResponse(ResourceHandle*, ResourceResponse&&) override;
+ void didReceiveData(ResourceHandle*, const char*, unsigned, int) override;
+ void didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&&, int encodedLength) override;
+ void didFinishLoading(ResourceHandle*) override;
+ void didFail(ResourceHandle*, const ResourceError&) override;
+ void wasBlocked(ResourceHandle*) override;
+ void cannotShowURL(ResourceHandle*) override;
- RefPtr<Thread> m_thread;
- Lock m_initializeRunLoopConditionMutex;
- Condition m_initializeRunLoopCondition;
- RunLoop* m_runLoop { nullptr };
- Lock m_terminateRunLoopConditionMutex;
- Condition m_terminateRunLoopCondition;
- RefPtr<ResourceHandle> m_resource;
+ RefPtr<Thread> m_thread;
+ Lock m_initializeRunLoopConditionMutex;
+ Condition m_initializeRunLoopCondition;
+ RunLoop* m_runLoop { nullptr };
+ Lock m_terminateRunLoopConditionMutex;
+ Condition m_terminateRunLoopCondition;
+ RefPtr<ResourceHandle> m_resource;
#if USE(SOUP)
- std::unique_ptr<SoupNetworkSession> m_session;
+ std::unique_ptr<SoupNetworkSession> m_session;
#endif
};
@@ -140,7 +141,7 @@
GstAppSrc* appsrc;
GstPad* srcpad;
CString originalURI;
- CString resolvedURI;
+ CString redirectedURI;
bool keepAlive;
GUniquePtr<GstStructure> extraHeaders;
bool compress;
@@ -317,6 +318,8 @@
// This might need tweaking for ports not using libsoup.
g_object_set(priv->appsrc, "min-percent", 20, nullptr);
+ gst_base_src_set_automatic_eos(GST_BASE_SRC(priv->appsrc), FALSE);
+
gst_app_src_set_caps(priv->appsrc, nullptr);
gst_app_src_set_size(priv->appsrc, -1);
}
@@ -379,7 +382,7 @@
g_value_set_string(value, priv->originalURI.data());
break;
case PROP_RESOLVED_LOCATION:
- g_value_set_string(value, priv->resolvedURI.data());
+ g_value_set_string(value, priv->redirectedURI.isNull() ? priv->originalURI.data() : priv->redirectedURI.data());
break;
case PROP_KEEP_ALIVE:
g_value_set_boolean(value, priv->keepAlive);
@@ -599,10 +602,9 @@
PlatformMediaResourceLoader::LoadOptions loadOptions = 0;
if (request.url().protocolIsBlob())
loadOptions |= PlatformMediaResourceLoader::LoadOption::BufferData;
- // FIXME: request should be moved for efficiency
priv->resource = priv->loader->requestResource(ResourceRequest(request), loadOptions);
if (priv->resource) {
- priv->resource->setClient(std::make_unique<CachedResourceStreamingClient>(protector.get()));
+ priv->resource->setClient(std::make_unique<CachedResourceStreamingClient>(protector.get(), ResourceRequest(request)));
GST_DEBUG_OBJECT(protector.get(), "Started request");
} else {
GST_ERROR_OBJECT(protector.get(), "Failed to setup streaming client");
@@ -680,6 +682,8 @@
case GST_QUERY_URI: {
WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
gst_query_set_uri(query, src->priv->originalURI.data());
+ if (!src->priv->redirectedURI.isNull())
+ gst_query_set_uri_redirection(query, src->priv->redirectedURI.data());
result = TRUE;
break;
}
@@ -745,6 +749,7 @@
WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
+ priv->redirectedURI = CString();
priv->originalURI = CString();
if (!uri)
return TRUE;
@@ -863,19 +868,19 @@
return src->priv->didPassAccessControlCheck;
}
-StreamingClient::StreamingClient(WebKitWebSrc* src)
- : m_src(static_cast<GstElement*>(gst_object_ref(src)))
+StreamingClient::StreamingClient(WebKitWebSrc* src, ResourceRequest&& request)
+ : m_src(GST_ELEMENT(src))
+ , m_request(WTFMove(request))
{
}
StreamingClient::~StreamingClient()
{
- gst_object_unref(m_src);
}
char* StreamingClient::createReadBuffer(size_t requestedSize, size_t& actualSize)
{
- WebKitWebSrc* src = ""
+ WebKitWebSrc* src = ""
WebKitWebSrcPrivate* priv = src->priv;
ASSERT(!priv->buffer);
@@ -894,12 +899,14 @@
void StreamingClient::handleResponseReceived(const ResourceResponse& response)
{
- WebKitWebSrc* src = ""
+ WebKitWebSrc* src = ""
WebKitWebSrcPrivate* priv = src->priv;
GST_DEBUG_OBJECT(src, "Received response: %d", response.httpStatusCode());
- priv->resolvedURI = response.url().string().utf8();
+ auto responseURI = response.url().string().utf8();
+ if (priv->originalURI != responseURI)
+ priv->redirectedURI = WTFMove(responseURI);
if (response.httpStatusCode() >= 400) {
GST_ELEMENT_ERROR(src, RESOURCE, READ, ("Received %d HTTP error code", response.httpStatusCode()), (nullptr));
@@ -946,11 +953,26 @@
gst_app_src_set_size(priv->appsrc, -1);
gst_app_src_set_caps(priv->appsrc, nullptr);
+
+ // Emit a GST_EVENT_CUSTOM_DOWNSTREAM_STICKY event to let GStreamer know about the HTTP headers sent and received.
+ GstStructure* httpHeaders = gst_structure_new_empty("http-headers");
+ gst_structure_set(httpHeaders, "uri", G_TYPE_STRING, priv->originalURI.data(), nullptr);
+ if (!priv->redirectedURI.isNull())
+ gst_structure_set(httpHeaders, "redirection-uri", G_TYPE_STRING, priv->redirectedURI.data(), nullptr);
+ GUniquePtr<GstStructure> headers(gst_structure_new_empty("request-headers"));
+ for (const auto& header : m_request.httpHeaderFields())
+ gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_STRING, header.value.utf8().data(), nullptr);
+ gst_structure_set(httpHeaders, "request-headers", GST_TYPE_STRUCTURE, headers.get(), nullptr);
+ headers.reset(gst_structure_new_empty("response-headers"));
+ for (const auto& header : response.httpHeaderFields())
+ gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_STRING, header.value.utf8().data(), nullptr);
+ gst_structure_set(httpHeaders, "response-headers", GST_TYPE_STRUCTURE, headers.get(), nullptr);
+ gst_pad_push_event(GST_BASE_SRC_PAD(priv->appsrc), gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, httpHeaders));
}
void StreamingClient::handleDataReceived(const char* data, int length)
{
- WebKitWebSrc* src = ""
+ WebKitWebSrc* src = ""
WebKitWebSrcPrivate* priv = src->priv;
WTF::GMutexLocker<GMutex> locker(*GST_OBJECT_GET_LOCK(src));
@@ -1017,7 +1039,7 @@
void StreamingClient::handleNotifyFinished()
{
- WebKitWebSrc* src = ""
+ WebKitWebSrc* src = ""
WebKitWebSrcPrivate* priv = src->priv;
GST_DEBUG_OBJECT(src, "Have EOS");
@@ -1029,8 +1051,8 @@
}
}
-CachedResourceStreamingClient::CachedResourceStreamingClient(WebKitWebSrc* src)
- : StreamingClient(src)
+CachedResourceStreamingClient::CachedResourceStreamingClient(WebKitWebSrc* src, ResourceRequest&& request)
+ : StreamingClient(src, WTFMove(request))
{
}
@@ -1047,7 +1069,7 @@
void CachedResourceStreamingClient::responseReceived(PlatformMediaResource&, const ResourceResponse& response)
{
- WebKitWebSrcPrivate* priv = WEBKIT_WEB_SRC(m_src)->priv;
+ WebKitWebSrcPrivate* priv = WEBKIT_WEB_SRC(m_src.get())->priv;
priv->didPassAccessControlCheck = priv->resource->didPassAccessControlCheck();
handleResponseReceived(response);
}
@@ -1059,7 +1081,7 @@
void CachedResourceStreamingClient::accessControlCheckFailed(PlatformMediaResource&, const ResourceError& error)
{
- WebKitWebSrc* src = ""
+ WebKitWebSrc* src = ""
GST_ELEMENT_ERROR(src, RESOURCE, READ, ("%s", error.localizedDescription().utf8().data()), (nullptr));
gst_app_src_end_of_stream(src->priv->appsrc);
webKitWebSrcStop(src);
@@ -1067,7 +1089,7 @@
void CachedResourceStreamingClient::loadFailed(PlatformMediaResource&, const ResourceError& error)
{
- WebKitWebSrc* src = ""
+ WebKitWebSrc* src = ""
if (!error.isCancellation()) {
GST_ERROR_OBJECT(src, "Have failure: %s", error.localizedDescription().utf8().data());
@@ -1083,19 +1105,19 @@
}
ResourceHandleStreamingClient::ResourceHandleStreamingClient(WebKitWebSrc* src, ResourceRequest&& request)
- : StreamingClient(src)
+ : StreamingClient(src, WTFMove(request))
{
LockHolder locker(m_initializeRunLoopConditionMutex);
- m_thread = Thread::create("ResourceHandleStreamingClient", [this, request = WTFMove(request)] {
+ m_thread = Thread::create("ResourceHandleStreamingClient", [this] {
{
LockHolder locker(m_initializeRunLoopConditionMutex);
m_runLoop = &RunLoop::current();
#if USE(SOUP)
m_session = std::make_unique<SoupNetworkSession>();
- m_resource = ResourceHandle::create(*m_session, request, this, true, false);
+ m_resource = ResourceHandle::create(*m_session, m_request, this, true, false);
#else
// FIXME: This create will hit an assert in debug builds. See https://bugs.webkit.org/show_bug.cgi?id=167003.
- m_resource = ResourceHandle::create(nullptr /*context*/, request, this, true, false);
+ m_resource = ResourceHandle::create(nullptr, m_request, this, true, false);
#endif
m_initializeRunLoopCondition.notifyOne();
}
@@ -1196,7 +1218,7 @@
void ResourceHandleStreamingClient::didFail(ResourceHandle*, const ResourceError& error)
{
- WebKitWebSrc* src = ""
+ WebKitWebSrc* src = ""
GST_ERROR_OBJECT(src, "Have failure: %s", error.localizedDescription().utf8().data());
GST_ELEMENT_ERROR(src, RESOURCE, FAILED, ("%s", error.localizedDescription().utf8().data()), (nullptr));
@@ -1205,7 +1227,7 @@
void ResourceHandleStreamingClient::wasBlocked(ResourceHandle*)
{
- WebKitWebSrc* src = ""
+ WebKitWebSrc* src = ""
GUniquePtr<gchar> uri;
GST_ERROR_OBJECT(src, "Request was blocked");
@@ -1219,7 +1241,7 @@
void ResourceHandleStreamingClient::cannotShowURL(ResourceHandle*)
{
- WebKitWebSrc* src = ""
+ WebKitWebSrc* src = ""
GUniquePtr<gchar> uri;
GST_ERROR_OBJECT(src, "Cannot show URL");