Chromium Code Reviews| 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 1c3684d23427119f7b38e5ca3f7a72d901d702f6..5d099557e1f6b2be158805e4c17e5c7f36991a93 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" |
| @@ -623,7 +624,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 (m_networkState == NETWORK_EMPTY && (!getAttribute(srcAttr).isEmpty() || m_source.isMediaProviderObject())) { |
|
philipj_slow
2016/04/06 11:58:42
Hmm, why this change? This block of code isn't per
Guido Urdaneta
2016/04/06 16:34:54
Nothing broke with or without this change.
wolenet
philipj_slow
2016/04/07 15:38:11
What could now be broken when using srcObject is m
Guido Urdaneta
2016/04/08 10:58:47
I think it makes sense to add the srcObject check
|
| m_ignorePreloadNone = false; |
| invokeLoadAlgorithm(); |
| } |
| @@ -718,6 +719,15 @@ void HTMLMediaElement::setSrc(const AtomicString& url) |
| setAttribute(srcAttr, url); |
| } |
| +void HTMLMediaElement::setSrcObject(const WebMediaElementSource& srcObject) |
| +{ |
| + // 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_source = srcObject; |
|
philipj_slow
2016/04/06 11:58:42
Looking at this I'm thinking that it'd be cleaner
Guido Urdaneta
2016/04/06 16:34:55
Done.
|
| + invokeLoadAlgorithm(); |
| +} |
| + |
| HTMLMediaElement::NetworkState HTMLMediaElement::getNetworkState() const |
| { |
| return m_networkState; |
| @@ -896,68 +906,98 @@ 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_source.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(); |
| + } |
| +} |
| - 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; |
| - } |
| +void HTMLMediaElement::loadSourceFromObject() |
| +{ |
| + ASSERT(m_source.isMediaProviderObject()); |
| + m_loadState = LoadingFromSrcObject; |
| - KURL mediaURL = document().completeURL(srcValue); |
| - if (!isSafeToLoadURL(mediaURL, Complain)) { |
| - mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError); |
| - return; |
| - } |
| + // No type is available when the resource comes from the 'srcObject' |
| + // attribute. |
| + ContentType contentType((String())); |
| + loadResource(contentType); |
| +} |
| - // 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); |
| +void HTMLMediaElement::loadSourceFromAttribute() |
| +{ |
| + m_loadState = LoadingFromSrcAttr; |
| + 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; |
| } |
| - // 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())); |
| + m_source = WebMediaElementSource(WebURL(mediaURL)); |
|
philipj_slow
2016/04/06 11:58:42
Here, rather than setting m_source/m_srcObject, ca
Guido Urdaneta
2016/04/06 16:34:55
Done.
|
| + loadResource(contentType); |
| } |
| void HTMLMediaElement::loadNextSourceChild() |
| @@ -973,15 +1013,19 @@ void HTMLMediaElement::loadNextSourceChild() |
| resetMediaPlayerAndMediaSource(); |
| m_loadState = LoadingFromSourceElement; |
| - loadResource(mediaURL, contentType); |
| + m_source = WebMediaElementSource(WebURL(mediaURL)); |
|
philipj_slow
2016/04/06 11:58:42
Ditto.
Guido Urdaneta
2016/04/06 16:34:54
Done.
|
| + loadResource(contentType); |
| } |
| -void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType) |
| +void HTMLMediaElement::loadResource(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 (m_source.isURL()) { |
| + url = m_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) { |
| @@ -1018,8 +1062,10 @@ void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType) |
| bool attemptLoad = true; |
| - if (url.protocolIs(mediaSourceBlobProtocol)) { |
| - if (isMediaStreamURL(url.getString())) { |
| + bool isBlobProtocol = m_source.isMediaProviderObject() || url.protocolIs(mediaSourceBlobProtocol); |
|
philipj_slow
2016/04/06 11:58:42
I guess isObjectOrBlobURL or something would be mo
Guido Urdaneta
2016/04/06 16:34:55
Done.
|
| + if (isBlobProtocol) { |
| + bool isMediaStream = m_source.isMediaStream() || (m_source.isURL() && isMediaStreamURL(url.getString())); |
| + if (isMediaStream) { |
| m_autoplayHelper->removeUserGestureRequirement(GesturelessPlaybackEnabledByStream); |
| } else { |
| m_mediaSource = HTMLMediaSource::lookup(url.getString()); |
| @@ -1035,7 +1081,8 @@ void HTMLMediaElement::loadResource(const KURL& url, ContentType& contentType) |
| } |
| } |
| - if (attemptLoad && canLoadURL(url, contentType)) { |
| + bool canLoadResource = m_source.isMediaProviderObject() || canLoadURL(url, contentType); |
| + if (attemptLoad && canLoadResource) { |
| ASSERT(!webMediaPlayer()); |
| if (effectivePreloadType() == WebMediaPlayer::PreloadNone) { |
| @@ -1059,24 +1106,30 @@ 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()); |
| + |
| + if (m_source.isURL()) { |
|
philipj_slow
2016/04/06 11:58:42
This will have to change with my proposed changes
Guido Urdaneta
2016/04/06 16:34:55
Done.
|
| + // 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); |
| + m_source = WebMediaElementSource(WebURL(kurl)); |
| + } |
| LocalFrame* frame = document().frame(); |
| // TODO(srirama.m): Figure out how frame can be null when |
| @@ -1086,8 +1139,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, m_source, this); |
| if (!m_webMediaPlayer) { |
| mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError); |
| return; |
| @@ -1103,7 +1155,7 @@ void HTMLMediaElement::startPlayerLoad() |
| m_webMediaPlayer->setPreload(effectivePreloadType()); |
| - m_webMediaPlayer->load(loadType(), kurl, corsMode()); |
| + m_webMediaPlayer->load(loadType(), m_source, corsMode()); |
| if (isFullscreen()) { |
| // This handles any transition to or from fullscreen overlay mode. |
| @@ -1196,6 +1248,9 @@ WebMediaPlayer::LoadType HTMLMediaElement::loadType() const |
| if (m_mediaSource) |
| return WebMediaPlayer::LoadTypeMediaSource; |
| + if (m_source.isMediaStream()) |
| + return WebMediaPlayer::LoadTypeMediaStream; |
| + |
| if (isMediaStreamURL(m_currentSrc.getString())) |
| return WebMediaPlayer::LoadTypeMediaStream; |