Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(438)

Unified Diff: third_party/WebKit/Source/core/html/HTMLMediaElement.cpp

Issue 1815033003: Add srcObject attribute of type MediaStream to HTMLMediaElement. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: philipj's comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
index 06d4a93b6dfca9cb3d42b26427ecb7be2d3f6673..4d1e231a09a9e44a2db95305554a181721c8c437 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -83,6 +83,7 @@
#include "public/platform/WebAudioSourceProvider.h"
#include "public/platform/WebContentDecryptionModule.h"
#include "public/platform/WebInbandTextTrack.h"
+#include "public/platform/WebMediaStream.h"
#include "public/platform/modules/remoteplayback/WebRemotePlaybackClient.h"
#include "public/platform/modules/remoteplayback/WebRemotePlaybackState.h"
#include "wtf/CurrentTime.h"
@@ -631,7 +632,7 @@ Node::InsertionNotificationRequest HTMLMediaElement::insertedInto(ContainerNode*
HTMLElement::insertedInto(insertionPoint);
if (insertionPoint->inDocument()) {
UseCounter::count(document(), UseCounter::HTMLMediaElementInDocument);
- if (!getAttribute(srcAttr).isEmpty() && m_networkState == NETWORK_EMPTY) {
+ if ((!getAttribute(srcAttr).isEmpty() || m_srcObject.isMediaProviderObject()) && m_networkState == NETWORK_EMPTY) {
m_ignorePreloadNone = false;
invokeLoadAlgorithm();
}
@@ -726,6 +727,18 @@ void HTMLMediaElement::setSrc(const AtomicString& url)
setAttribute(srcAttr, url);
}
+void HTMLMediaElement::setSrcObject(const WebMediaPlayerSource& srcObject)
+{
+ // srcObject can be a media-provider object or null.
+ ASSERT(!srcObject.isURL());
+
+ // The srcObject IDL attribute, on setting, must set the element's assigned
+ // media provider object to the new value, and then invoke the element's
+ // media element load algorithm.
+ m_srcObject = srcObject;
+ invokeLoadAlgorithm();
+}
+
HTMLMediaElement::NetworkState HTMLMediaElement::getNetworkState() const
{
return m_networkState;
@@ -904,68 +917,97 @@ void HTMLMediaElement::selectMediaResource()
{
WTF_LOG(Media, "HTMLMediaElement::selectMediaResource(%p)", this);
- enum Mode { attribute, children };
-
- // 3 - If the media element has a src attribute, then let mode be attribute.
- Mode mode = attribute;
- if (!fastHasAttribute(srcAttr)) {
- // Otherwise, if the media element does not have a src attribute but has a source
- // element child, then let mode be children and let candidate be the first such
- // source element child in tree order.
- if (HTMLSourceElement* element = Traversal<HTMLSourceElement>::firstChild(*this)) {
- mode = children;
- m_nextChildNodeToConsider = element;
- m_currentSourceNode = nullptr;
- } else {
- // Otherwise the media element has neither a src attribute nor a source element
- // child: set the networkState to NETWORK_EMPTY, and abort these steps; the
- // synchronous section ends.
- m_loadState = WaitingForSource;
- setShouldDelayLoadEvent(false);
- setNetworkState(NETWORK_EMPTY);
- updateDisplayState();
+ enum Mode { Object, Attribute, Children, Nothing };
+ Mode mode = Nothing;
+
+ // 6 - If the media element has an assigned media provider object, then let
+ // mode be object.
+ if (m_srcObject.isMediaProviderObject()) {
+ mode = Object;
+ } else if (fastHasAttribute(srcAttr)) {
+ // Otherwise, if the media element has no assigned media provider object
+ // but has a src attribute, then let mode be attribute.
+ mode = Attribute;
+ } else if (HTMLSourceElement* element = Traversal<HTMLSourceElement>::firstChild(*this)) {
+ // Otherwise, if the media element does not have an assigned media
+ // provider object and does not have a src attribute, but does have a
+ // source element child, then let mode be children and let candidate be
+ // the first such source element child in tree order.
+ mode = Children;
+ m_nextChildNodeToConsider = element;
+ m_currentSourceNode = nullptr;
+ } else {
+ // Otherwise the media element has no assigned media provider object and
+ // has neither a src attribute nor a source element child: set the
+ // networkState to NETWORK_EMPTY, and abort these steps; the synchronous
+ // section ends.
+ m_loadState = WaitingForSource;
+ setShouldDelayLoadEvent(false);
+ setNetworkState(NETWORK_EMPTY);
+ updateDisplayState();
- WTF_LOG(Media, "HTMLMediaElement::selectMediaResource(%p), nothing to load", this);
- return;
- }
+ WTF_LOG(Media, "HTMLMediaElement::selectMediaResource(%p), nothing to load", this);
+ return;
}
- // 4 - Set the media element's delaying-the-load-event flag to true (this delays the load event),
- // and set its networkState to NETWORK_LOADING.
- setShouldDelayLoadEvent(true);
+ // 7 - Set the media element's networkState to NETWORK_LOADING.
setNetworkState(NETWORK_LOADING);
- // 5 - Queue a task to fire a simple event named loadstart at the media element.
+ // 8 - Queue a task to fire a simple event named loadstart at the media element.
scheduleEvent(EventTypeNames::loadstart);
- // 6 - If mode is attribute, then run these substeps
- if (mode == attribute) {
- m_loadState = LoadingFromSrcAttr;
+ // 9 - Run the appropriate steps...
+ switch (mode) {
+ case Object:
+ loadSourceFromObject();
+ WTF_LOG(Media, "HTMLMediaElement::selectMediaResource(%p), using 'srcObject' attribute", this);
+ break;
+ case Attribute:
+ loadSourceFromAttribute();
+ WTF_LOG(Media, "HTMLMediaElement::selectMediaResource(%p), using 'src' attribute url", this);
+ break;
+ case Children:
+ loadNextSourceChild();
+ WTF_LOG(Media, "HTMLMediaElement::selectMediaResource(%p), using source element", this);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+void HTMLMediaElement::loadSourceFromObject()
+{
+ ASSERT(m_srcObject.isMediaProviderObject());
+ m_loadState = LoadingFromSrcObject;
- const AtomicString& srcValue = fastGetAttribute(srcAttr);
- // If the src attribute's value is the empty string ... jump down to the failed step below
- if (srcValue.isEmpty()) {
- mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError);
- WTF_LOG(Media, "HTMLMediaElement::selectMediaResource(%p), empty 'src'", this);
- return;
- }
+ // No type is available when the resource comes from the 'srcObject'
+ // attribute.
+ ContentType contentType((String()));
+ loadResource(m_srcObject, contentType);
+}
- KURL mediaURL = document().completeURL(srcValue);
- if (!isSafeToLoadURL(mediaURL, Complain)) {
- mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError);
- return;
- }
+void HTMLMediaElement::loadSourceFromAttribute()
+{
+ m_loadState = LoadingFromSrcAttr;
+ const AtomicString& srcValue = fastGetAttribute(srcAttr);
- // No type is available when the url comes from the 'src' attribute so MediaPlayer
- // will have to pick a media engine based on the file extension.
- ContentType contentType((String()));
- loadResource(mediaURL, contentType);
- WTF_LOG(Media, "HTMLMediaElement::selectMediaResource(%p), using 'src' attribute url", this);
+ // If the src attribute's value is the empty string ... jump down to the failed step below
+ if (srcValue.isEmpty()) {
+ mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError);
+ WTF_LOG(Media, "HTMLMediaElement::selectMediaResource(%p), empty 'src'", this);
return;
}
- // Otherwise, the source elements will be used
- loadNextSourceChild();
+ KURL mediaURL = document().completeURL(srcValue);
+ if (!isSafeToLoadURL(mediaURL, Complain)) {
+ mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError);
+ return;
+ }
+
+ // No type is available when the url comes from the 'src' attribute so
+ // MediaPlayer will have to pick a media engine based on the file extension.
+ ContentType contentType((String()));
+ loadResource(WebMediaPlayerSource(WebURL(mediaURL)), contentType);
}
void HTMLMediaElement::loadNextSourceChild()
@@ -981,15 +1023,18 @@ void HTMLMediaElement::loadNextSourceChild()
resetMediaPlayerAndMediaSource();
m_loadState = LoadingFromSourceElement;
- loadResource(mediaURL, contentType);
+ loadResource(WebMediaPlayerSource(WebURL(mediaURL)), contentType);
}
-void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType)
+void HTMLMediaElement::loadResource(const WebMediaPlayerSource& source, ContentType& contentType)
{
ASSERT(isMainThread());
- ASSERT(isSafeToLoadURL(url, Complain));
-
- WTF_LOG(Media, "HTMLMediaElement::loadResource(%p, %s, %s)", this, urlForLoggingMedia(url).utf8().data(), contentType.raw().utf8().data());
+ KURL url;
+ if (source.isURL()) {
+ url = source.getAsURL();
+ ASSERT(isSafeToLoadURL(url, Complain));
+ WTF_LOG(Media, "HTMLMediaElement::loadResource(%p, %s, %s)", this, urlForLoggingMedia(url).utf8().data(), contentType.raw().utf8().data());
+ }
LocalFrame* frame = document().frame();
if (!frame) {
@@ -1026,8 +1071,10 @@ void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType)
bool attemptLoad = true;
- if (url.protocolIs(mediaSourceBlobProtocol)) {
- if (isMediaStreamURL(url.getString())) {
+ bool isObjectOrBlobURL = source.isMediaProviderObject() || url.protocolIs(mediaSourceBlobProtocol);
+ if (isObjectOrBlobURL) {
+ bool isMediaStream = source.isMediaStream() || (source.isURL() && isMediaStreamURL(url.getString()));
+ if (isMediaStream) {
m_autoplayHelper->removeUserGestureRequirement(GesturelessPlaybackEnabledByStream);
} else {
m_mediaSource = HTMLMediaSource::lookup(url.getString());
@@ -1043,7 +1090,8 @@ void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType)
}
}
- if (attemptLoad && canLoadURL(url, contentType)) {
+ bool canLoadResource = source.isMediaProviderObject() || canLoadURL(url, contentType);
+ if (attemptLoad && canLoadResource) {
ASSERT(!webMediaPlayer());
if (effectivePreloadType() == WebMediaPlayer::PreloadNone) {
@@ -1067,24 +1115,33 @@ void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType)
void HTMLMediaElement::startPlayerLoad()
{
ASSERT(!m_webMediaPlayer);
- // Filter out user:pass as those two URL components aren't
- // considered for media resource fetches (including for the CORS
- // use-credentials mode.) That behavior aligns with Gecko, with IE
- // being more restrictive and not allowing fetches to such URLs.
- //
- // Spec reference: http://whatwg.org/c/#concept-media-load-resource
- //
- // FIXME: when the HTML spec switches to specifying resource
- // fetches in terms of Fetch (http://fetch.spec.whatwg.org), and
- // along with that potentially also specifying a setting for its
- // 'authentication flag' to control how user:pass embedded in a
- // media resource URL should be treated, then update the handling
- // here to match.
- KURL requestURL = m_currentSrc;
- if (!requestURL.user().isEmpty())
- requestURL.setUser(String());
- if (!requestURL.pass().isEmpty())
- requestURL.setPass(String());
+
+ WebMediaPlayerSource source;
+ if (m_srcObject.isMediaProviderObject()) {
+ source = m_srcObject;
+ } else {
+ // Filter out user:pass as those two URL components aren't
+ // considered for media resource fetches (including for the CORS
+ // use-credentials mode.) That behavior aligns with Gecko, with IE
+ // being more restrictive and not allowing fetches to such URLs.
+ //
+ // Spec reference: http://whatwg.org/c/#concept-media-load-resource
+ //
+ // FIXME: when the HTML spec switches to specifying resource
+ // fetches in terms of Fetch (http://fetch.spec.whatwg.org), and
+ // along with that potentially also specifying a setting for its
+ // 'authentication flag' to control how user:pass embedded in a
+ // media resource URL should be treated, then update the handling
+ // here to match.
+ KURL requestURL = m_currentSrc;
+ if (!requestURL.user().isEmpty())
+ requestURL.setUser(String());
+ if (!requestURL.pass().isEmpty())
+ requestURL.setPass(String());
+
+ KURL kurl(ParsedURLString, requestURL);
+ source = WebMediaPlayerSource(WebURL(kurl));
+ }
LocalFrame* frame = document().frame();
// TODO(srirama.m): Figure out how frame can be null when
@@ -1094,8 +1151,7 @@ void HTMLMediaElement::startPlayerLoad()
return;
}
- KURL kurl(ParsedURLString, requestURL);
- m_webMediaPlayer = frame->loader().client()->createWebMediaPlayer(*this, kurl, this);
+ m_webMediaPlayer = frame->loader().client()->createWebMediaPlayer(*this, source, this);
if (!m_webMediaPlayer) {
mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError);
return;
@@ -1111,7 +1167,7 @@ void HTMLMediaElement::startPlayerLoad()
m_webMediaPlayer->setPreload(effectivePreloadType());
- m_webMediaPlayer->load(loadType(), kurl, corsMode());
+ m_webMediaPlayer->load(loadType(), source, corsMode());
if (isFullscreen()) {
// This handles any transition to or from fullscreen overlay mode.
@@ -1204,7 +1260,7 @@ WebMediaPlayer::LoadType HTMLMediaElement::loadType() const
if (m_mediaSource)
return WebMediaPlayer::LoadTypeMediaSource;
- if (isMediaStreamURL(m_currentSrc.getString()))
+ if (m_srcObject.isMediaStream() || isMediaStreamURL(m_currentSrc.getString()))
return WebMediaPlayer::LoadTypeMediaStream;
return WebMediaPlayer::LoadTypeURL;

Powered by Google App Engine
This is Rietveld 408576698