Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (243196 => 243197)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp 2019-03-20 09:47:26 UTC (rev 243196)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp 2019-03-20 11:22:57 UTC (rev 243197)
@@ -225,12 +225,6 @@
}
}
-static void convertToInternalProtocol(URL& url)
-{
- if (url.protocolIsInHTTPFamily() || url.protocolIsBlob())
- url.setProtocol("webkit+" + url.protocol());
-}
-
void MediaPlayerPrivateGStreamer::setPlaybinURL(const URL& url)
{
// Clean out everything after file:// url path.
@@ -239,8 +233,6 @@
cleanURLString = cleanURLString.substring(0, url.pathEnd());
m_url = URL(URL(), cleanURLString);
- convertToInternalProtocol(m_url);
-
GST_INFO_OBJECT(pipeline(), "Load %s", m_url.string().utf8().data());
g_object_set(m_pipeline.get(), "uri", m_url.string().utf8().data(), nullptr);
}
@@ -311,7 +303,6 @@
m_player->readyStateChanged();
m_volumeAndMuteInitialized = false;
m_durationAtEOS = MediaTime::invalidTime();
- m_hasTaintedOrigin = WTF::nullopt;
if (!m_delayingLoad)
commitLoad();
@@ -1346,9 +1337,13 @@
}
#endif
else if (gst_structure_has_name(structure, "http-headers")) {
- if (const char* uri = gst_structure_get_string(structure, "uri")) {
+ const char* redirectionUri = gst_structure_get_string(structure, "redirection-uri");
+ const char* uri = redirectionUri ? redirectionUri : gst_structure_get_string(structure, "uri");
+ if (uri) {
URL url(URL(), uri);
- convertToInternalProtocol(url);
+
+ m_origins.add(SecurityOrigin::create(url));
+
if (url != m_url) {
GST_DEBUG_OBJECT(pipeline(), "Ignoring HTTP response headers for non-main URI.");
break;
@@ -1358,16 +1353,7 @@
if (gst_structure_get(structure, "response-headers", GST_TYPE_STRUCTURE, &responseHeaders.outPtr(), nullptr)) {
const char* contentLengthHeaderName = httpHeaderNameString(HTTPHeaderName::ContentLength).utf8().data();
uint64_t contentLength = 0;
- if (!gst_structure_get_uint64(responseHeaders.get(), contentLengthHeaderName, &contentLength)) {
- // souphttpsrc sets a string for Content-Length, so
- // handle it here, until we remove the webkit+ protocol
- // prefix from webkitwebsrc.
- if (const char* contentLengthAsString = gst_structure_get_string(responseHeaders.get(), contentLengthHeaderName)) {
- contentLength = g_ascii_strtoull(contentLengthAsString, nullptr, 10);
- if (contentLength == G_MAXUINT64)
- contentLength = 0;
- }
- }
+ gst_structure_get_uint64(responseHeaders.get(), contentLengthHeaderName, &contentLength);
GST_INFO_OBJECT(pipeline(), "%s stream detected", !contentLength ? "Live" : "Non-live");
if (!contentLength) {
m_isStreaming = true;
@@ -1377,10 +1363,6 @@
} else if (gst_structure_has_name(structure, "webkit-network-statistics")) {
if (gst_structure_get_uint64(structure, "read-position", &m_networkReadPosition))
GST_DEBUG_OBJECT(pipeline(), "Updated network read position %" G_GUINT64_FORMAT, m_networkReadPosition);
- } else if (gst_structure_has_name(structure, "adaptive-streaming-statistics")) {
- if (WEBKIT_IS_WEB_SRC(m_source.get()))
- if (const char* uri = gst_structure_get_string(structure, "uri"))
- m_hasTaintedOrigin = webKitSrcWouldTaintOrigin(WEBKIT_WEB_SRC(m_source.get()), SecurityOrigin::create(URL(URL(), uri)));
} else
GST_DEBUG_OBJECT(pipeline(), "Unhandled element message: %" GST_PTR_FORMAT, structure);
break;
@@ -2168,7 +2150,6 @@
// append the value of new-location to it.
URL baseUrl = gst_uri_is_valid(newLocation) ? URL() : m_url;
URL newUrl = URL(baseUrl, newLocation);
- convertToInternalProtocol(newUrl);
auto securityOrigin = SecurityOrigin::create(m_url);
if (securityOrigin->canRequest(newUrl)) {
@@ -2530,17 +2511,19 @@
return false;
}
-Optional<bool> MediaPlayerPrivateGStreamer::wouldTaintOrigin(const SecurityOrigin&) const
+Optional<bool> MediaPlayerPrivateGStreamer::wouldTaintOrigin(const SecurityOrigin& origin) const
{
- // Ideally the given origin should always be verified with
- // webKitSrcWouldTaintOrigin() instead of only checking it for
- // adaptive-streaming-statistics. We can't do this yet because HLS fragments
- // are currently downloaded independently from WebKit.
- // See also https://bugs.webkit.org/show_bug.cgi?id=189967.
- return m_hasTaintedOrigin;
+ GST_TRACE_OBJECT(pipeline(), "Checking %u origins", m_origins.size());
+ for (auto& responseOrigin : m_origins) {
+ if (!origin.canAccess(*responseOrigin)) {
+ GST_DEBUG_OBJECT(pipeline(), "Found reachable response origin");
+ return true;
+ }
+ }
+ GST_DEBUG_OBJECT(pipeline(), "No valid response origin found");
+ return false;
}
-
}
#endif // USE(GSTREAMER)
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp (243196 => 243197)
--- trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp 2019-03-20 09:47:26 UTC (rev 243196)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp 2019-03-20 11:22:57 UTC (rev 243197)
@@ -31,9 +31,9 @@
#include "ResourceError.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
-#include "SecurityOrigin.h"
#include <cstdint>
#include <wtf/Condition.h>
+#include <wtf/Scope.h>
#include <wtf/text/CString.h>
using namespace WebCore;
@@ -44,8 +44,6 @@
CachedResourceStreamingClient(WebKitWebSrc*, ResourceRequest&&);
virtual ~CachedResourceStreamingClient();
- const HashSet<RefPtr<WebCore::SecurityOrigin>>& securityOrigins() const { return m_origins; }
-
private:
void checkUpdateBlocksize(uint64_t bytesRead);
@@ -67,7 +65,6 @@
GRefPtr<GstElement> m_src;
ResourceRequest m_request;
- HashSet<RefPtr<WebCore::SecurityOrigin>> m_origins;
};
enum MainThreadSourceNotification {
@@ -110,6 +107,7 @@
uint64_t queueSize { 0 };
GRefPtr<GstAdapter> adapter;
GRefPtr<GstEvent> httpHeadersEvent;
+ GUniquePtr<GstStructure> httpHeaders;
};
enum {
@@ -143,6 +141,7 @@
static gboolean webKitWebSrcQuery(GstBaseSrc*, GstQuery*);
static gboolean webKitWebSrcUnLock(GstBaseSrc*);
static gboolean webKitWebSrcUnLockStop(GstBaseSrc*);
+static void webKitWebSrcSetContext(GstElement*, GstContext*);
#define webkit_web_src_parent_class parent_class
// We split this out into another macro to avoid a check-webkit-style error.
@@ -193,6 +192,7 @@
nullptr, static_cast<GParamFlags>(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
eklass->change_state = GST_DEBUG_FUNCPTR(webKitWebSrcChangeState);
+ eklass->set_context = GST_DEBUG_FUNCPTR(webKitWebSrcSetContext);
GstBaseSrcClass* baseSrcClass = GST_BASE_SRC_CLASS(klass);
baseSrcClass->start = GST_DEBUG_FUNCPTR(webKitWebSrcStart);
@@ -317,6 +317,19 @@
}
}
+static void webKitWebSrcSetContext(GstElement* element, GstContext* context)
+{
+ WebKitWebSrc* src = ""
+ WebKitWebSrcPrivate* priv = src->priv;
+
+ GST_DEBUG_OBJECT(src, "context type: %s", gst_context_get_context_type(context));
+ if (gst_context_has_context_type(context, WEBKIT_WEB_SRC_PLAYER_CONTEXT_TYPE_NAME)) {
+ const GValue* value = gst_structure_get_value(gst_context_get_structure(context), "player");
+ priv->player = reinterpret_cast<MediaPlayer*>(g_value_get_pointer(value));
+ }
+ GST_ELEMENT_CLASS(parent_class)->set_context(element, context);
+}
+
static GstFlowReturn webKitWebSrcCreate(GstPushSrc* pushSrc, GstBuffer** buffer)
{
GstBaseSrc* baseSrc = GST_BASE_SRC_CAST(pushSrc);
@@ -472,8 +485,20 @@
{
WebKitWebSrc* src = ""
WebKitWebSrcPrivate* priv = src->priv;
- ASSERT(priv->player);
+ if (!priv->player) {
+ GRefPtr<GstQuery> query = adoptGRef(gst_query_new_context(WEBKIT_WEB_SRC_PLAYER_CONTEXT_TYPE_NAME));
+ if (gst_pad_peer_query(GST_BASE_SRC_PAD(baseSrc), query.get())) {
+ GstContext* context;
+
+ gst_query_parse_context(query.get(), &context);
+ gst_element_set_context(GST_ELEMENT_CAST(src), context);
+ } else
+ gst_element_post_message(GST_ELEMENT_CAST(src), gst_message_new_need_context(GST_OBJECT_CAST(src), WEBKIT_WEB_SRC_PLAYER_CONTEXT_TYPE_NAME));
+ }
+
+ RELEASE_ASSERT(priv->player);
+
priv->wereHeadersReceived = false;
priv->wasResponseReceived = false;
priv->isDurationSet = false;
@@ -740,18 +765,10 @@
const gchar* const* webKitWebSrcGetProtocols(GType)
{
- static const char* protocols[] = {"webkit+http", "webkit+https", "webkit+blob", nullptr };
+ static const char* protocols[] = {"http", "https", "blob", nullptr };
return protocols;
}
-static URL convertPlaybinURI(const char* uriString)
-{
- URL url(URL(), uriString);
- ASSERT(url.protocol().substring(0, 7) == "webkit+");
- url.setProtocol(url.protocol().substring(7).toString());
- return url;
-}
-
static gchar* webKitWebSrcGetUri(GstURIHandler* handler)
{
WebKitWebSrc* src = ""
@@ -774,7 +791,12 @@
if (!uri)
return TRUE;
- URL url = ""
+ if (priv->originalURI.length()) {
+ GST_ERROR_OBJECT(src, "URI can only be set in states < PAUSED");
+ return FALSE;
+ }
+
+ URL url(URL(), uri);
if (!urlHasSupportedProtocol(url)) {
g_set_error(error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, "Invalid URI '%s'", uri);
return FALSE;
@@ -857,13 +879,46 @@
GST_DEBUG_OBJECT(src, "Received response: %d", response.httpStatusCode());
- auto origin = SecurityOrigin::create(response.url());
- m_origins.add(WTFMove(origin));
-
auto responseURI = response.url().string().utf8();
if (priv->originalURI != responseURI)
priv->redirectedURI = WTFMove(responseURI);
+ uint64_t length = response.expectedContentLength();
+ if (length > 0 && priv->requestedPosition && response.httpStatusCode() == 206)
+ length += priv->requestedPosition;
+
+ priv->httpHeaders.reset(gst_structure_new_empty("http-headers"));
+ gst_structure_set(priv->httpHeaders.get(), "uri", G_TYPE_STRING, priv->originalURI.data(),
+ "http-status-code", G_TYPE_UINT, response.httpStatusCode(), nullptr);
+ if (!priv->redirectedURI.isNull())
+ gst_structure_set(priv->httpHeaders.get(), "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_DEBUG_OBJECT(src, "Request headers going downstream: %" GST_PTR_FORMAT, headers.get());
+ gst_structure_set(priv->httpHeaders.get(), "request-headers", GST_TYPE_STRUCTURE, headers.get(), nullptr);
+ headers.reset(gst_structure_new_empty("response-headers"));
+ for (const auto& header : response.httpHeaderFields()) {
+ bool ok = false;
+ uint64_t convertedValue = header.value.toUInt64(&ok);
+ if (ok)
+ gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_UINT64, convertedValue, nullptr);
+ else
+ gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_STRING, header.value.utf8().data(), nullptr);
+ }
+ auto contentLengthFieldName(httpHeaderNameString(HTTPHeaderName::ContentLength).toString());
+ if (!gst_structure_has_field(headers.get(), contentLengthFieldName.utf8().data()))
+ gst_structure_set(headers.get(), contentLengthFieldName.utf8().data(), G_TYPE_UINT64, static_cast<uint64_t>(length), nullptr);
+ gst_structure_set(priv->httpHeaders.get(), "response-headers", GST_TYPE_STRUCTURE, headers.get(), nullptr);
+ GST_DEBUG_OBJECT(src, "Response headers going downstream: %" GST_PTR_FORMAT, headers.get());
+
+ priv->httpHeadersEvent = adoptGRef(gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, gst_structure_copy(priv->httpHeaders.get())));
+
+ auto scopeExit = makeScopeExit([&] {
+ GstStructure* structure = gst_structure_copy(src->priv->httpHeaders.get());
+ gst_element_post_message(GST_ELEMENT_CAST(src), gst_message_new_element(GST_OBJECT_CAST(src), structure));
+ });
+
if (response.httpStatusCode() >= 400) {
GST_ELEMENT_ERROR(src, RESOURCE, READ, ("Received %d HTTP error code", response.httpStatusCode()), (nullptr));
priv->doesHaveEOS = true;
@@ -891,15 +946,11 @@
}
}
- long long length = response.expectedContentLength();
- if (length > 0 && priv->requestedPosition && response.httpStatusCode() == 206)
- length += priv->requestedPosition;
-
priv->isSeekable = length > 0 && g_ascii_strcasecmp("none", response.httpHeaderField(HTTPHeaderName::AcceptRanges).utf8().data());
- GST_DEBUG_OBJECT(src, "Size: %lld, isSeekable: %s", length, boolForPrinting(priv->isSeekable));
+ GST_DEBUG_OBJECT(src, "Size: %" G_GUINT64_FORMAT ", isSeekable: %s", length, boolForPrinting(priv->isSeekable));
if (length > 0) {
- if (!priv->haveSize || (static_cast<long long>(priv->size) != length)) {
+ if (!priv->haveSize || priv->size != length) {
priv->haveSize = true;
priv->size = length;
priv->isDurationSet = false;
@@ -928,37 +979,6 @@
{
LockHolder locker(priv->responseLock);
-
- // Emit a GST_EVENT_CUSTOM_DOWNSTREAM_STICKY event and message 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(),
- "http-status-code", G_TYPE_UINT, response.httpStatusCode(), 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_DEBUG_OBJECT(src, "Request headers going downstream: %" GST_PTR_FORMAT, headers.get());
- 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()) {
- bool ok = false;
- uint64_t convertedValue = header.value.toUInt64(&ok);
- if (ok)
- gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_UINT64, convertedValue, nullptr);
- else
- gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_STRING, header.value.utf8().data(), nullptr);
- }
- auto contentLengthFieldName(httpHeaderNameString(HTTPHeaderName::ContentLength).toString());
- if (!gst_structure_has_field(headers.get(), contentLengthFieldName.utf8().data()))
- gst_structure_set(headers.get(), contentLengthFieldName.utf8().data(), G_TYPE_UINT64, static_cast<uint64_t>(length), nullptr);
- gst_structure_set(httpHeaders, "response-headers", GST_TYPE_STRUCTURE, headers.get(), nullptr);
- GST_DEBUG_OBJECT(src, "Response headers going downstream: %" GST_PTR_FORMAT, headers.get());
-
- gst_element_post_message(GST_ELEMENT_CAST(src), gst_message_new_element(GST_OBJECT_CAST(src), gst_structure_copy(httpHeaders)));
-
- priv->httpHeadersEvent = adoptGRef(gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, httpHeaders));
priv->wereHeadersReceived = true;
priv->headersCondition.notifyOne();
}
@@ -1041,16 +1061,4 @@
priv->isSeeking = false;
}
-bool webKitSrcWouldTaintOrigin(WebKitWebSrc* src, const SecurityOrigin& origin)
-{
- WebKitWebSrcPrivate* priv = src->priv;
-
- auto* cachedResourceStreamingClient = reinterpret_cast<CachedResourceStreamingClient*>(priv->resource->client());
- for (auto& responseOrigin : cachedResourceStreamingClient->securityOrigins()) {
- if (!origin.canAccess(*responseOrigin))
- return true;
- }
- return false;
-}
-
#endif // ENABLE(VIDEO) && USE(GSTREAMER)