Changeset 243197 in webkit
- Timestamp:
- Mar 20, 2019 4:22:57 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r243196 r243197 1 2019-03-20 Philippe Normand <pnormand@igalia.com> 2 3 [GStreamer] Switch back to webkitwebsrc for adaptive streaming fragments downloading 4 https://bugs.webkit.org/show_bug.cgi?id=195948 5 6 Reviewed by Xabier Rodriguez-Calvar. 7 8 The webkitwebsrc element now behaves much better when used through 9 GStreamer's adaptivedemux, so use it for all WebKit media 10 downloads. The MediaPlayer needed by the webkitwebsrc element now 11 travels through GstContext messages and queries so that it can be 12 shared by multiple elements, typically the first webkitwebsrc 13 element downloads the HLS manifest and then adaptivedemux, through 14 uridownloader, will create new webkitwebsrc elements for fragments 15 downloading. Those new elements will query the first webkitwebsrc 16 element for its context. 17 18 The previous hack used to check SecurityOrigins can 19 also be cleaned-up. The origins are now cached upon reception of 20 the HTTP headers message from webkitwebsrc. 21 22 No new tests, existing http/tests/media/hls tests cover this change. 23 24 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: 25 (WebCore::MediaPlayerPrivateGStreamer::setPlaybinURL): 26 (WebCore::MediaPlayerPrivateGStreamer::loadFull): 27 (WebCore::MediaPlayerPrivateGStreamer::handleMessage): 28 (WebCore::MediaPlayerPrivateGStreamer::loadNextLocation): 29 (WebCore::MediaPlayerPrivateGStreamer::wouldTaintOrigin const): 30 (WebCore::convertToInternalProtocol): Deleted. 31 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: 32 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp: 33 (WebCore::MediaPlayerPrivateGStreamerBase::handleSyncMessage): 34 * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp: 35 (webkit_web_src_class_init): 36 (webKitWebSrcSetContext): 37 (webKitWebSrcStart): 38 (webKitWebSrcGetProtocols): 39 (webKitWebSrcSetUri): 40 (CachedResourceStreamingClient::responseReceived): 41 (convertPlaybinURI): Deleted. 42 (webKitSrcWouldTaintOrigin): Deleted. 43 * platform/graphics/gstreamer/WebKitWebSourceGStreamer.h: 44 1 45 2019-03-20 Thibault Saunier <tsaunier@igalia.com> 2 46 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
r243140 r243197 226 226 } 227 227 228 static void convertToInternalProtocol(URL& url)229 {230 if (url.protocolIsInHTTPFamily() || url.protocolIsBlob())231 url.setProtocol("webkit+" + url.protocol());232 }233 234 228 void MediaPlayerPrivateGStreamer::setPlaybinURL(const URL& url) 235 229 { … … 240 234 241 235 m_url = URL(URL(), cleanURLString); 242 convertToInternalProtocol(m_url);243 244 236 GST_INFO_OBJECT(pipeline(), "Load %s", m_url.string().utf8().data()); 245 237 g_object_set(m_pipeline.get(), "uri", m_url.string().utf8().data(), nullptr); … … 312 304 m_volumeAndMuteInitialized = false; 313 305 m_durationAtEOS = MediaTime::invalidTime(); 314 m_hasTaintedOrigin = WTF::nullopt;315 306 316 307 if (!m_delayingLoad) … … 1347 1338 #endif 1348 1339 else if (gst_structure_has_name(structure, "http-headers")) { 1349 if (const char* uri = gst_structure_get_string(structure, "uri")) { 1340 const char* redirectionUri = gst_structure_get_string(structure, "redirection-uri"); 1341 const char* uri = redirectionUri ? redirectionUri : gst_structure_get_string(structure, "uri"); 1342 if (uri) { 1350 1343 URL url(URL(), uri); 1351 convertToInternalProtocol(url); 1344 1345 m_origins.add(SecurityOrigin::create(url)); 1346 1352 1347 if (url != m_url) { 1353 1348 GST_DEBUG_OBJECT(pipeline(), "Ignoring HTTP response headers for non-main URI."); … … 1359 1354 const char* contentLengthHeaderName = httpHeaderNameString(HTTPHeaderName::ContentLength).utf8().data(); 1360 1355 uint64_t contentLength = 0; 1361 if (!gst_structure_get_uint64(responseHeaders.get(), contentLengthHeaderName, &contentLength)) { 1362 // souphttpsrc sets a string for Content-Length, so 1363 // handle it here, until we remove the webkit+ protocol 1364 // prefix from webkitwebsrc. 1365 if (const char* contentLengthAsString = gst_structure_get_string(responseHeaders.get(), contentLengthHeaderName)) { 1366 contentLength = g_ascii_strtoull(contentLengthAsString, nullptr, 10); 1367 if (contentLength == G_MAXUINT64) 1368 contentLength = 0; 1369 } 1370 } 1356 gst_structure_get_uint64(responseHeaders.get(), contentLengthHeaderName, &contentLength); 1371 1357 GST_INFO_OBJECT(pipeline(), "%s stream detected", !contentLength ? "Live" : "Non-live"); 1372 1358 if (!contentLength) { … … 1378 1364 if (gst_structure_get_uint64(structure, "read-position", &m_networkReadPosition)) 1379 1365 GST_DEBUG_OBJECT(pipeline(), "Updated network read position %" G_GUINT64_FORMAT, m_networkReadPosition); 1380 } else if (gst_structure_has_name(structure, "adaptive-streaming-statistics")) {1381 if (WEBKIT_IS_WEB_SRC(m_source.get()))1382 if (const char* uri = gst_structure_get_string(structure, "uri"))1383 m_hasTaintedOrigin = webKitSrcWouldTaintOrigin(WEBKIT_WEB_SRC(m_source.get()), SecurityOrigin::create(URL(URL(), uri)));1384 1366 } else 1385 1367 GST_DEBUG_OBJECT(pipeline(), "Unhandled element message: %" GST_PTR_FORMAT, structure); … … 2169 2151 URL baseUrl = gst_uri_is_valid(newLocation) ? URL() : m_url; 2170 2152 URL newUrl = URL(baseUrl, newLocation); 2171 convertToInternalProtocol(newUrl);2172 2153 2173 2154 auto securityOrigin = SecurityOrigin::create(m_url); … … 2531 2512 } 2532 2513 2533 Optional<bool> MediaPlayerPrivateGStreamer::wouldTaintOrigin(const SecurityOrigin&) const 2534 { 2535 // Ideally the given origin should always be verified with 2536 // webKitSrcWouldTaintOrigin() instead of only checking it for 2537 // adaptive-streaming-statistics. We can't do this yet because HLS fragments 2538 // are currently downloaded independently from WebKit. 2539 // See also https://bugs.webkit.org/show_bug.cgi?id=189967. 2540 return m_hasTaintedOrigin; 2541 } 2542 2514 Optional<bool> MediaPlayerPrivateGStreamer::wouldTaintOrigin(const SecurityOrigin& origin) const 2515 { 2516 GST_TRACE_OBJECT(pipeline(), "Checking %u origins", m_origins.size()); 2517 for (auto& responseOrigin : m_origins) { 2518 if (!origin.canAccess(*responseOrigin)) { 2519 GST_DEBUG_OBJECT(pipeline(), "Found reachable response origin"); 2520 return true; 2521 } 2522 } 2523 GST_DEBUG_OBJECT(pipeline(), "No valid response origin found"); 2524 return false; 2525 } 2543 2526 2544 2527 } -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
r243140 r243197 292 292 mutable uint64_t m_readPositionAtLastDidLoadingProgress { 0 }; 293 293 294 Optional<bool> m_hasTaintedOrigin { WTF::nullopt };294 HashSet<RefPtr<WebCore::SecurityOrigin>> m_origins; 295 295 }; 296 296 297 } 297 298 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
r242793 r243197 38 38 #include "NotImplemented.h" 39 39 #include "VideoSinkGStreamer.h" 40 #include "WebKitWebSourceGStreamer.h" 40 41 #include <wtf/glib/GUniquePtr.h> 41 42 #include <wtf/text/AtomicString.h> … … 334 335 gst_message_parse_context_type(message, &contextType); 335 336 GST_DEBUG_OBJECT(pipeline(), "Handling %s need-context message for %s", contextType, GST_MESSAGE_SRC_NAME(message)); 337 338 if (!g_strcmp0(contextType, WEBKIT_WEB_SRC_PLAYER_CONTEXT_TYPE_NAME)) { 339 GRefPtr<GstContext> context = adoptGRef(gst_context_new(WEBKIT_WEB_SRC_PLAYER_CONTEXT_TYPE_NAME, FALSE)); 340 GstStructure* contextStructure = gst_context_writable_structure(context.get()); 341 342 ASSERT(m_player); 343 gst_structure_set(contextStructure, "player", G_TYPE_POINTER, m_player, nullptr); 344 gst_element_set_context(GST_ELEMENT(GST_MESSAGE_SRC(message)), context.get()); 345 return true; 346 } 336 347 337 348 #if USE(GSTREAMER_GL) -
trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
r243140 r243197 32 32 #include "ResourceRequest.h" 33 33 #include "ResourceResponse.h" 34 #include "SecurityOrigin.h"35 34 #include <cstdint> 36 35 #include <wtf/Condition.h> 36 #include <wtf/Scope.h> 37 37 #include <wtf/text/CString.h> 38 38 … … 44 44 CachedResourceStreamingClient(WebKitWebSrc*, ResourceRequest&&); 45 45 virtual ~CachedResourceStreamingClient(); 46 47 const HashSet<RefPtr<WebCore::SecurityOrigin>>& securityOrigins() const { return m_origins; }48 46 49 47 private: … … 68 66 GRefPtr<GstElement> m_src; 69 67 ResourceRequest m_request; 70 HashSet<RefPtr<WebCore::SecurityOrigin>> m_origins;71 68 }; 72 69 … … 111 108 GRefPtr<GstAdapter> adapter; 112 109 GRefPtr<GstEvent> httpHeadersEvent; 110 GUniquePtr<GstStructure> httpHeaders; 113 111 }; 114 112 … … 144 142 static gboolean webKitWebSrcUnLock(GstBaseSrc*); 145 143 static gboolean webKitWebSrcUnLockStop(GstBaseSrc*); 144 static void webKitWebSrcSetContext(GstElement*, GstContext*); 146 145 147 146 #define webkit_web_src_parent_class parent_class … … 194 193 195 194 eklass->change_state = GST_DEBUG_FUNCPTR(webKitWebSrcChangeState); 195 eklass->set_context = GST_DEBUG_FUNCPTR(webKitWebSrcSetContext); 196 196 197 197 GstBaseSrcClass* baseSrcClass = GST_BASE_SRC_CLASS(klass); … … 316 316 break; 317 317 } 318 } 319 320 static void webKitWebSrcSetContext(GstElement* element, GstContext* context) 321 { 322 WebKitWebSrc* src = WEBKIT_WEB_SRC(element); 323 WebKitWebSrcPrivate* priv = src->priv; 324 325 GST_DEBUG_OBJECT(src, "context type: %s", gst_context_get_context_type(context)); 326 if (gst_context_has_context_type(context, WEBKIT_WEB_SRC_PLAYER_CONTEXT_TYPE_NAME)) { 327 const GValue* value = gst_structure_get_value(gst_context_get_structure(context), "player"); 328 priv->player = reinterpret_cast<MediaPlayer*>(g_value_get_pointer(value)); 329 } 330 GST_ELEMENT_CLASS(parent_class)->set_context(element, context); 318 331 } 319 332 … … 473 486 WebKitWebSrc* src = WEBKIT_WEB_SRC(baseSrc); 474 487 WebKitWebSrcPrivate* priv = src->priv; 475 ASSERT(priv->player); 488 489 if (!priv->player) { 490 GRefPtr<GstQuery> query = adoptGRef(gst_query_new_context(WEBKIT_WEB_SRC_PLAYER_CONTEXT_TYPE_NAME)); 491 if (gst_pad_peer_query(GST_BASE_SRC_PAD(baseSrc), query.get())) { 492 GstContext* context; 493 494 gst_query_parse_context(query.get(), &context); 495 gst_element_set_context(GST_ELEMENT_CAST(src), context); 496 } else 497 gst_element_post_message(GST_ELEMENT_CAST(src), gst_message_new_need_context(GST_OBJECT_CAST(src), WEBKIT_WEB_SRC_PLAYER_CONTEXT_TYPE_NAME)); 498 } 499 500 RELEASE_ASSERT(priv->player); 476 501 477 502 priv->wereHeadersReceived = false; … … 741 766 const gchar* const* webKitWebSrcGetProtocols(GType) 742 767 { 743 static const char* protocols[] = {" webkit+http", "webkit+https", "webkit+blob", nullptr };768 static const char* protocols[] = {"http", "https", "blob", nullptr }; 744 769 return protocols; 745 }746 747 static URL convertPlaybinURI(const char* uriString)748 {749 URL url(URL(), uriString);750 ASSERT(url.protocol().substring(0, 7) == "webkit+");751 url.setProtocol(url.protocol().substring(7).toString());752 return url;753 770 } 754 771 … … 775 792 return TRUE; 776 793 777 URL url = convertPlaybinURI(uri); 794 if (priv->originalURI.length()) { 795 GST_ERROR_OBJECT(src, "URI can only be set in states < PAUSED"); 796 return FALSE; 797 } 798 799 URL url(URL(), uri); 778 800 if (!urlHasSupportedProtocol(url)) { 779 801 g_set_error(error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, "Invalid URI '%s'", uri); … … 858 880 GST_DEBUG_OBJECT(src, "Received response: %d", response.httpStatusCode()); 859 881 860 auto origin = SecurityOrigin::create(response.url());861 m_origins.add(WTFMove(origin));862 863 882 auto responseURI = response.url().string().utf8(); 864 883 if (priv->originalURI != responseURI) 865 884 priv->redirectedURI = WTFMove(responseURI); 885 886 uint64_t length = response.expectedContentLength(); 887 if (length > 0 && priv->requestedPosition && response.httpStatusCode() == 206) 888 length += priv->requestedPosition; 889 890 priv->httpHeaders.reset(gst_structure_new_empty("http-headers")); 891 gst_structure_set(priv->httpHeaders.get(), "uri", G_TYPE_STRING, priv->originalURI.data(), 892 "http-status-code", G_TYPE_UINT, response.httpStatusCode(), nullptr); 893 if (!priv->redirectedURI.isNull()) 894 gst_structure_set(priv->httpHeaders.get(), "redirection-uri", G_TYPE_STRING, priv->redirectedURI.data(), nullptr); 895 GUniquePtr<GstStructure> headers(gst_structure_new_empty("request-headers")); 896 for (const auto& header : m_request.httpHeaderFields()) 897 gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_STRING, header.value.utf8().data(), nullptr); 898 GST_DEBUG_OBJECT(src, "Request headers going downstream: %" GST_PTR_FORMAT, headers.get()); 899 gst_structure_set(priv->httpHeaders.get(), "request-headers", GST_TYPE_STRUCTURE, headers.get(), nullptr); 900 headers.reset(gst_structure_new_empty("response-headers")); 901 for (const auto& header : response.httpHeaderFields()) { 902 bool ok = false; 903 uint64_t convertedValue = header.value.toUInt64(&ok); 904 if (ok) 905 gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_UINT64, convertedValue, nullptr); 906 else 907 gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_STRING, header.value.utf8().data(), nullptr); 908 } 909 auto contentLengthFieldName(httpHeaderNameString(HTTPHeaderName::ContentLength).toString()); 910 if (!gst_structure_has_field(headers.get(), contentLengthFieldName.utf8().data())) 911 gst_structure_set(headers.get(), contentLengthFieldName.utf8().data(), G_TYPE_UINT64, static_cast<uint64_t>(length), nullptr); 912 gst_structure_set(priv->httpHeaders.get(), "response-headers", GST_TYPE_STRUCTURE, headers.get(), nullptr); 913 GST_DEBUG_OBJECT(src, "Response headers going downstream: %" GST_PTR_FORMAT, headers.get()); 914 915 priv->httpHeadersEvent = adoptGRef(gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, gst_structure_copy(priv->httpHeaders.get()))); 916 917 auto scopeExit = makeScopeExit([&] { 918 GstStructure* structure = gst_structure_copy(src->priv->httpHeaders.get()); 919 gst_element_post_message(GST_ELEMENT_CAST(src), gst_message_new_element(GST_OBJECT_CAST(src), structure)); 920 }); 866 921 867 922 if (response.httpStatusCode() >= 400) { … … 892 947 } 893 948 894 long long length = response.expectedContentLength();895 if (length > 0 && priv->requestedPosition && response.httpStatusCode() == 206)896 length += priv->requestedPosition;897 898 949 priv->isSeekable = length > 0 && g_ascii_strcasecmp("none", response.httpHeaderField(HTTPHeaderName::AcceptRanges).utf8().data()); 899 950 900 GST_DEBUG_OBJECT(src, "Size: % lld, isSeekable: %s", length, boolForPrinting(priv->isSeekable));951 GST_DEBUG_OBJECT(src, "Size: %" G_GUINT64_FORMAT ", isSeekable: %s", length, boolForPrinting(priv->isSeekable)); 901 952 if (length > 0) { 902 if (!priv->haveSize || (static_cast<long long>(priv->size) != length)) {953 if (!priv->haveSize || priv->size != length) { 903 954 priv->haveSize = true; 904 955 priv->size = length; … … 929 980 { 930 981 LockHolder locker(priv->responseLock); 931 932 // Emit a GST_EVENT_CUSTOM_DOWNSTREAM_STICKY event and message to let933 // GStreamer know about the HTTP headers sent and received.934 GstStructure* httpHeaders = gst_structure_new_empty("http-headers");935 gst_structure_set(httpHeaders, "uri", G_TYPE_STRING, priv->originalURI.data(),936 "http-status-code", G_TYPE_UINT, response.httpStatusCode(), nullptr);937 if (!priv->redirectedURI.isNull())938 gst_structure_set(httpHeaders, "redirection-uri", G_TYPE_STRING, priv->redirectedURI.data(), nullptr);939 GUniquePtr<GstStructure> headers(gst_structure_new_empty("request-headers"));940 for (const auto& header : m_request.httpHeaderFields())941 gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_STRING, header.value.utf8().data(), nullptr);942 GST_DEBUG_OBJECT(src, "Request headers going downstream: %" GST_PTR_FORMAT, headers.get());943 gst_structure_set(httpHeaders, "request-headers", GST_TYPE_STRUCTURE, headers.get(), nullptr);944 headers.reset(gst_structure_new_empty("response-headers"));945 for (const auto& header : response.httpHeaderFields()) {946 bool ok = false;947 uint64_t convertedValue = header.value.toUInt64(&ok);948 if (ok)949 gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_UINT64, convertedValue, nullptr);950 else951 gst_structure_set(headers.get(), header.key.utf8().data(), G_TYPE_STRING, header.value.utf8().data(), nullptr);952 }953 auto contentLengthFieldName(httpHeaderNameString(HTTPHeaderName::ContentLength).toString());954 if (!gst_structure_has_field(headers.get(), contentLengthFieldName.utf8().data()))955 gst_structure_set(headers.get(), contentLengthFieldName.utf8().data(), G_TYPE_UINT64, static_cast<uint64_t>(length), nullptr);956 gst_structure_set(httpHeaders, "response-headers", GST_TYPE_STRUCTURE, headers.get(), nullptr);957 GST_DEBUG_OBJECT(src, "Response headers going downstream: %" GST_PTR_FORMAT, headers.get());958 959 gst_element_post_message(GST_ELEMENT_CAST(src), gst_message_new_element(GST_OBJECT_CAST(src), gst_structure_copy(httpHeaders)));960 961 priv->httpHeadersEvent = adoptGRef(gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, httpHeaders));962 982 priv->wereHeadersReceived = true; 963 983 priv->headersCondition.notifyOne(); … … 1042 1062 } 1043 1063 1044 bool webKitSrcWouldTaintOrigin(WebKitWebSrc* src, const SecurityOrigin& origin)1045 {1046 WebKitWebSrcPrivate* priv = src->priv;1047 1048 auto* cachedResourceStreamingClient = reinterpret_cast<CachedResourceStreamingClient*>(priv->resource->client());1049 for (auto& responseOrigin : cachedResourceStreamingClient->securityOrigins()) {1050 if (!origin.canAccess(*responseOrigin))1051 return true;1052 }1053 return false;1054 }1055 1056 1064 #endif // ENABLE(VIDEO) && USE(GSTREAMER) -
trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h
r243058 r243197 26 26 namespace WebCore { 27 27 class MediaPlayer; 28 class SecurityOrigin;29 28 } 30 29 … … 36 35 #define WEBKIT_IS_WEB_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_WEB_SRC)) 37 36 #define WEBKIT_IS_WEB_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_WEB_SRC)) 37 38 #define WEBKIT_WEB_SRC_PLAYER_CONTEXT_TYPE_NAME "webkit.media-player" 38 39 39 40 typedef struct _WebKitWebSrc WebKitWebSrc; … … 54 55 void webKitWebSrcSetMediaPlayer(WebKitWebSrc*, WebCore::MediaPlayer*); 55 56 bool webKitSrcPassedCORSAccessCheck(WebKitWebSrc*); 56 bool webKitSrcWouldTaintOrigin(WebKitWebSrc*, const WebCore::SecurityOrigin&);57 57 58 58 G_END_DECLS
Note: See TracChangeset
for help on using the changeset viewer.