Remove all uses of PassRefPtr in WebCore/svg
[WebKit-https.git] / Source / WebCore / html / HTMLMediaElement.cpp
1 /*
2  * Copyright (C) 2007-2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #if ENABLE(VIDEO)
28 #include "HTMLMediaElement.h"
29
30 #include "ApplicationCacheHost.h"
31 #include "ApplicationCacheResource.h"
32 #include "Attribute.h"
33 #include "CSSPropertyNames.h"
34 #include "CSSValueKeywords.h"
35 #include "ChromeClient.h"
36 #include "ClientRect.h"
37 #include "ClientRectList.h"
38 #include "ContentSecurityPolicy.h"
39 #include "ContentType.h"
40 #include "CookieJar.h"
41 #include "DiagnosticLoggingClient.h"
42 #include "DiagnosticLoggingKeys.h"
43 #include "DisplaySleepDisabler.h"
44 #include "Document.h"
45 #include "DocumentLoader.h"
46 #include "ElementIterator.h"
47 #include "EventNames.h"
48 #include "ExceptionCodePlaceholder.h"
49 #include "FrameLoader.h"
50 #include "FrameLoaderClient.h"
51 #include "FrameView.h"
52 #include "HTMLSourceElement.h"
53 #include "HTMLVideoElement.h"
54 #include "JSHTMLMediaElement.h"
55 #include "Language.h"
56 #include "Logging.h"
57 #include "MIMETypeRegistry.h"
58 #include "MainFrame.h"
59 #include "MediaController.h"
60 #include "MediaControls.h"
61 #include "MediaDocument.h"
62 #include "MediaError.h"
63 #include "MediaFragmentURIParser.h"
64 #include "MediaKeyEvent.h"
65 #include "MediaList.h"
66 #include "MediaPlayer.h"
67 #include "MediaQueryEvaluator.h"
68 #include "MediaResourceLoader.h"
69 #include "MemoryPressureHandler.h"
70 #include "NetworkingContext.h"
71 #include "PageGroup.h"
72 #include "PageThrottler.h"
73 #include "PlatformMediaSessionManager.h"
74 #include "ProgressTracker.h"
75 #include "RenderLayerCompositor.h"
76 #include "RenderVideo.h"
77 #include "RenderView.h"
78 #include "ResourceLoadInfo.h"
79 #include "ScriptController.h"
80 #include "ScriptSourceCode.h"
81 #include "SecurityPolicy.h"
82 #include "SessionID.h"
83 #include "Settings.h"
84 #include "ShadowRoot.h"
85 #include "TimeRanges.h"
86 #include "UserContentController.h"
87 #include <limits>
88 #include <runtime/Uint8Array.h>
89 #include <wtf/CurrentTime.h>
90 #include <wtf/MathExtras.h>
91 #include <wtf/Ref.h>
92 #include <wtf/text/CString.h>
93
94 #if ENABLE(VIDEO_TRACK)
95 #include "AudioTrackList.h"
96 #include "HTMLTrackElement.h"
97 #include "InbandGenericTextTrack.h"
98 #include "InbandTextTrackPrivate.h"
99 #include "InbandWebVTTTextTrack.h"
100 #include "RuntimeEnabledFeatures.h"
101 #include "TextTrackCueList.h"
102 #include "TextTrackList.h"
103 #include "VideoTrackList.h"
104 #endif
105
106 #if ENABLE(WEB_AUDIO)
107 #include "AudioSourceProvider.h"
108 #include "MediaElementAudioSourceNode.h"
109 #endif
110
111 #if PLATFORM(IOS)
112 #include "RuntimeApplicationChecksIOS.h"
113 #endif
114
115 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
116 #include "WebKitPlaybackTargetAvailabilityEvent.h"
117 #endif
118
119 #if ENABLE(MEDIA_SESSION)
120 #include "MediaSession.h"
121 #endif
122
123 #if ENABLE(MEDIA_SOURCE)
124 #include "DOMWindow.h"
125 #include "MediaSource.h"
126 #include "Performance.h"
127 #include "VideoPlaybackQuality.h"
128 #endif
129
130 #if ENABLE(MEDIA_STREAM)
131 #include "MediaStream.h"
132 #include "MediaStreamRegistry.h"
133 #endif
134
135 #if ENABLE(ENCRYPTED_MEDIA_V2)
136 #include "MediaKeyNeededEvent.h"
137 #include "MediaKeys.h"
138 #endif
139
140 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
141 #include "JSMediaControlsHost.h"
142 #include "MediaControlsHost.h"
143 #include "ScriptGlobalObject.h"
144 #include <bindings/ScriptObject.h>
145 #endif
146
147 namespace WebCore {
148
149 static const double SeekRepeatDelay = 0.1;
150 static const double SeekTime = 0.2;
151 static const double ScanRepeatDelay = 1.5;
152 static const double ScanMaximumRate = 8;
153
154 static void setFlags(unsigned& value, unsigned flags)
155 {
156     value |= flags;
157 }
158
159 static void clearFlags(unsigned& value, unsigned flags)
160 {
161     value &= ~flags;
162 }
163     
164 #if !LOG_DISABLED
165 static String urlForLoggingMedia(const URL& url)
166 {
167     static const unsigned maximumURLLengthForLogging = 128;
168
169     if (url.string().length() < maximumURLLengthForLogging)
170         return url.string();
171     return url.string().substring(0, maximumURLLengthForLogging) + "...";
172 }
173
174 static const char* boolString(bool val)
175 {
176     return val ? "true" : "false";
177 }
178 #endif
179
180 #ifndef LOG_MEDIA_EVENTS
181 // Default to not logging events because so many are generated they can overwhelm the rest of 
182 // the logging.
183 #define LOG_MEDIA_EVENTS 0
184 #endif
185
186 #ifndef LOG_CACHED_TIME_WARNINGS
187 // Default to not logging warnings about excessive drift in the cached media time because it adds a
188 // fair amount of overhead and logging.
189 #define LOG_CACHED_TIME_WARNINGS 0
190 #endif
191
192 #if ENABLE(MEDIA_SOURCE)
193 // URL protocol used to signal that the media source API is being used.
194 static const char* mediaSourceBlobProtocol = "blob";
195 #endif
196
197 #if ENABLE(MEDIA_STREAM)
198 // URL protocol used to signal that the media stream API is being used.
199 static const char* mediaStreamBlobProtocol = "blob";
200 #endif
201
202 using namespace HTMLNames;
203
204 typedef HashMap<Document*, HashSet<HTMLMediaElement*>> DocumentElementSetMap;
205 static DocumentElementSetMap& documentToElementSetMap()
206 {
207     DEPRECATED_DEFINE_STATIC_LOCAL(DocumentElementSetMap, map, ());
208     return map;
209 }
210
211 static void addElementToDocumentMap(HTMLMediaElement& element, Document& document)
212 {
213     DocumentElementSetMap& map = documentToElementSetMap();
214     HashSet<HTMLMediaElement*> set = map.take(&document);
215     set.add(&element);
216     map.add(&document, set);
217 }
218
219 static void removeElementFromDocumentMap(HTMLMediaElement& element, Document& document)
220 {
221     DocumentElementSetMap& map = documentToElementSetMap();
222     HashSet<HTMLMediaElement*> set = map.take(&document);
223     set.remove(&element);
224     if (!set.isEmpty())
225         map.add(&document, set);
226 }
227
228 #if ENABLE(ENCRYPTED_MEDIA)
229 static ExceptionCode exceptionCodeForMediaKeyException(MediaPlayer::MediaKeyException exception)
230 {
231     switch (exception) {
232     case MediaPlayer::NoError:
233         return 0;
234     case MediaPlayer::InvalidPlayerState:
235         return INVALID_STATE_ERR;
236     case MediaPlayer::KeySystemNotSupported:
237         return NOT_SUPPORTED_ERR;
238     }
239
240     ASSERT_NOT_REACHED();
241     return INVALID_STATE_ERR;
242 }
243 #endif
244
245 #if ENABLE(VIDEO_TRACK)
246 class TrackDisplayUpdateScope {
247 public:
248     TrackDisplayUpdateScope(HTMLMediaElement* mediaElement)
249     {
250         m_mediaElement = mediaElement;
251         m_mediaElement->beginIgnoringTrackDisplayUpdateRequests();
252     }
253     ~TrackDisplayUpdateScope()
254     {
255         ASSERT(m_mediaElement);
256         m_mediaElement->endIgnoringTrackDisplayUpdateRequests();
257     }
258     
259 private:
260     HTMLMediaElement* m_mediaElement;
261 };
262 #endif
263
264 struct HTMLMediaElement::TrackGroup {
265     enum GroupKind { CaptionsAndSubtitles, Description, Chapter, Metadata, Other };
266
267     TrackGroup(GroupKind kind)
268         : visibleTrack(0)
269         , defaultTrack(0)
270         , kind(kind)
271         , hasSrcLang(false)
272     {
273     }
274
275     Vector<RefPtr<TextTrack>> tracks;
276     RefPtr<TextTrack> visibleTrack;
277     RefPtr<TextTrack> defaultTrack;
278     GroupKind kind;
279     bool hasSrcLang;
280 };
281
282 HashSet<HTMLMediaElement*>& HTMLMediaElement::allMediaElements()
283 {
284     static NeverDestroyed<HashSet<HTMLMediaElement*>> elements;
285     return elements;
286 }
287
288 #if ENABLE(MEDIA_SESSION)
289 typedef HashMap<uint64_t, HTMLMediaElement*> IDToElementMap;
290
291 static IDToElementMap& elementIDsToElements()
292 {
293     static NeverDestroyed<IDToElementMap> map;
294     return map;
295 }
296
297 HTMLMediaElement* HTMLMediaElement::elementWithID(uint64_t id)
298 {
299     if (id == HTMLMediaElementInvalidID)
300         return nullptr;
301     
302     return elementIDsToElements().get(id);
303 }
304
305 static uint64_t nextElementID()
306 {
307     static uint64_t elementID = 0;
308     return ++elementID;
309 }
310 #endif
311
312 HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& document, bool createdByParser)
313     : HTMLElement(tagName, document)
314     , ActiveDOMObject(&document)
315     , m_pendingActionTimer(*this, &HTMLMediaElement::pendingActionTimerFired)
316     , m_progressEventTimer(*this, &HTMLMediaElement::progressEventTimerFired)
317     , m_playbackProgressTimer(*this, &HTMLMediaElement::playbackProgressTimerFired)
318     , m_scanTimer(*this, &HTMLMediaElement::scanTimerFired)
319     , m_seekTaskQueue(document)
320     , m_resizeTaskQueue(document)
321     , m_shadowDOMTaskQueue(document)
322     , m_playedTimeRanges()
323     , m_asyncEventQueue(*this)
324     , m_requestedPlaybackRate(1)
325     , m_reportedPlaybackRate(1)
326     , m_defaultPlaybackRate(1)
327     , m_webkitPreservesPitch(true)
328     , m_networkState(NETWORK_EMPTY)
329     , m_readyState(HAVE_NOTHING)
330     , m_readyStateMaximum(HAVE_NOTHING)
331     , m_volume(1.0f)
332     , m_volumeInitialized(false)
333     , m_previousProgressTime(std::numeric_limits<double>::max())
334     , m_clockTimeAtLastUpdateEvent(0)
335     , m_lastTimeUpdateEventMovieTime(MediaTime::positiveInfiniteTime())
336     , m_loadState(WaitingForSource)
337     , m_videoFullscreenMode(VideoFullscreenModeNone)
338 #if PLATFORM(IOS)
339     , m_videoFullscreenGravity(MediaPlayer::VideoGravityResizeAspect)
340 #endif
341     , m_preload(MediaPlayer::Auto)
342     , m_displayMode(Unknown)
343     , m_processingMediaPlayerCallback(0)
344 #if ENABLE(MEDIA_SOURCE)
345     , m_droppedVideoFrames(0)
346 #endif
347     , m_clockTimeAtLastCachedTimeUpdate(0)
348     , m_minimumClockTimeToUpdateCachedTime(0)
349     , m_pendingActionFlags(0)
350     , m_actionAfterScan(Nothing)
351     , m_scanType(Scan)
352     , m_scanDirection(Forward)
353     , m_firstTimePlaying(true)
354     , m_playing(false)
355     , m_isWaitingUntilMediaCanStart(false)
356     , m_shouldDelayLoadEvent(false)
357     , m_haveFiredLoadedData(false)
358     , m_inActiveDocument(true)
359     , m_autoplaying(true)
360     , m_muted(false)
361     , m_explicitlyMuted(false)
362     , m_initiallyMuted(false)
363     , m_paused(true)
364     , m_seeking(false)
365     , m_sentStalledEvent(false)
366     , m_sentEndEvent(false)
367     , m_pausedInternal(false)
368     , m_sendProgressEvents(true)
369     , m_closedCaptionsVisible(false)
370     , m_webkitLegacyClosedCaptionOverride(false)
371     , m_completelyLoaded(false)
372     , m_havePreparedToPlay(false)
373     , m_parsingInProgress(createdByParser)
374     , m_elementIsHidden(document.hidden())
375 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
376     , m_mediaControlsDependOnPageScaleFactor(false)
377 #endif
378 #if ENABLE(VIDEO_TRACK)
379     , m_tracksAreReady(true)
380     , m_haveVisibleTextTrack(false)
381     , m_processingPreferenceChange(false)
382     , m_lastTextTrackUpdateTime(MediaTime(-1, 1))
383     , m_captionDisplayMode(CaptionUserPreferences::Automatic)
384     , m_audioTracks(0)
385     , m_textTracks(0)
386     , m_videoTracks(0)
387     , m_ignoreTrackDisplayUpdate(0)
388 #endif
389 #if ENABLE(WEB_AUDIO)
390     , m_audioSourceNode(0)
391 #endif
392     , m_mediaSession(std::make_unique<MediaElementSession>(*this))
393     , m_reportedExtraMemoryCost(0)
394 #if ENABLE(MEDIA_STREAM)
395     , m_mediaStreamSrcObject(nullptr)
396 #endif
397 {
398     allMediaElements().add(this);
399
400     LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this);
401     setHasCustomStyleResolveCallbacks();
402
403     m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForFullscreen);
404     m_mediaSession->addBehaviorRestriction(MediaElementSession::RequirePageConsentToLoadMedia);
405 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
406     m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureToAutoplayToExternalDevice);
407 #endif
408
409     // FIXME: We should clean up and look to better merge the iOS and non-iOS code below.
410     Settings* settings = document.settings();
411 #if !PLATFORM(IOS)
412     if (settings && settings->requiresUserGestureForMediaPlayback()) {
413         m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForRateChange);
414         m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForLoad);
415     }
416 #else
417     m_sendProgressEvents = false;
418     if (!settings || settings->requiresUserGestureForMediaPlayback()) {
419         // Allow autoplay in a MediaDocument that is not in an iframe.
420         if (document.ownerElement() || !document.isMediaDocument())
421             m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForRateChange);
422 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
423         m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker);
424 #endif
425     } else {
426         // Relax RequireUserGestureForFullscreen when requiresUserGestureForMediaPlayback is not set:
427         m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequireUserGestureForFullscreen);
428     }
429 #endif // !PLATFORM(IOS)
430
431     if (settings && settings->audioPlaybackRequiresUserGesture() && settings->requiresUserGestureForMediaPlayback())
432         m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForAudioRateChange);
433
434     if (!settings || !settings->mediaDataLoadsAutomatically())
435         m_mediaSession->addBehaviorRestriction(MediaElementSession::AutoPreloadingNotPermitted);
436
437 #if ENABLE(VIDEO_TRACK)
438     if (document.page())
439         m_captionDisplayMode = document.page()->group().captionPreferences()->captionDisplayMode();
440 #endif
441
442 #if ENABLE(MEDIA_SESSION)
443     m_elementID = nextElementID();
444     elementIDsToElements().add(m_elementID, this);
445
446     setSessionInternal(document.defaultMediaSession());
447 #endif
448
449     registerWithDocument(document);
450 }
451
452 HTMLMediaElement::~HTMLMediaElement()
453 {
454     LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this);
455
456     allMediaElements().remove(this);
457
458     m_asyncEventQueue.close();
459
460     setShouldDelayLoadEvent(false);
461     unregisterWithDocument(document());
462
463 #if ENABLE(VIDEO_TRACK)
464     if (m_audioTracks) {
465         m_audioTracks->clearElement();
466         for (unsigned i = 0; i < m_audioTracks->length(); ++i)
467             m_audioTracks->item(i)->clearClient();
468     }
469     if (m_textTracks)
470         m_textTracks->clearElement();
471     if (m_textTracks) {
472         for (unsigned i = 0; i < m_textTracks->length(); ++i)
473             m_textTracks->item(i)->clearClient();
474     }
475     if (m_videoTracks) {
476         m_videoTracks->clearElement();
477         for (unsigned i = 0; i < m_videoTracks->length(); ++i)
478             m_videoTracks->item(i)->clearClient();
479     }
480 #endif
481
482 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
483     if (hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent)) {
484         m_hasPlaybackTargetAvailabilityListeners = false;
485         m_mediaSession->setHasPlaybackTargetAvailabilityListeners(*this, false);
486         updateMediaState();
487     }
488 #endif
489
490     if (m_mediaController) {
491         m_mediaController->removeMediaElement(this);
492         m_mediaController = nullptr;
493     }
494
495 #if ENABLE(MEDIA_SOURCE)
496     closeMediaSource();
497 #endif
498
499 #if ENABLE(ENCRYPTED_MEDIA_V2)
500     setMediaKeys(0);
501 #endif
502
503 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
504     if (m_isolatedWorld)
505         m_isolatedWorld->clearWrappers();
506 #endif
507
508 #if ENABLE(MEDIA_SESSION)
509     if (m_session) {
510         m_session->removeMediaElement(*this);
511         m_session = nullptr;
512     }
513
514     elementIDsToElements().remove(m_elementID);
515 #endif
516
517     m_seekTaskQueue.close();
518
519     m_completelyLoaded = true;
520 }
521
522 void HTMLMediaElement::registerWithDocument(Document& document)
523 {
524     m_mediaSession->registerWithDocument(document);
525
526     if (m_isWaitingUntilMediaCanStart)
527         document.addMediaCanStartListener(this);
528
529 #if !PLATFORM(IOS)
530     document.registerForMediaVolumeCallbacks(this);
531     document.registerForPrivateBrowsingStateChangedCallbacks(this);
532 #endif
533
534     document.registerForVisibilityStateChangedCallbacks(this);
535
536 #if ENABLE(VIDEO_TRACK)
537     if (m_requireCaptionPreferencesChangedCallbacks)
538         document.registerForCaptionPreferencesChangedCallbacks(this);
539 #endif
540
541 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
542     if (m_mediaControlsDependOnPageScaleFactor)
543         document.registerForPageScaleFactorChangedCallbacks(this);
544 #endif
545
546 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
547     document.registerForPageCacheSuspensionCallbacks(this);
548 #endif
549
550     document.registerForAllowsMediaDocumentInlinePlaybackChangedCallbacks(*this);
551
552     document.addAudioProducer(this);
553     addElementToDocumentMap(*this, document);
554 }
555
556 void HTMLMediaElement::unregisterWithDocument(Document& document)
557 {
558     m_mediaSession->unregisterWithDocument(document);
559
560     if (m_isWaitingUntilMediaCanStart)
561         document.removeMediaCanStartListener(this);
562
563 #if !PLATFORM(IOS)
564     document.unregisterForMediaVolumeCallbacks(this);
565     document.unregisterForPrivateBrowsingStateChangedCallbacks(this);
566 #endif
567
568     document.unregisterForVisibilityStateChangedCallbacks(this);
569
570 #if ENABLE(VIDEO_TRACK)
571     if (m_requireCaptionPreferencesChangedCallbacks)
572         document.unregisterForCaptionPreferencesChangedCallbacks(this);
573 #endif
574
575 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
576     if (m_mediaControlsDependOnPageScaleFactor)
577         document.unregisterForPageScaleFactorChangedCallbacks(this);
578 #endif
579
580 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
581     document.unregisterForPageCacheSuspensionCallbacks(this);
582 #endif
583
584     document.unregisterForAllowsMediaDocumentInlinePlaybackChangedCallbacks(*this);
585
586     document.removeAudioProducer(this);
587     removeElementFromDocumentMap(*this, document);
588 }
589
590 void HTMLMediaElement::didMoveToNewDocument(Document* oldDocument)
591 {
592     if (m_shouldDelayLoadEvent) {
593         if (oldDocument)
594             oldDocument->decrementLoadEventDelayCount();
595         document().incrementLoadEventDelayCount();
596     }
597
598     if (oldDocument)
599         unregisterWithDocument(*oldDocument);
600
601     registerWithDocument(document());
602
603     HTMLElement::didMoveToNewDocument(oldDocument);
604 }
605
606 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
607 void HTMLMediaElement::documentWillSuspendForPageCache()
608 {
609     m_mediaSession->unregisterWithDocument(document());
610 }
611
612 void HTMLMediaElement::documentDidResumeFromPageCache()
613 {
614     m_mediaSession->registerWithDocument(document());
615 }
616 #endif
617
618 bool HTMLMediaElement::hasCustomFocusLogic() const
619 {
620     return true;
621 }
622
623 bool HTMLMediaElement::supportsFocus() const
624 {
625     if (document().isMediaDocument())
626         return false;
627
628     // If no controls specified, we should still be able to focus the element if it has tabIndex.
629     return controls() ||  HTMLElement::supportsFocus();
630 }
631
632 bool HTMLMediaElement::isMouseFocusable() const
633 {
634     return false;
635 }
636
637 void HTMLMediaElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
638 {
639     if (name == srcAttr) {
640 #if PLATFORM(IOS)
641         // Note, unless the restriction on requiring user action has been removed,
642         // do not begin downloading data on iOS.
643         if (!value.isNull() && m_mediaSession->dataLoadingPermitted(*this))
644 #else
645         // Trigger a reload, as long as the 'src' attribute is present.
646         if (!value.isNull())
647 #endif
648         {
649             clearMediaPlayer(LoadMediaResource);
650             scheduleDelayedAction(LoadMediaResource);
651         }
652     } else if (name == controlsAttr)
653         configureMediaControls();
654     else if (name == loopAttr)
655         updateSleepDisabling();
656     else if (name == preloadAttr) {
657         if (equalIgnoringCase(value, "none"))
658             m_preload = MediaPlayer::None;
659         else if (equalIgnoringCase(value, "metadata"))
660             m_preload = MediaPlayer::MetaData;
661         else {
662             // The spec does not define an "invalid value default" but "auto" is suggested as the
663             // "missing value default", so use it for everything except "none" and "metadata"
664             m_preload = MediaPlayer::Auto;
665         }
666
667         // The attribute must be ignored if the autoplay attribute is present
668         if (!autoplay() && m_player)
669             m_player->setPreload(m_mediaSession->effectivePreloadForElement(*this));
670
671     } else if (name == mediagroupAttr)
672         setMediaGroup(value);
673     else
674         HTMLElement::parseAttribute(name, value);
675 }
676
677 void HTMLMediaElement::finishParsingChildren()
678 {
679     HTMLElement::finishParsingChildren();
680     m_parsingInProgress = false;
681     
682 #if ENABLE(VIDEO_TRACK)
683     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
684         return;
685
686     if (descendantsOfType<HTMLTrackElement>(*this).first())
687         scheduleDelayedAction(ConfigureTextTracks);
688 #endif
689 }
690
691 bool HTMLMediaElement::rendererIsNeeded(const RenderStyle& style)
692 {
693     return controls() && HTMLElement::rendererIsNeeded(style);
694 }
695
696 RenderPtr<RenderElement> HTMLMediaElement::createElementRenderer(Ref<RenderStyle>&& style, const RenderTreePosition&)
697 {
698     return createRenderer<RenderMedia>(*this, WTF::move(style));
699 }
700
701 bool HTMLMediaElement::childShouldCreateRenderer(const Node& child) const
702 {
703 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
704     return hasShadowRootParent(child) && HTMLElement::childShouldCreateRenderer(child);
705 #else
706     if (!hasMediaControls())
707         return false;
708     // <media> doesn't allow its content, including shadow subtree, to
709     // be rendered. So this should return false for most of the children.
710     // One exception is a shadow tree built for rendering controls which should be visible.
711     // So we let them go here by comparing its subtree root with one of the controls.
712     return &mediaControls()->treeScope() == &child.treeScope()
713         && hasShadowRootParent(child)
714         && HTMLElement::childShouldCreateRenderer(child);
715 #endif
716 }
717
718 Node::InsertionNotificationRequest HTMLMediaElement::insertedInto(ContainerNode& insertionPoint)
719 {
720     LOG(Media, "HTMLMediaElement::insertedInto(%p)", this);
721
722     HTMLElement::insertedInto(insertionPoint);
723     if (insertionPoint.inDocument()) {
724         m_inActiveDocument = true;
725
726 #if PLATFORM(IOS)
727         if (m_networkState == NETWORK_EMPTY && !fastGetAttribute(srcAttr).isEmpty() && m_mediaSession->dataLoadingPermitted(*this))
728 #else
729         if (m_networkState == NETWORK_EMPTY && !fastGetAttribute(srcAttr).isEmpty())
730 #endif
731             scheduleDelayedAction(LoadMediaResource);
732     }
733
734     if (!m_explicitlyMuted) {
735         m_explicitlyMuted = true;
736         m_muted = fastHasAttribute(mutedAttr);
737     }
738
739     configureMediaControls();
740     return InsertionDone;
741 }
742
743 void HTMLMediaElement::removedFrom(ContainerNode& insertionPoint)
744 {
745     LOG(Media, "HTMLMediaElement::removedFrom(%p)", this);
746
747     m_inActiveDocument = false;
748     if (insertionPoint.inDocument()) {
749         if (hasMediaControls())
750             mediaControls()->hide();
751         if (m_networkState > NETWORK_EMPTY)
752             pause();
753         if (m_videoFullscreenMode != VideoFullscreenModeNone)
754             exitFullscreen();
755
756         if (m_player) {
757             size_t extraMemoryCost = m_player->extraMemoryCost();
758             if (extraMemoryCost > m_reportedExtraMemoryCost) {
759                 JSC::VM& vm = JSDOMWindowBase::commonVM();
760                 JSC::JSLockHolder lock(vm);
761
762                 size_t extraMemoryCostDelta = extraMemoryCost - m_reportedExtraMemoryCost;
763                 m_reportedExtraMemoryCost = extraMemoryCost;
764                 // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
765                 // https://bugs.webkit.org/show_bug.cgi?id=142595
766                 vm.heap.deprecatedReportExtraMemory(extraMemoryCostDelta);
767             }
768         }
769     }
770
771     HTMLElement::removedFrom(insertionPoint);
772 }
773
774 void HTMLMediaElement::willAttachRenderers()
775 {
776     ASSERT(!renderer());
777 }
778
779 void HTMLMediaElement::didAttachRenderers()
780 {
781     if (renderer())
782         renderer()->updateFromElement();
783 }
784
785 void HTMLMediaElement::didRecalcStyle(Style::Change)
786 {
787     if (renderer())
788         renderer()->updateFromElement();
789 }
790
791 void HTMLMediaElement::scheduleDelayedAction(DelayedActionType actionType)
792 {
793     LOG(Media, "HTMLMediaElement::scheduleLoad(%p)", this);
794
795     if ((actionType & LoadMediaResource) && !(m_pendingActionFlags & LoadMediaResource)) {
796         prepareForLoad();
797         setFlags(m_pendingActionFlags, LoadMediaResource);
798     }
799
800 #if ENABLE(VIDEO_TRACK)
801     if (RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled() && (actionType & ConfigureTextTracks))
802         setFlags(m_pendingActionFlags, ConfigureTextTracks);
803 #endif
804
805 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
806     if (actionType & CheckPlaybackTargetCompatablity)
807         setFlags(m_pendingActionFlags, CheckPlaybackTargetCompatablity);
808 #endif
809
810     if (actionType & CheckMediaState)
811         setFlags(m_pendingActionFlags, CheckMediaState);
812
813     m_pendingActionTimer.startOneShot(0);
814 }
815
816 void HTMLMediaElement::scheduleNextSourceChild()
817 {
818     // Schedule the timer to try the next <source> element WITHOUT resetting state ala prepareForLoad.
819     setFlags(m_pendingActionFlags, LoadMediaResource);
820     m_pendingActionTimer.startOneShot(0);
821 }
822
823 void HTMLMediaElement::scheduleEvent(const AtomicString& eventName)
824 {
825 #if LOG_MEDIA_EVENTS
826     LOG(Media, "HTMLMediaElement::scheduleEvent(%p) - scheduling '%s'", this, eventName.string().ascii().data());
827 #endif
828     RefPtr<Event> event = Event::create(eventName, false, true);
829     
830     // Don't set the event target, the event queue will set it in GenericEventQueue::timerFired and setting it here
831     // will trigger an ASSERT if this element has been marked for deletion.
832
833     m_asyncEventQueue.enqueueEvent(event.release());
834 }
835
836 void HTMLMediaElement::pendingActionTimerFired()
837 {
838     Ref<HTMLMediaElement> protect(*this); // loadNextSourceChild may fire 'beforeload', which can make arbitrary DOM mutations.
839
840 #if ENABLE(VIDEO_TRACK)
841     if (RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled() && (m_pendingActionFlags & ConfigureTextTracks))
842         configureTextTracks();
843 #endif
844
845     if (m_pendingActionFlags & LoadMediaResource) {
846         if (m_loadState == LoadingFromSourceElement)
847             loadNextSourceChild();
848         else
849             loadInternal();
850     }
851
852 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
853     if (m_pendingActionFlags & CheckPlaybackTargetCompatablity && m_player && m_player->isCurrentPlaybackTargetWireless() && !m_player->canPlayToWirelessPlaybackTarget()) {
854         LOG(Media, "HTMLMediaElement::pendingActionTimerFired(%p) - calling setShouldPlayToPlaybackTarget(false)", this);
855         m_failedToPlayToWirelessTarget = true;
856         m_player->setShouldPlayToPlaybackTarget(false);
857     }
858
859     if (m_pendingActionFlags & CheckMediaState)
860         updateMediaState();
861 #endif
862
863     m_pendingActionFlags = 0;
864 }
865
866 PassRefPtr<MediaError> HTMLMediaElement::error() const 
867 {
868     return m_error;
869 }
870
871 void HTMLMediaElement::setSrc(const String& url)
872 {
873     setAttribute(srcAttr, url);
874 }
875
876 #if ENABLE(MEDIA_STREAM)
877 void HTMLMediaElement::setSrcObject(MediaStream* mediaStream)
878 {
879     // FIXME: Setting the srcObject attribute may cause other changes to the media element's internal state:
880     // Specifically, if srcObject is specified, the UA must use it as the source of media, even if the src
881     // attribute is also set or children are present. If the value of srcObject is replaced or set to null
882     // the UA must re-run the media element load algorithm.
883     //
884     // https://bugs.webkit.org/show_bug.cgi?id=124896
885
886     m_mediaStreamSrcObject = mediaStream;
887 }
888 #endif
889
890 HTMLMediaElement::NetworkState HTMLMediaElement::networkState() const
891 {
892     return m_networkState;
893 }
894
895 String HTMLMediaElement::canPlayType(const String& mimeType, const String& keySystem, const URL& url) const
896 {
897     MediaEngineSupportParameters parameters;
898     ContentType contentType(mimeType);
899     parameters.type = contentType.type().lower();
900     parameters.codecs = contentType.parameter(ASCIILiteral("codecs"));
901     parameters.url = url;
902 #if ENABLE(ENCRYPTED_MEDIA)
903     parameters.keySystem = keySystem;
904 #else
905     UNUSED_PARAM(keySystem);
906 #endif
907     MediaPlayer::SupportsType support = MediaPlayer::supportsType(parameters, this);
908     String canPlay;
909
910     // 4.8.10.3
911     switch (support)
912     {
913         case MediaPlayer::IsNotSupported:
914             canPlay = emptyString();
915             break;
916         case MediaPlayer::MayBeSupported:
917             canPlay = ASCIILiteral("maybe");
918             break;
919         case MediaPlayer::IsSupported:
920             canPlay = ASCIILiteral("probably");
921             break;
922     }
923     
924     LOG(Media, "HTMLMediaElement::canPlayType(%p) - [%s, %s, %s] -> %s", this, mimeType.utf8().data(), keySystem.utf8().data(), url.stringCenterEllipsizedToLength().utf8().data(), canPlay.utf8().data());
925
926     return canPlay;
927 }
928
929 double HTMLMediaElement::getStartDate() const
930 {
931     return m_player->getStartDate().toDouble();
932 }
933
934 void HTMLMediaElement::load()
935 {
936     Ref<HTMLMediaElement> protect(*this); // loadInternal may result in a 'beforeload' event, which can make arbitrary DOM mutations.
937     
938     LOG(Media, "HTMLMediaElement::load(%p)", this);
939     
940     if (!m_mediaSession->dataLoadingPermitted(*this))
941         return;
942     if (ScriptController::processingUserGestureForMedia())
943         removeBehaviorsRestrictionsAfterFirstUserGesture();
944
945     prepareForLoad();
946     loadInternal();
947     prepareToPlay();
948 }
949
950 void HTMLMediaElement::prepareForLoad()
951 {
952     LOG(Media, "HTMLMediaElement::prepareForLoad(%p)", this);
953
954     // Perform the cleanup required for the resource load algorithm to run.
955     stopPeriodicTimers();
956     m_pendingActionTimer.stop();
957     // FIXME: Figure out appropriate place to reset LoadTextTrackResource if necessary and set m_pendingActionFlags to 0 here.
958     m_pendingActionFlags &= ~LoadMediaResource;
959     m_sentEndEvent = false;
960     m_sentStalledEvent = false;
961     m_haveFiredLoadedData = false;
962     m_completelyLoaded = false;
963     m_havePreparedToPlay = false;
964     m_displayMode = Unknown;
965     m_currentSrc = URL();
966
967 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
968     m_failedToPlayToWirelessTarget = false;
969 #endif
970
971     // 1 - Abort any already-running instance of the resource selection algorithm for this element.
972     m_loadState = WaitingForSource;
973     m_currentSourceNode = nullptr;
974
975     // 2 - If there are any tasks from the media element's media element event task source in 
976     // one of the task queues, then remove those tasks.
977     cancelPendingEventsAndCallbacks();
978
979     // 3 - If the media element's networkState is set to NETWORK_LOADING or NETWORK_IDLE, queue
980     // a task to fire a simple event named abort at the media element.
981     if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE)
982         scheduleEvent(eventNames().abortEvent);
983
984 #if ENABLE(MEDIA_SOURCE)
985     closeMediaSource();
986 #endif
987
988     createMediaPlayer();
989
990     // 4 - If the media element's networkState is not set to NETWORK_EMPTY, then run these substeps
991     if (m_networkState != NETWORK_EMPTY) {
992         // 4.1 - Queue a task to fire a simple event named emptied at the media element.
993         scheduleEvent(eventNames().emptiedEvent);
994
995         // 4.2 - If a fetching process is in progress for the media element, the user agent should stop it.
996         m_networkState = NETWORK_EMPTY;
997
998         // 4.3 - Forget the media element's media-resource-specific tracks.
999         forgetResourceSpecificTracks();
1000
1001         // 4.4 - If readyState is not set to HAVE_NOTHING, then set it to that state.
1002         m_readyState = HAVE_NOTHING;
1003         m_readyStateMaximum = HAVE_NOTHING;
1004
1005         // 4.5 - If the paused attribute is false, then set it to true.
1006         m_paused = true;
1007
1008         // 4.6 - If seeking is true, set it to false.
1009         clearSeeking();
1010
1011         // 4.7 - Set the current playback position to 0.
1012         //       Set the official playback position to 0.
1013         //       If this changed the official playback position, then queue a task to fire a simple event named timeupdate at the media element.
1014         // FIXME: Add support for firing this event. e.g., scheduleEvent(eventNames().timeUpdateEvent);
1015
1016         // 4.8 - Set the initial playback position to 0.
1017         // FIXME: Make this less subtle. The position only becomes 0 because of the createMediaPlayer() call
1018         // above.
1019         refreshCachedTime();
1020
1021         invalidateCachedTime();
1022
1023         // 4.9 - Set the timeline offset to Not-a-Number (NaN).
1024         // 4.10 - Update the duration attribute to Not-a-Number (NaN).
1025
1026         updateMediaController();
1027 #if ENABLE(VIDEO_TRACK)
1028         if (RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
1029             updateActiveTextTrackCues(MediaTime::zeroTime());
1030 #endif
1031     }
1032
1033     // 5 - Set the playbackRate attribute to the value of the defaultPlaybackRate attribute.
1034     setPlaybackRate(defaultPlaybackRate());
1035
1036     // 6 - Set the error attribute to null and the autoplaying flag to true.
1037     m_error = nullptr;
1038     m_autoplaying = true;
1039
1040     // 7 - Invoke the media element's resource selection algorithm.
1041
1042     // 8 - Note: Playback of any previously playing media resource for this element stops.
1043
1044     // The resource selection algorithm
1045     // 1 - Set the networkState to NETWORK_NO_SOURCE
1046     m_networkState = NETWORK_NO_SOURCE;
1047
1048     // 2 - Asynchronously await a stable state.
1049
1050     m_playedTimeRanges = TimeRanges::create();
1051
1052     // FIXME: Investigate whether these can be moved into m_networkState != NETWORK_EMPTY block above
1053     // so they are closer to the relevant spec steps.
1054     m_lastSeekTime = MediaTime::zeroTime();
1055
1056     // The spec doesn't say to block the load event until we actually run the asynchronous section
1057     // algorithm, but do it now because we won't start that until after the timer fires and the 
1058     // event may have already fired by then.
1059     MediaPlayer::Preload effectivePreload = m_mediaSession->effectivePreloadForElement(*this);
1060     if (effectivePreload != MediaPlayer::None)
1061         setShouldDelayLoadEvent(true);
1062
1063 #if PLATFORM(IOS)
1064     if (effectivePreload != MediaPlayer::None && m_mediaSession->allowsAutomaticMediaDataLoading(*this))
1065         prepareToPlay();
1066 #endif
1067
1068     configureMediaControls();
1069 }
1070
1071 void HTMLMediaElement::loadInternal()
1072 {
1073     // Some of the code paths below this function dispatch the BeforeLoad event. This ASSERT helps
1074     // us catch those bugs more quickly without needing all the branches to align to actually
1075     // trigger the event.
1076     ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
1077
1078     // If we can't start a load right away, start it later.
1079     if (!m_mediaSession->pageAllowsDataLoading(*this)) {
1080         setShouldDelayLoadEvent(false);
1081         if (m_isWaitingUntilMediaCanStart)
1082             return;
1083         document().addMediaCanStartListener(this);
1084         m_isWaitingUntilMediaCanStart = true;
1085         return;
1086     }
1087
1088     clearFlags(m_pendingActionFlags, LoadMediaResource);
1089
1090     // Once the page has allowed an element to load media, it is free to load at will. This allows a 
1091     // playlist that starts in a foreground tab to continue automatically if the tab is subsequently 
1092     // put into the background.
1093     m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequirePageConsentToLoadMedia);
1094
1095 #if ENABLE(VIDEO_TRACK)
1096     if (hasMediaControls())
1097         mediaControls()->changedClosedCaptionsVisibility();
1098
1099     // HTMLMediaElement::textTracksAreReady will need "... the text tracks whose mode was not in the
1100     // disabled state when the element's resource selection algorithm last started".
1101     if (RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled()) {
1102         m_textTracksWhenResourceSelectionBegan.clear();
1103         if (m_textTracks) {
1104             for (unsigned i = 0; i < m_textTracks->length(); ++i) {
1105                 TextTrack* track = m_textTracks->item(i);
1106                 if (track->mode() != TextTrack::disabledKeyword())
1107                     m_textTracksWhenResourceSelectionBegan.append(track);
1108             }
1109         }
1110     }
1111 #endif
1112
1113     selectMediaResource();
1114 }
1115
1116 void HTMLMediaElement::selectMediaResource()
1117 {
1118     LOG(Media, "HTMLMediaElement::selectMediaResource(%p)", this);
1119
1120     enum Mode { attribute, children };
1121
1122     // 3 - If the media element has a src attribute, then let mode be attribute.
1123     Mode mode = attribute;
1124     if (!fastHasAttribute(srcAttr)) {
1125         // Otherwise, if the media element does not have a src attribute but has a source 
1126         // element child, then let mode be children and let candidate be the first such 
1127         // source element child in tree order.
1128         if (auto firstSource = childrenOfType<HTMLSourceElement>(*this).first()) {
1129             mode = children;
1130             m_nextChildNodeToConsider = firstSource;
1131             m_currentSourceNode = nullptr;
1132         } else {
1133             // Otherwise the media element has neither a src attribute nor a source element 
1134             // child: set the networkState to NETWORK_EMPTY, and abort these steps; the 
1135             // synchronous section ends.
1136             m_loadState = WaitingForSource;
1137             setShouldDelayLoadEvent(false);
1138             m_networkState = NETWORK_EMPTY;
1139
1140             LOG(Media, "HTMLMediaElement::selectMediaResource(%p) - nothing to load", this);
1141             return;
1142         }
1143     }
1144
1145     // 4 - Set the media element's delaying-the-load-event flag to true (this delays the load event), 
1146     // and set its networkState to NETWORK_LOADING.
1147     setShouldDelayLoadEvent(true);
1148     m_networkState = NETWORK_LOADING;
1149
1150     // 5 - Queue a task to fire a simple event named loadstart at the media element.
1151     scheduleEvent(eventNames().loadstartEvent);
1152
1153     // 6 - If mode is attribute, then run these substeps
1154     if (mode == attribute) {
1155         m_loadState = LoadingFromSrcAttr;
1156
1157         // If the src attribute's value is the empty string ... jump down to the failed step below
1158         URL mediaURL = getNonEmptyURLAttribute(srcAttr);
1159         if (mediaURL.isEmpty()) {
1160             mediaLoadingFailed(MediaPlayer::FormatError);
1161             LOG(Media, "HTMLMediaElement::selectMediaResource(%p) -  empty 'src'", this);
1162             return;
1163         }
1164
1165         if (!isSafeToLoadURL(mediaURL, Complain) || !dispatchBeforeLoadEvent(mediaURL.string())) {
1166             mediaLoadingFailed(MediaPlayer::FormatError);
1167             return;
1168         }
1169
1170         // No type or key system information is available when the url comes
1171         // from the 'src' attribute so MediaPlayer
1172         // will have to pick a media engine based on the file extension.
1173         ContentType contentType((String()));
1174         loadResource(mediaURL, contentType, String());
1175         LOG(Media, "HTMLMediaElement::selectMediaResource(%p) - using 'src' attribute url", this);
1176         return;
1177     }
1178
1179     // Otherwise, the source elements will be used
1180     loadNextSourceChild();
1181 }
1182
1183 void HTMLMediaElement::loadNextSourceChild()
1184 {
1185     ContentType contentType((String()));
1186     String keySystem;
1187     URL mediaURL = selectNextSourceChild(&contentType, &keySystem, Complain);
1188     if (!mediaURL.isValid()) {
1189         waitForSourceChange();
1190         return;
1191     }
1192
1193     // Recreate the media player for the new url
1194     createMediaPlayer();
1195
1196     m_loadState = LoadingFromSourceElement;
1197     loadResource(mediaURL, contentType, keySystem);
1198 }
1199
1200 void HTMLMediaElement::loadResource(const URL& initialURL, ContentType& contentType, const String& keySystem)
1201 {
1202     ASSERT(isSafeToLoadURL(initialURL, Complain));
1203
1204     LOG(Media, "HTMLMediaElement::loadResource(%p) - %s, %s, %s", this, urlForLoggingMedia(initialURL).utf8().data(), contentType.raw().utf8().data(), keySystem.utf8().data());
1205
1206     Frame* frame = document().frame();
1207     if (!frame) {
1208         mediaLoadingFailed(MediaPlayer::FormatError);
1209         return;
1210     }
1211
1212     Page* page = frame->page();
1213     if (!page) {
1214         mediaLoadingFailed(MediaPlayer::FormatError);
1215         return;
1216     }
1217
1218     URL url = initialURL;
1219     if (!frame->loader().willLoadMediaElementURL(url)) {
1220         mediaLoadingFailed(MediaPlayer::FormatError);
1221         return;
1222     }
1223
1224 #if ENABLE(CONTENT_EXTENSIONS)
1225     ResourceRequest request(url);
1226     DocumentLoader* documentLoader = frame->loader().documentLoader();
1227
1228     if (page->userContentController() && documentLoader)
1229         page->userContentController()->processContentExtensionRulesForLoad(*page, request, ResourceType::Media, *documentLoader);
1230
1231     if (request.isNull()) {
1232         mediaLoadingFailed(MediaPlayer::FormatError);
1233         return;
1234     }
1235 #endif
1236
1237     // The resource fetch algorithm 
1238     m_networkState = NETWORK_LOADING;
1239
1240     // If the url should be loaded from the application cache, pass the url of the cached file
1241     // to the media engine.
1242     ApplicationCacheHost* cacheHost = frame->loader().documentLoader()->applicationCacheHost();
1243     ApplicationCacheResource* resource = 0;
1244     if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(url), resource)) {
1245         // Resources that are not present in the manifest will always fail to load (at least, after the
1246         // cache has been primed the first time), making the testing of offline applications simpler.
1247         if (!resource || resource->path().isEmpty()) {
1248             mediaLoadingFailed(MediaPlayer::NetworkError);
1249             return;
1250         }
1251     }
1252
1253     // Log that we started loading a media element.
1254     if (Frame* frame = document().frame())
1255         frame->mainFrame().diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::mediaKey(), isVideo() ? DiagnosticLoggingKeys::videoKey() : DiagnosticLoggingKeys::audioKey(), DiagnosticLoggingKeys::loadingKey(), ShouldSample::No);
1256
1257     m_firstTimePlaying = true;
1258
1259     // Set m_currentSrc *before* changing to the cache url, the fact that we are loading from the app
1260     // cache is an internal detail not exposed through the media element API.
1261     m_currentSrc = url;
1262
1263     if (resource) {
1264         url = ApplicationCacheHost::createFileURL(resource->path());
1265         LOG(Media, "HTMLMediaElement::loadResource(%p) - will load from app cache -> %s", this, urlForLoggingMedia(url).utf8().data());
1266     }
1267
1268     LOG(Media, "HTMLMediaElement::loadResource(%p) - m_currentSrc -> %s", this, urlForLoggingMedia(m_currentSrc).utf8().data());
1269
1270 #if ENABLE(MEDIA_STREAM)
1271     if (MediaStreamRegistry::registry().lookup(url.string()))
1272         m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequireUserGestureForRateChange);
1273 #endif
1274
1275     if (m_sendProgressEvents) 
1276         startProgressEventTimer();
1277
1278     bool privateMode = document().page() && document().page()->usesEphemeralSession();
1279     m_player->setPrivateBrowsingMode(privateMode);
1280
1281     // Reset display mode to force a recalculation of what to show because we are resetting the player.
1282     setDisplayMode(Unknown);
1283
1284     if (!autoplay())
1285         m_player->setPreload(m_mediaSession->effectivePreloadForElement(*this));
1286     m_player->setPreservesPitch(m_webkitPreservesPitch);
1287
1288     if (!m_explicitlyMuted) {
1289         m_explicitlyMuted = true;
1290         m_muted = fastHasAttribute(mutedAttr);
1291     }
1292
1293     updateVolume();
1294
1295 #if ENABLE(MEDIA_SOURCE)
1296     ASSERT(!m_mediaSource);
1297
1298     if (url.protocolIs(mediaSourceBlobProtocol))
1299         m_mediaSource = MediaSource::lookup(url.string());
1300
1301     if (m_mediaSource) {
1302         if (m_mediaSource->attachToElement(this))
1303             m_player->load(url, contentType, m_mediaSource.get());
1304         else {
1305             // Forget our reference to the MediaSource, so we leave it alone
1306             // while processing remainder of load failure.
1307             m_mediaSource = nullptr;
1308             mediaLoadingFailed(MediaPlayer::FormatError);
1309         }
1310     } else
1311 #endif
1312 #if ENABLE(MEDIA_STREAM)
1313         if (m_mediaStreamSrcObject)
1314             m_player->load(m_mediaStreamSrcObject->privateStream());
1315         else
1316 #endif
1317     if (!m_player->load(url, contentType, keySystem))
1318         mediaLoadingFailed(MediaPlayer::FormatError);
1319
1320     // If there is no poster to display, allow the media engine to render video frames as soon as
1321     // they are available.
1322     updateDisplayState();
1323
1324     if (renderer())
1325         renderer()->updateFromElement();
1326 }
1327
1328 #if ENABLE(VIDEO_TRACK)
1329 static bool trackIndexCompare(TextTrack* a,
1330                               TextTrack* b)
1331 {
1332     return a->trackIndex() - b->trackIndex() < 0;
1333 }
1334
1335 static bool eventTimeCueCompare(const std::pair<MediaTime, TextTrackCue*>& a, const std::pair<MediaTime, TextTrackCue*>& b)
1336 {
1337     // 12 - Sort the tasks in events in ascending time order (tasks with earlier
1338     // times first).
1339     if (a.first != b.first)
1340         return a.first - b.first < MediaTime::zeroTime();
1341
1342     // If the cues belong to different text tracks, it doesn't make sense to
1343     // compare the two tracks by the relative cue order, so return the relative
1344     // track order.
1345     if (a.second->track() != b.second->track())
1346         return trackIndexCompare(a.second->track(), b.second->track());
1347
1348     // 12 - Further sort tasks in events that have the same time by the
1349     // relative text track cue order of the text track cues associated
1350     // with these tasks.
1351     return a.second->cueIndex() - b.second->cueIndex() < 0;
1352 }
1353
1354 static bool compareCueInterval(const CueInterval& one, const CueInterval& two)
1355 {
1356     return one.data()->isOrderedBefore(two.data());
1357 };
1358
1359
1360 void HTMLMediaElement::updateActiveTextTrackCues(const MediaTime& movieTime)
1361 {
1362     // 4.8.10.8 Playing the media resource
1363
1364     //  If the current playback position changes while the steps are running,
1365     //  then the user agent must wait for the steps to complete, and then must
1366     //  immediately rerun the steps.
1367     if (ignoreTrackDisplayUpdateRequests())
1368         return;
1369
1370     LOG(Media, "HTMLMediaElement::updateActiveTextTracks(%p)", this);
1371
1372     // 1 - Let current cues be a list of cues, initialized to contain all the
1373     // cues of all the hidden, showing, or showing by default text tracks of the
1374     // media element (not the disabled ones) whose start times are less than or
1375     // equal to the current playback position and whose end times are greater
1376     // than the current playback position.
1377     CueList currentCues;
1378
1379     // The user agent must synchronously unset [the text track cue active] flag
1380     // whenever ... the media element's readyState is changed back to HAVE_NOTHING.
1381     if (m_readyState != HAVE_NOTHING && m_player) {
1382         currentCues = m_cueTree.allOverlaps(m_cueTree.createInterval(movieTime, movieTime));
1383         if (currentCues.size() > 1)
1384             std::sort(currentCues.begin(), currentCues.end(), &compareCueInterval);
1385     }
1386
1387     CueList previousCues;
1388     CueList missedCues;
1389
1390     // 2 - Let other cues be a list of cues, initialized to contain all the cues
1391     // of hidden, showing, and showing by default text tracks of the media
1392     // element that are not present in current cues.
1393     previousCues = m_currentlyActiveCues;
1394
1395     // 3 - Let last time be the current playback position at the time this
1396     // algorithm was last run for this media element, if this is not the first
1397     // time it has run.
1398     MediaTime lastTime = m_lastTextTrackUpdateTime;
1399
1400     // 4 - If the current playback position has, since the last time this
1401     // algorithm was run, only changed through its usual monotonic increase
1402     // during normal playback, then let missed cues be the list of cues in other
1403     // cues whose start times are greater than or equal to last time and whose
1404     // end times are less than or equal to the current playback position.
1405     // Otherwise, let missed cues be an empty list.
1406     if (lastTime >= MediaTime::zeroTime() && m_lastSeekTime < movieTime) {
1407         CueList potentiallySkippedCues =
1408             m_cueTree.allOverlaps(m_cueTree.createInterval(lastTime, movieTime));
1409
1410         for (size_t i = 0; i < potentiallySkippedCues.size(); ++i) {
1411             MediaTime cueStartTime = potentiallySkippedCues[i].low();
1412             MediaTime cueEndTime = potentiallySkippedCues[i].high();
1413
1414             // Consider cues that may have been missed since the last seek time.
1415             if (cueStartTime > std::max(m_lastSeekTime, lastTime) && cueEndTime < movieTime)
1416                 missedCues.append(potentiallySkippedCues[i]);
1417         }
1418     }
1419
1420     m_lastTextTrackUpdateTime = movieTime;
1421
1422     // 5 - If the time was reached through the usual monotonic increase of the
1423     // current playback position during normal playback, and if the user agent
1424     // has not fired a timeupdate event at the element in the past 15 to 250ms
1425     // and is not still running event handlers for such an event, then the user
1426     // agent must queue a task to fire a simple event named timeupdate at the
1427     // element. (In the other cases, such as explicit seeks, relevant events get
1428     // fired as part of the overall process of changing the current playback
1429     // position.)
1430     if (!m_paused && m_lastSeekTime <= lastTime)
1431         scheduleTimeupdateEvent(false);
1432
1433     // Explicitly cache vector sizes, as their content is constant from here.
1434     size_t currentCuesSize = currentCues.size();
1435     size_t missedCuesSize = missedCues.size();
1436     size_t previousCuesSize = previousCues.size();
1437
1438     // 6 - If all of the cues in current cues have their text track cue active
1439     // flag set, none of the cues in other cues have their text track cue active
1440     // flag set, and missed cues is empty, then abort these steps.
1441     bool activeSetChanged = missedCuesSize;
1442
1443     for (size_t i = 0; !activeSetChanged && i < previousCuesSize; ++i)
1444         if (!currentCues.contains(previousCues[i]) && previousCues[i].data()->isActive())
1445             activeSetChanged = true;
1446
1447     for (size_t i = 0; i < currentCuesSize; ++i) {
1448         TextTrackCue* cue = currentCues[i].data();
1449
1450         if (cue->isRenderable())
1451             toVTTCue(cue)->updateDisplayTree(movieTime);
1452
1453         if (!cue->isActive())
1454             activeSetChanged = true;
1455     }
1456
1457     if (!activeSetChanged)
1458         return;
1459
1460     // 7 - If the time was reached through the usual monotonic increase of the
1461     // current playback position during normal playback, and there are cues in
1462     // other cues that have their text track cue pause-on-exi flag set and that
1463     // either have their text track cue active flag set or are also in missed
1464     // cues, then immediately pause the media element.
1465     for (size_t i = 0; !m_paused && i < previousCuesSize; ++i) {
1466         if (previousCues[i].data()->pauseOnExit()
1467             && previousCues[i].data()->isActive()
1468             && !currentCues.contains(previousCues[i]))
1469             pause();
1470     }
1471
1472     for (size_t i = 0; !m_paused && i < missedCuesSize; ++i) {
1473         if (missedCues[i].data()->pauseOnExit())
1474             pause();
1475     }
1476
1477     // 8 - Let events be a list of tasks, initially empty. Each task in this
1478     // list will be associated with a text track, a text track cue, and a time,
1479     // which are used to sort the list before the tasks are queued.
1480     Vector<std::pair<MediaTime, TextTrackCue*>> eventTasks;
1481
1482     // 8 - Let affected tracks be a list of text tracks, initially empty.
1483     Vector<TextTrack*> affectedTracks;
1484
1485     for (size_t i = 0; i < missedCuesSize; ++i) {
1486         // 9 - For each text track cue in missed cues, prepare an event named enter
1487         // for the TextTrackCue object with the text track cue start time.
1488         eventTasks.append(std::make_pair(missedCues[i].data()->startMediaTime(),
1489                                          missedCues[i].data()));
1490
1491         // 10 - For each text track [...] in missed cues, prepare an event
1492         // named exit for the TextTrackCue object with the  with the later of
1493         // the text track cue end time and the text track cue start time.
1494
1495         // Note: An explicit task is added only if the cue is NOT a zero or
1496         // negative length cue. Otherwise, the need for an exit event is
1497         // checked when these tasks are actually queued below. This doesn't
1498         // affect sorting events before dispatch either, because the exit
1499         // event has the same time as the enter event.
1500         if (missedCues[i].data()->startMediaTime() < missedCues[i].data()->endMediaTime())
1501             eventTasks.append(std::make_pair(missedCues[i].data()->endMediaTime(), missedCues[i].data()));
1502     }
1503
1504     for (size_t i = 0; i < previousCuesSize; ++i) {
1505         // 10 - For each text track cue in other cues that has its text
1506         // track cue active flag set prepare an event named exit for the
1507         // TextTrackCue object with the text track cue end time.
1508         if (!currentCues.contains(previousCues[i]))
1509             eventTasks.append(std::make_pair(previousCues[i].data()->endMediaTime(),
1510                                              previousCues[i].data()));
1511     }
1512
1513     for (size_t i = 0; i < currentCuesSize; ++i) {
1514         // 11 - For each text track cue in current cues that does not have its
1515         // text track cue active flag set, prepare an event named enter for the
1516         // TextTrackCue object with the text track cue start time.
1517         if (!previousCues.contains(currentCues[i]))
1518             eventTasks.append(std::make_pair(currentCues[i].data()->startMediaTime(),
1519                                              currentCues[i].data()));
1520     }
1521
1522     // 12 - Sort the tasks in events in ascending time order (tasks with earlier
1523     // times first).
1524     std::sort(eventTasks.begin(), eventTasks.end(), eventTimeCueCompare);
1525
1526     for (size_t i = 0; i < eventTasks.size(); ++i) {
1527         if (!affectedTracks.contains(eventTasks[i].second->track()))
1528             affectedTracks.append(eventTasks[i].second->track());
1529
1530         // 13 - Queue each task in events, in list order.
1531         RefPtr<Event> event;
1532
1533         // Each event in eventTasks may be either an enterEvent or an exitEvent,
1534         // depending on the time that is associated with the event. This
1535         // correctly identifies the type of the event, if the startTime is
1536         // less than the endTime in the cue.
1537         if (eventTasks[i].second->startTime() >= eventTasks[i].second->endTime()) {
1538             event = Event::create(eventNames().enterEvent, false, false);
1539             event->setTarget(eventTasks[i].second);
1540             m_asyncEventQueue.enqueueEvent(event.release());
1541
1542             event = Event::create(eventNames().exitEvent, false, false);
1543             event->setTarget(eventTasks[i].second);
1544             m_asyncEventQueue.enqueueEvent(event.release());
1545         } else {
1546             if (eventTasks[i].first == eventTasks[i].second->startMediaTime())
1547                 event = Event::create(eventNames().enterEvent, false, false);
1548             else
1549                 event = Event::create(eventNames().exitEvent, false, false);
1550
1551             event->setTarget(eventTasks[i].second);
1552             m_asyncEventQueue.enqueueEvent(event.release());
1553         }
1554     }
1555
1556     // 14 - Sort affected tracks in the same order as the text tracks appear in
1557     // the media element's list of text tracks, and remove duplicates.
1558     std::sort(affectedTracks.begin(), affectedTracks.end(), trackIndexCompare);
1559
1560     // 15 - For each text track in affected tracks, in the list order, queue a
1561     // task to fire a simple event named cuechange at the TextTrack object, and, ...
1562     for (size_t i = 0; i < affectedTracks.size(); ++i) {
1563         RefPtr<Event> event = Event::create(eventNames().cuechangeEvent, false, false);
1564         event->setTarget(affectedTracks[i]);
1565
1566         m_asyncEventQueue.enqueueEvent(event.release());
1567
1568         // ... if the text track has a corresponding track element, to then fire a
1569         // simple event named cuechange at the track element as well.
1570         if (is<LoadableTextTrack>(*affectedTracks[i])) {
1571             RefPtr<Event> event = Event::create(eventNames().cuechangeEvent, false, false);
1572             HTMLTrackElement* trackElement = downcast<LoadableTextTrack>(*affectedTracks[i]).trackElement();
1573             ASSERT(trackElement);
1574             event->setTarget(trackElement);
1575             
1576             m_asyncEventQueue.enqueueEvent(event.release());
1577         }
1578     }
1579
1580     // 16 - Set the text track cue active flag of all the cues in the current
1581     // cues, and unset the text track cue active flag of all the cues in the
1582     // other cues.
1583     for (size_t i = 0; i < currentCuesSize; ++i)
1584         currentCues[i].data()->setIsActive(true);
1585
1586     for (size_t i = 0; i < previousCuesSize; ++i)
1587         if (!currentCues.contains(previousCues[i]))
1588             previousCues[i].data()->setIsActive(false);
1589
1590     // Update the current active cues.
1591     m_currentlyActiveCues = currentCues;
1592
1593     if (activeSetChanged)
1594         updateTextTrackDisplay();
1595 }
1596
1597 bool HTMLMediaElement::textTracksAreReady() const
1598 {
1599     // 4.8.10.12.1 Text track model
1600     // ...
1601     // The text tracks of a media element are ready if all the text tracks whose mode was not 
1602     // in the disabled state when the element's resource selection algorithm last started now
1603     // have a text track readiness state of loaded or failed to load.
1604     for (unsigned i = 0; i < m_textTracksWhenResourceSelectionBegan.size(); ++i) {
1605         if (m_textTracksWhenResourceSelectionBegan[i]->readinessState() == TextTrack::Loading
1606             || m_textTracksWhenResourceSelectionBegan[i]->readinessState() == TextTrack::NotLoaded)
1607             return false;
1608     }
1609
1610     return true;
1611 }
1612
1613 void HTMLMediaElement::textTrackReadyStateChanged(TextTrack* track)
1614 {
1615     if (m_player && m_textTracksWhenResourceSelectionBegan.contains(track)) {
1616         if (track->readinessState() != TextTrack::Loading)
1617             setReadyState(m_player->readyState());
1618     } else {
1619         // The track readiness state might have changed as a result of the user
1620         // clicking the captions button. In this case, a check whether all the
1621         // resources have failed loading should be done in order to hide the CC button.
1622         if (hasMediaControls() && track->readinessState() == TextTrack::FailedToLoad)
1623             mediaControls()->refreshClosedCaptionsButtonVisibility();
1624     }
1625 }
1626
1627 void HTMLMediaElement::audioTrackEnabledChanged(AudioTrack* track)
1628 {
1629     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
1630         return;
1631     if (m_audioTracks && m_audioTracks->contains(track))
1632         m_audioTracks->scheduleChangeEvent();
1633 }
1634
1635 void HTMLMediaElement::textTrackModeChanged(TextTrack* track)
1636 {
1637     bool trackIsLoaded = true;
1638     if (track->trackType() == TextTrack::TrackElement) {
1639         trackIsLoaded = false;
1640         for (auto& trackElement : childrenOfType<HTMLTrackElement>(*this)) {
1641             if (trackElement.track() == track) {
1642                 if (trackElement.readyState() == HTMLTrackElement::LOADING || trackElement.readyState() == HTMLTrackElement::LOADED)
1643                     trackIsLoaded = true;
1644                 break;
1645             }
1646         }
1647     }
1648
1649     // If this is the first added track, create the list of text tracks.
1650     if (!m_textTracks)
1651         m_textTracks = TextTrackList::create(this, ActiveDOMObject::scriptExecutionContext());
1652     
1653     // Mark this track as "configured" so configureTextTracks won't change the mode again.
1654     track->setHasBeenConfigured(true);
1655     
1656     if (track->mode() != TextTrack::disabledKeyword() && trackIsLoaded)
1657         textTrackAddCues(track, track->cues());
1658
1659     configureTextTrackDisplay(AssumeTextTrackVisibilityChanged);
1660
1661     if (m_textTracks && m_textTracks->contains(track))
1662         m_textTracks->scheduleChangeEvent();
1663
1664 #if ENABLE(AVF_CAPTIONS)
1665     if (track->trackType() == TextTrack::TrackElement && m_player)
1666         m_player->notifyTrackModeChanged();
1667 #endif
1668 }
1669
1670 void HTMLMediaElement::videoTrackSelectedChanged(VideoTrack* track)
1671 {
1672     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
1673         return;
1674     if (m_videoTracks && m_videoTracks->contains(track))
1675         m_videoTracks->scheduleChangeEvent();
1676 }
1677
1678 void HTMLMediaElement::textTrackKindChanged(TextTrack* track)
1679 {
1680     if (track->kind() != TextTrack::captionsKeyword() && track->kind() != TextTrack::subtitlesKeyword() && track->mode() == TextTrack::showingKeyword())
1681         track->setMode(TextTrack::hiddenKeyword());
1682 }
1683
1684 void HTMLMediaElement::beginIgnoringTrackDisplayUpdateRequests()
1685 {
1686     ++m_ignoreTrackDisplayUpdate;
1687 }
1688
1689 void HTMLMediaElement::endIgnoringTrackDisplayUpdateRequests()
1690 {
1691     ASSERT(m_ignoreTrackDisplayUpdate);
1692     --m_ignoreTrackDisplayUpdate;
1693     if (!m_ignoreTrackDisplayUpdate && m_inActiveDocument)
1694         updateActiveTextTrackCues(currentMediaTime());
1695 }
1696
1697 void HTMLMediaElement::textTrackAddCues(TextTrack* track, const TextTrackCueList* cues) 
1698 {
1699     if (track->mode() == TextTrack::disabledKeyword())
1700         return;
1701
1702     TrackDisplayUpdateScope scope(this);
1703     for (size_t i = 0; i < cues->length(); ++i)
1704         textTrackAddCue(track, cues->item(i));
1705 }
1706
1707 void HTMLMediaElement::textTrackRemoveCues(TextTrack*, const TextTrackCueList* cues) 
1708 {
1709     TrackDisplayUpdateScope scope(this);
1710     for (size_t i = 0; i < cues->length(); ++i)
1711         textTrackRemoveCue(cues->item(i)->track(), cues->item(i));
1712 }
1713
1714 void HTMLMediaElement::textTrackAddCue(TextTrack* track, PassRefPtr<TextTrackCue> prpCue)
1715 {
1716     if (track->mode() == TextTrack::disabledKeyword())
1717         return;
1718
1719     RefPtr<TextTrackCue> cue = prpCue;
1720
1721     // Negative duration cues need be treated in the interval tree as
1722     // zero-length cues.
1723     MediaTime endTime = std::max(cue->startMediaTime(), cue->endMediaTime());
1724
1725     CueInterval interval = m_cueTree.createInterval(cue->startMediaTime(), endTime, cue.get());
1726     if (!m_cueTree.contains(interval))
1727         m_cueTree.add(interval);
1728     updateActiveTextTrackCues(currentMediaTime());
1729 }
1730
1731 void HTMLMediaElement::textTrackRemoveCue(TextTrack*, PassRefPtr<TextTrackCue> prpCue)
1732 {
1733     RefPtr<TextTrackCue> cue = prpCue;
1734     // Negative duration cues need to be treated in the interval tree as
1735     // zero-length cues.
1736     MediaTime endTime = std::max(cue->startMediaTime(), cue->endMediaTime());
1737
1738     CueInterval interval = m_cueTree.createInterval(cue->startMediaTime(), endTime, cue.get());
1739     m_cueTree.remove(interval);
1740
1741     // Since the cue will be removed from the media element and likely the
1742     // TextTrack might also be destructed, notifying the region of the cue
1743     // removal shouldn't be done.
1744     if (cue->isRenderable())
1745         toVTTCue(cue.get())->notifyRegionWhenRemovingDisplayTree(false);
1746
1747     size_t index = m_currentlyActiveCues.find(interval);
1748     if (index != notFound) {
1749         cue->setIsActive(false);
1750         m_currentlyActiveCues.remove(index);
1751     }
1752
1753     if (cue->isRenderable())
1754         toVTTCue(cue.get())->removeDisplayTree();
1755     updateActiveTextTrackCues(currentMediaTime());
1756
1757     if (cue->isRenderable())
1758         toVTTCue(cue.get())->notifyRegionWhenRemovingDisplayTree(true);
1759 }
1760
1761 #endif
1762
1763 bool HTMLMediaElement::isSafeToLoadURL(const URL& url, InvalidURLAction actionIfInvalid)
1764 {
1765     if (!url.isValid()) {
1766         LOG(Media, "HTMLMediaElement::isSafeToLoadURL(%p) - %s -> FALSE because url is invalid", this, urlForLoggingMedia(url).utf8().data());
1767         return false;
1768     }
1769
1770     Frame* frame = document().frame();
1771     if (!frame || !document().securityOrigin()->canDisplay(url)) {
1772         if (actionIfInvalid == Complain)
1773             FrameLoader::reportLocalLoadFailed(frame, url.stringCenterEllipsizedToLength());
1774         LOG(Media, "HTMLMediaElement::isSafeToLoadURL(%p) - %s -> FALSE rejected by SecurityOrigin", this, urlForLoggingMedia(url).utf8().data());
1775         return false;
1776     }
1777
1778     if (!document().contentSecurityPolicy()->allowMediaFromSource(url, isInUserAgentShadowTree())) {
1779         LOG(Media, "HTMLMediaElement::isSafeToLoadURL(%p) - %s -> rejected by Content Security Policy", this, urlForLoggingMedia(url).utf8().data());
1780         return false;
1781     }
1782
1783     return true;
1784 }
1785
1786 void HTMLMediaElement::startProgressEventTimer()
1787 {
1788     if (m_progressEventTimer.isActive())
1789         return;
1790
1791     m_previousProgressTime = monotonicallyIncreasingTime();
1792     // 350ms is not magic, it is in the spec!
1793     m_progressEventTimer.startRepeating(0.350);
1794 }
1795
1796 void HTMLMediaElement::waitForSourceChange()
1797 {
1798     LOG(Media, "HTMLMediaElement::waitForSourceChange(%p)", this);
1799
1800     stopPeriodicTimers();
1801     m_loadState = WaitingForSource;
1802
1803     // 6.17 - Waiting: Set the element's networkState attribute to the NETWORK_NO_SOURCE value
1804     m_networkState = NETWORK_NO_SOURCE;
1805
1806     // 6.18 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
1807     setShouldDelayLoadEvent(false);
1808
1809     updateDisplayState();
1810
1811     if (renderer())
1812         renderer()->updateFromElement();
1813 }
1814
1815 void HTMLMediaElement::noneSupported()
1816 {
1817     LOG(Media, "HTMLMediaElement::noneSupported(%p)", this);
1818
1819     stopPeriodicTimers();
1820     m_loadState = WaitingForSource;
1821     m_currentSourceNode = nullptr;
1822
1823     // 4.8.10.5 
1824     // 6 - Reaching this step indicates that the media resource failed to load or that the given 
1825     // URL could not be resolved. In one atomic operation, run the following steps:
1826
1827     // 6.1 - Set the error attribute to a new MediaError object whose code attribute is set to
1828     // MEDIA_ERR_SRC_NOT_SUPPORTED.
1829     m_error = MediaError::create(MediaError::MEDIA_ERR_SRC_NOT_SUPPORTED);
1830
1831     // 6.2 - Forget the media element's media-resource-specific text tracks.
1832     forgetResourceSpecificTracks();
1833
1834     // 6.3 - Set the element's networkState attribute to the NETWORK_NO_SOURCE value.
1835     m_networkState = NETWORK_NO_SOURCE;
1836
1837     // 7 - Queue a task to fire a simple event named error at the media element.
1838     scheduleEvent(eventNames().errorEvent);
1839
1840 #if ENABLE(MEDIA_SOURCE)
1841     closeMediaSource();
1842 #endif
1843
1844     // 8 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
1845     setShouldDelayLoadEvent(false);
1846
1847     // 9 - Abort these steps. Until the load() method is invoked or the src attribute is changed, 
1848     // the element won't attempt to load another resource.
1849
1850     updateDisplayState();
1851
1852     if (renderer())
1853         renderer()->updateFromElement();
1854 }
1855
1856 void HTMLMediaElement::mediaLoadingFailedFatally(MediaPlayer::NetworkState error)
1857 {
1858     LOG(Media, "HTMLMediaElement::mediaLoadingFailedFatally(%p) - error = %d", this, static_cast<int>(error));
1859
1860     // 1 - The user agent should cancel the fetching process.
1861     stopPeriodicTimers();
1862     m_loadState = WaitingForSource;
1863
1864     // 2 - Set the error attribute to a new MediaError object whose code attribute is 
1865     // set to MEDIA_ERR_NETWORK/MEDIA_ERR_DECODE.
1866     if (error == MediaPlayer::NetworkError)
1867         m_error = MediaError::create(MediaError::MEDIA_ERR_NETWORK);
1868     else if (error == MediaPlayer::DecodeError)
1869         m_error = MediaError::create(MediaError::MEDIA_ERR_DECODE);
1870     else
1871         ASSERT_NOT_REACHED();
1872
1873     // 3 - Queue a task to fire a simple event named error at the media element.
1874     scheduleEvent(eventNames().errorEvent);
1875
1876 #if ENABLE(MEDIA_SOURCE)
1877     closeMediaSource();
1878 #endif
1879
1880     // 4 - Set the element's networkState attribute to the NETWORK_EMPTY value and queue a
1881     // task to fire a simple event called emptied at the element.
1882     m_networkState = NETWORK_EMPTY;
1883     scheduleEvent(eventNames().emptiedEvent);
1884
1885     // 5 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
1886     setShouldDelayLoadEvent(false);
1887
1888     // 6 - Abort the overall resource selection algorithm.
1889     m_currentSourceNode = nullptr;
1890
1891 #if PLATFORM(COCOA)
1892     if (is<MediaDocument>(document()))
1893         downcast<MediaDocument>(document()).mediaElementSawUnsupportedTracks();
1894 #endif
1895 }
1896
1897 void HTMLMediaElement::cancelPendingEventsAndCallbacks()
1898 {
1899     LOG(Media, "HTMLMediaElement::cancelPendingEventsAndCallbacks(%p)", this);
1900     m_asyncEventQueue.cancelAllEvents();
1901
1902     for (auto& source : childrenOfType<HTMLSourceElement>(*this))
1903         source.cancelPendingErrorEvent();
1904 }
1905
1906 void HTMLMediaElement::mediaPlayerNetworkStateChanged(MediaPlayer*)
1907 {
1908     beginProcessingMediaPlayerCallback();
1909     setNetworkState(m_player->networkState());
1910     endProcessingMediaPlayerCallback();
1911 }
1912
1913 static void logMediaLoadRequest(Page* page, const String& mediaEngine, const String& errorMessage, bool succeeded)
1914 {
1915     if (!page)
1916         return;
1917
1918     DiagnosticLoggingClient& diagnosticLoggingClient = page->mainFrame().diagnosticLoggingClient();
1919     if (!succeeded) {
1920         diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::mediaLoadingFailedKey(), errorMessage, DiagnosticLoggingResultFail, ShouldSample::No);
1921         return;
1922     }
1923
1924     diagnosticLoggingClient.logDiagnosticMessage(DiagnosticLoggingKeys::mediaLoadedKey(), mediaEngine, ShouldSample::No);
1925
1926     if (!page->hasSeenAnyMediaEngine())
1927         diagnosticLoggingClient.logDiagnosticMessage(DiagnosticLoggingKeys::pageContainsAtLeastOneMediaEngineKey(), emptyString(), ShouldSample::No);
1928
1929     if (!page->hasSeenMediaEngine(mediaEngine))
1930         diagnosticLoggingClient.logDiagnosticMessage(DiagnosticLoggingKeys::pageContainsMediaEngineKey(), mediaEngine, ShouldSample::No);
1931
1932     page->sawMediaEngine(mediaEngine);
1933 }
1934
1935 static String stringForNetworkState(MediaPlayer::NetworkState state)
1936 {
1937     switch (state) {
1938     case MediaPlayer::Empty: return ASCIILiteral("Empty");
1939     case MediaPlayer::Idle: return ASCIILiteral("Idle");
1940     case MediaPlayer::Loading: return ASCIILiteral("Loading");
1941     case MediaPlayer::Loaded: return ASCIILiteral("Loaded");
1942     case MediaPlayer::FormatError: return ASCIILiteral("FormatError");
1943     case MediaPlayer::NetworkError: return ASCIILiteral("NetworkError");
1944     case MediaPlayer::DecodeError: return ASCIILiteral("DecodeError");
1945     default: return emptyString();
1946     }
1947 }
1948
1949 void HTMLMediaElement::mediaLoadingFailed(MediaPlayer::NetworkState error)
1950 {
1951     stopPeriodicTimers();
1952     
1953     // If we failed while trying to load a <source> element, the movie was never parsed, and there are more
1954     // <source> children, schedule the next one
1955     if (m_readyState < HAVE_METADATA && m_loadState == LoadingFromSourceElement) {
1956         
1957         // resource selection algorithm
1958         // Step 9.Otherwise.9 - Failed with elements: Queue a task, using the DOM manipulation task source, to fire a simple event named error at the candidate element.
1959         if (m_currentSourceNode)
1960             m_currentSourceNode->scheduleErrorEvent();
1961         else
1962             LOG(Media, "HTMLMediaElement::setNetworkState(%p) - error event not sent, <source> was removed", this);
1963         
1964         // 9.Otherwise.10 - Asynchronously await a stable state. The synchronous section consists of all the remaining steps of this algorithm until the algorithm says the synchronous section has ended.
1965         
1966         // 9.Otherwise.11 - Forget the media element's media-resource-specific tracks.
1967         forgetResourceSpecificTracks();
1968
1969         if (havePotentialSourceChild()) {
1970             LOG(Media, "HTMLMediaElement::setNetworkState(%p) - scheduling next <source>", this);
1971             scheduleNextSourceChild();
1972         } else {
1973             LOG(Media, "HTMLMediaElement::setNetworkState(%p) - no more <source> elements, waiting", this);
1974             waitForSourceChange();
1975         }
1976         
1977         return;
1978     }
1979     
1980     if ((error == MediaPlayer::NetworkError && m_readyState >= HAVE_METADATA) || error == MediaPlayer::DecodeError)
1981         mediaLoadingFailedFatally(error);
1982     else if ((error == MediaPlayer::FormatError || error == MediaPlayer::NetworkError) && m_loadState == LoadingFromSrcAttr)
1983         noneSupported();
1984     
1985     updateDisplayState();
1986     if (hasMediaControls()) {
1987         mediaControls()->reset();
1988         mediaControls()->reportedError();
1989     }
1990
1991     logMediaLoadRequest(document().page(), String(), stringForNetworkState(error), false);
1992 }
1993
1994 void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)
1995 {
1996     LOG(Media, "HTMLMediaElement::setNetworkState(%p) - new state = %d, current state = %d", this, static_cast<int>(state), static_cast<int>(m_networkState));
1997
1998     if (state == MediaPlayer::Empty) {
1999         // Just update the cached state and leave, we can't do anything.
2000         m_networkState = NETWORK_EMPTY;
2001         return;
2002     }
2003
2004     if (state == MediaPlayer::FormatError || state == MediaPlayer::NetworkError || state == MediaPlayer::DecodeError) {
2005         mediaLoadingFailed(state);
2006         return;
2007     }
2008
2009     if (state == MediaPlayer::Idle) {
2010         if (m_networkState > NETWORK_IDLE) {
2011             changeNetworkStateFromLoadingToIdle();
2012             setShouldDelayLoadEvent(false);
2013         } else {
2014             m_networkState = NETWORK_IDLE;
2015         }
2016     }
2017
2018     if (state == MediaPlayer::Loading) {
2019         if (m_networkState < NETWORK_LOADING || m_networkState == NETWORK_NO_SOURCE)
2020             startProgressEventTimer();
2021         m_networkState = NETWORK_LOADING;
2022     }
2023
2024     if (state == MediaPlayer::Loaded) {
2025         if (m_networkState != NETWORK_IDLE)
2026             changeNetworkStateFromLoadingToIdle();
2027         m_completelyLoaded = true;
2028     }
2029
2030     if (hasMediaControls())
2031         mediaControls()->updateStatusDisplay();
2032 }
2033
2034 void HTMLMediaElement::changeNetworkStateFromLoadingToIdle()
2035 {
2036     m_progressEventTimer.stop();
2037     if (hasMediaControls() && m_player->didLoadingProgress())
2038         mediaControls()->bufferingProgressed();
2039
2040     // Schedule one last progress event so we guarantee that at least one is fired
2041     // for files that load very quickly.
2042     scheduleEvent(eventNames().progressEvent);
2043     scheduleEvent(eventNames().suspendEvent);
2044     m_networkState = NETWORK_IDLE;
2045 }
2046
2047 void HTMLMediaElement::mediaPlayerReadyStateChanged(MediaPlayer*)
2048 {
2049     beginProcessingMediaPlayerCallback();
2050
2051     setReadyState(m_player->readyState());
2052
2053     endProcessingMediaPlayerCallback();
2054 }
2055
2056 void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state)
2057 {
2058     LOG(Media, "HTMLMediaElement::setReadyState(%p) - new state = %d, current state = %d,", this, static_cast<int>(state), static_cast<int>(m_readyState));
2059
2060     // Set "wasPotentiallyPlaying" BEFORE updating m_readyState, potentiallyPlaying() uses it
2061     bool wasPotentiallyPlaying = potentiallyPlaying();
2062
2063     ReadyState oldState = m_readyState;
2064     ReadyState newState = static_cast<ReadyState>(state);
2065
2066 #if ENABLE(VIDEO_TRACK)
2067     bool tracksAreReady = !RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled() || textTracksAreReady();
2068
2069     if (newState == oldState && m_tracksAreReady == tracksAreReady)
2070         return;
2071
2072     m_tracksAreReady = tracksAreReady;
2073 #else
2074     if (newState == oldState)
2075         return;
2076     bool tracksAreReady = true;
2077 #endif
2078     
2079     if (tracksAreReady)
2080         m_readyState = newState;
2081     else {
2082         // If a media file has text tracks the readyState may not progress beyond HAVE_FUTURE_DATA until
2083         // the text tracks are ready, regardless of the state of the media file.
2084         if (newState <= HAVE_METADATA)
2085             m_readyState = newState;
2086         else
2087             m_readyState = HAVE_CURRENT_DATA;
2088     }
2089     
2090     if (oldState > m_readyStateMaximum)
2091         m_readyStateMaximum = oldState;
2092
2093     if (m_networkState == NETWORK_EMPTY)
2094         return;
2095
2096     if (m_seeking) {
2097         // 4.8.10.9, step 11
2098         if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA)
2099             scheduleEvent(eventNames().waitingEvent);
2100
2101         // 4.8.10.10 step 14 & 15.
2102         if (!m_player->seeking() && m_readyState >= HAVE_CURRENT_DATA)
2103             finishSeek();
2104     } else {
2105         if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA) {
2106             // 4.8.10.8
2107             invalidateCachedTime();
2108             scheduleTimeupdateEvent(false);
2109             scheduleEvent(eventNames().waitingEvent);
2110         }
2111     }
2112
2113     if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) {
2114         prepareMediaFragmentURI();
2115         scheduleEvent(eventNames().durationchangeEvent);
2116         scheduleEvent(eventNames().loadedmetadataEvent);
2117 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
2118         if (hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent))
2119             enqueuePlaybackTargetAvailabilityChangedEvent();
2120 #endif
2121         m_initiallyMuted = m_volume < 0.05 || muted();
2122
2123         if (hasMediaControls())
2124             mediaControls()->loadedMetadata();
2125         if (renderer())
2126             renderer()->updateFromElement();
2127
2128         if (is<MediaDocument>(document()))
2129             downcast<MediaDocument>(document()).mediaElementNaturalSizeChanged(expandedIntSize(m_player->naturalSize()));
2130
2131         logMediaLoadRequest(document().page(), m_player->engineDescription(), String(), true);
2132
2133 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
2134         updateMediaState(UpdateMediaState::Asynchronously);
2135 #endif
2136     }
2137
2138     bool shouldUpdateDisplayState = false;
2139
2140     if (m_readyState >= HAVE_CURRENT_DATA && oldState < HAVE_CURRENT_DATA && !m_haveFiredLoadedData) {
2141         m_haveFiredLoadedData = true;
2142         shouldUpdateDisplayState = true;
2143         scheduleEvent(eventNames().loadeddataEvent);
2144         setShouldDelayLoadEvent(false);
2145         applyMediaFragmentURI();
2146     }
2147
2148     bool isPotentiallyPlaying = potentiallyPlaying();
2149     if (m_readyState == HAVE_FUTURE_DATA && oldState <= HAVE_CURRENT_DATA && tracksAreReady) {
2150         scheduleEvent(eventNames().canplayEvent);
2151         if (isPotentiallyPlaying)
2152             scheduleEvent(eventNames().playingEvent);
2153         shouldUpdateDisplayState = true;
2154     }
2155
2156     if (m_readyState == HAVE_ENOUGH_DATA && oldState < HAVE_ENOUGH_DATA && tracksAreReady) {
2157         if (oldState <= HAVE_CURRENT_DATA)
2158             scheduleEvent(eventNames().canplayEvent);
2159
2160         scheduleEvent(eventNames().canplaythroughEvent);
2161
2162         if (isPotentiallyPlaying && oldState <= HAVE_CURRENT_DATA)
2163             scheduleEvent(eventNames().playingEvent);
2164
2165         if (m_autoplaying && m_paused && autoplay() && !document().isSandboxed(SandboxAutomaticFeatures) && m_mediaSession->playbackPermitted(*this)) {
2166             m_paused = false;
2167             invalidateCachedTime();
2168             scheduleEvent(eventNames().playEvent);
2169             scheduleEvent(eventNames().playingEvent);
2170         }
2171
2172         shouldUpdateDisplayState = true;
2173     }
2174
2175     if (shouldUpdateDisplayState) {
2176         updateDisplayState();
2177         if (hasMediaControls()) {
2178             mediaControls()->refreshClosedCaptionsButtonVisibility();
2179             mediaControls()->updateStatusDisplay();
2180         }
2181     }
2182
2183     updatePlayState();
2184     updateMediaController();
2185 #if ENABLE(VIDEO_TRACK)
2186     if (RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
2187         updateActiveTextTrackCues(currentMediaTime());
2188 #endif
2189 }
2190
2191 #if ENABLE(ENCRYPTED_MEDIA)
2192 void HTMLMediaElement::mediaPlayerKeyAdded(MediaPlayer*, const String& keySystem, const String& sessionId)
2193 {
2194     MediaKeyEventInit initializer;
2195     initializer.keySystem = keySystem;
2196     initializer.sessionId = sessionId;
2197     initializer.bubbles = false;
2198     initializer.cancelable = false;
2199
2200     RefPtr<Event> event = MediaKeyEvent::create(eventNames().webkitkeyaddedEvent, initializer);
2201     event->setTarget(this);
2202     m_asyncEventQueue.enqueueEvent(event.release());
2203 }
2204
2205 void HTMLMediaElement::mediaPlayerKeyError(MediaPlayer*, const String& keySystem, const String& sessionId, MediaPlayerClient::MediaKeyErrorCode errorCode, unsigned short systemCode)
2206 {
2207     MediaKeyError::Code mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN;
2208     switch (errorCode) {
2209     case MediaPlayerClient::UnknownError:
2210         mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_UNKNOWN;
2211         break;
2212     case MediaPlayerClient::ClientError:
2213         mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
2214         break;
2215     case MediaPlayerClient::ServiceError:
2216         mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_SERVICE;
2217         break;
2218     case MediaPlayerClient::OutputError:
2219         mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_OUTPUT;
2220         break;
2221     case MediaPlayerClient::HardwareChangeError:
2222         mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_HARDWARECHANGE;
2223         break;
2224     case MediaPlayerClient::DomainError:
2225         mediaKeyErrorCode = MediaKeyError::MEDIA_KEYERR_DOMAIN;
2226         break;
2227     }
2228
2229     MediaKeyEventInit initializer;
2230     initializer.keySystem = keySystem;
2231     initializer.sessionId = sessionId;
2232     initializer.errorCode = MediaKeyError::create(mediaKeyErrorCode);
2233     initializer.systemCode = systemCode;
2234     initializer.bubbles = false;
2235     initializer.cancelable = false;
2236
2237     RefPtr<Event> event = MediaKeyEvent::create(eventNames().webkitkeyerrorEvent, initializer);
2238     event->setTarget(this);
2239     m_asyncEventQueue.enqueueEvent(event.release());
2240 }
2241
2242 void HTMLMediaElement::mediaPlayerKeyMessage(MediaPlayer*, const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength, const URL& defaultURL)
2243 {
2244     MediaKeyEventInit initializer;
2245     initializer.keySystem = keySystem;
2246     initializer.sessionId = sessionId;
2247     initializer.message = Uint8Array::create(message, messageLength);
2248     initializer.defaultURL = defaultURL; 
2249     initializer.bubbles = false;
2250     initializer.cancelable = false;
2251
2252     RefPtr<Event> event = MediaKeyEvent::create(eventNames().webkitkeymessageEvent, initializer);
2253     event->setTarget(this);
2254     m_asyncEventQueue.enqueueEvent(event.release());
2255 }
2256
2257 bool HTMLMediaElement::mediaPlayerKeyNeeded(MediaPlayer*, const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength)
2258 {
2259     if (!hasEventListeners(eventNames().webkitneedkeyEvent)) {
2260         m_error = MediaError::create(MediaError::MEDIA_ERR_ENCRYPTED);
2261         scheduleEvent(eventNames().errorEvent);
2262         return false;
2263     }
2264
2265     MediaKeyEventInit initializer;
2266     initializer.keySystem = keySystem;
2267     initializer.sessionId = sessionId;
2268     initializer.initData = Uint8Array::create(initData, initDataLength);
2269     initializer.bubbles = false;
2270     initializer.cancelable = false;
2271
2272     RefPtr<Event> event = MediaKeyEvent::create(eventNames().webkitneedkeyEvent, initializer);
2273     event->setTarget(this);
2274     m_asyncEventQueue.enqueueEvent(event.release());
2275     return true;
2276 }
2277 #endif
2278
2279 #if ENABLE(ENCRYPTED_MEDIA_V2)
2280 RefPtr<ArrayBuffer> HTMLMediaElement::mediaPlayerCachedKeyForKeyId(const String& keyId) const
2281 {
2282     return m_mediaKeys ? m_mediaKeys->cachedKeyForKeyId(keyId) : nullptr;
2283 }
2284
2285 bool HTMLMediaElement::mediaPlayerKeyNeeded(MediaPlayer*, Uint8Array* initData)
2286 {
2287     if (!hasEventListeners("webkitneedkey")) {
2288         m_error = MediaError::create(MediaError::MEDIA_ERR_ENCRYPTED);
2289         scheduleEvent(eventNames().errorEvent);
2290         return false;
2291     }
2292
2293     MediaKeyNeededEventInit initializer;
2294     initializer.initData = initData;
2295     initializer.bubbles = false;
2296     initializer.cancelable = false;
2297
2298     RefPtr<Event> event = MediaKeyNeededEvent::create(eventNames().webkitneedkeyEvent, initializer);
2299     event->setTarget(this);
2300     m_asyncEventQueue.enqueueEvent(event.release());
2301
2302     return true;
2303 }
2304
2305 String HTMLMediaElement::mediaPlayerMediaKeysStorageDirectory() const
2306 {
2307     Settings* settings = document().settings();
2308     if (!settings)
2309         return emptyString();
2310
2311     String storageDirectory = settings->mediaKeysStorageDirectory();
2312     if (storageDirectory.isEmpty())
2313         return emptyString();
2314
2315     SecurityOrigin* origin = document().securityOrigin();
2316     if (!origin)
2317         return emptyString();
2318
2319     return pathByAppendingComponent(storageDirectory, origin->databaseIdentifier());
2320 }
2321
2322 void HTMLMediaElement::setMediaKeys(MediaKeys* mediaKeys)
2323 {
2324     if (m_mediaKeys == mediaKeys)
2325         return;
2326
2327     if (m_mediaKeys)
2328         m_mediaKeys->setMediaElement(0);
2329     m_mediaKeys = mediaKeys;
2330     if (m_mediaKeys)
2331         m_mediaKeys->setMediaElement(this);
2332 }
2333
2334 void HTMLMediaElement::keyAdded()
2335 {
2336     if (m_player)
2337         m_player->keyAdded();
2338 }
2339 #endif
2340
2341 #if ENABLE(MEDIA_STREAM)
2342 String HTMLMediaElement::mediaPlayerMediaDeviceIdentifierStorageDirectory() const
2343 {
2344     Settings* settings = document().settings();
2345     if (!settings)
2346         return emptyString();
2347
2348     String storageDirectory = settings->mediaDeviceIdentifierStorageDirectory();
2349     if (storageDirectory.isEmpty())
2350         return emptyString();
2351
2352     SecurityOrigin* origin = document().securityOrigin();
2353     if (!origin)
2354         return emptyString();
2355
2356     return pathByAppendingComponent(storageDirectory, origin->databaseIdentifier());
2357 }
2358 #endif
2359
2360 void HTMLMediaElement::progressEventTimerFired()
2361 {
2362     ASSERT(m_player);
2363     if (m_networkState != NETWORK_LOADING)
2364         return;
2365
2366     double time = monotonicallyIncreasingTime();
2367     double timedelta = time - m_previousProgressTime;
2368
2369     if (m_player->didLoadingProgress()) {
2370         scheduleEvent(eventNames().progressEvent);
2371         m_previousProgressTime = time;
2372         m_sentStalledEvent = false;
2373         if (renderer())
2374             renderer()->updateFromElement();
2375         if (hasMediaControls())
2376             mediaControls()->bufferingProgressed();
2377     } else if (timedelta > 3.0 && !m_sentStalledEvent) {
2378         scheduleEvent(eventNames().stalledEvent);
2379         m_sentStalledEvent = true;
2380         setShouldDelayLoadEvent(false);
2381     }
2382 }
2383
2384 void HTMLMediaElement::rewind(double timeDelta)
2385 {
2386     LOG(Media, "HTMLMediaElement::rewind(%p) - %f", this, timeDelta);
2387     setCurrentTime(std::max(currentMediaTime() - MediaTime::createWithDouble(timeDelta), minTimeSeekable()));
2388 }
2389
2390 void HTMLMediaElement::returnToRealtime()
2391 {
2392     LOG(Media, "HTMLMediaElement::returnToRealtime(%p)", this);
2393     setCurrentTime(maxTimeSeekable());
2394 }
2395
2396 void HTMLMediaElement::addPlayedRange(const MediaTime& start, const MediaTime& end)
2397 {
2398     LOG(Media, "HTMLMediaElement::addPlayedRange(%p) - [%s, %s]", this, toString(start).utf8().data(), toString(end).utf8().data());
2399     if (!m_playedTimeRanges)
2400         m_playedTimeRanges = TimeRanges::create();
2401     m_playedTimeRanges->ranges().add(start, end);
2402 }  
2403
2404 bool HTMLMediaElement::supportsScanning() const
2405 {
2406     return m_player ? m_player->supportsScanning() : false;
2407 }
2408
2409 void HTMLMediaElement::prepareToPlay()
2410 {
2411     LOG(Media, "HTMLMediaElement::prepareToPlay(%p)", this);
2412     if (m_havePreparedToPlay)
2413         return;
2414     m_havePreparedToPlay = true;
2415     m_player->prepareToPlay();
2416 }
2417
2418 void HTMLMediaElement::fastSeek(double time)
2419 {
2420     fastSeek(MediaTime::createWithDouble(time));
2421 }
2422
2423 void HTMLMediaElement::fastSeek(const MediaTime& time)
2424 {
2425     LOG(Media, "HTMLMediaElement::fastSeek(%p) - %s", this, toString(time).utf8().data());
2426     // 4.7.10.9 Seeking
2427     // 9. If the approximate-for-speed flag is set, adjust the new playback position to a value that will
2428     // allow for playback to resume promptly. If new playback position before this step is before current
2429     // playback position, then the adjusted new playback position must also be before the current playback
2430     // position. Similarly, if the new playback position before this step is after current playback position,
2431     // then the adjusted new playback position must also be after the current playback position.
2432     refreshCachedTime();
2433     MediaTime delta = time - currentMediaTime();
2434     MediaTime negativeTolerance = delta >= MediaTime::zeroTime() ? delta : MediaTime::positiveInfiniteTime();
2435     MediaTime positiveTolerance = delta < MediaTime::zeroTime() ? -delta : MediaTime::positiveInfiniteTime();
2436
2437     seekWithTolerance(time, negativeTolerance, positiveTolerance, true);
2438 }
2439
2440 void HTMLMediaElement::seek(const MediaTime& time)
2441 {
2442     LOG(Media, "HTMLMediaElement::seek(%p) - %s", this, toString(time).utf8().data());
2443     seekWithTolerance(time, MediaTime::zeroTime(), MediaTime::zeroTime(), true);
2444 }
2445
2446 void HTMLMediaElement::seekInternal(const MediaTime& time)
2447 {
2448     LOG(Media, "HTMLMediaElement::seekInternal(%p) - %s", this, toString(time).utf8().data());
2449     seekWithTolerance(time, MediaTime::zeroTime(), MediaTime::zeroTime(), false);
2450 }
2451
2452 void HTMLMediaElement::seekWithTolerance(const MediaTime& inTime, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance, bool fromDOM)
2453 {
2454     // 4.8.10.9 Seeking
2455     MediaTime time = inTime;
2456
2457     // 1 - Set the media element's show poster flag to false.
2458     setDisplayMode(Video);
2459
2460     // 2 - If the media element's readyState is HAVE_NOTHING, abort these steps.
2461     if (m_readyState == HAVE_NOTHING || !m_player)
2462         return;
2463
2464     // If the media engine has been told to postpone loading data, let it go ahead now.
2465     if (m_preload < MediaPlayer::Auto && m_readyState < HAVE_FUTURE_DATA)
2466         prepareToPlay();
2467
2468     // Get the current time before setting m_seeking, m_lastSeekTime is returned once it is set.
2469     refreshCachedTime();
2470     MediaTime now = currentMediaTime();
2471
2472     // 3 - If the element's seeking IDL attribute is true, then another instance of this algorithm is
2473     // already running. Abort that other instance of the algorithm without waiting for the step that
2474     // it is running to complete.
2475     if (m_seekTaskQueue.hasPendingTasks()) {
2476         LOG(Media, "HTMLMediaElement::seekWithTolerance(%p) - cancelling pending seeks", this);
2477         m_seekTaskQueue.cancelAllTasks();
2478         if (m_pendingSeek) {
2479             now = m_pendingSeek->now;
2480             m_pendingSeek = nullptr;
2481         }
2482         m_pendingSeekType = NoSeek;
2483     }
2484
2485     // 4 - Set the seeking IDL attribute to true.
2486     // The flag will be cleared when the engine tells us the time has actually changed.
2487     m_seeking = true;
2488     if (m_playing) {
2489         if (m_lastSeekTime < now)
2490             addPlayedRange(m_lastSeekTime, now);
2491     }
2492     m_lastSeekTime = time;
2493
2494     // 5 - If the seek was in response to a DOM method call or setting of an IDL attribute, then continue
2495     // the script. The remainder of these steps must be run asynchronously.
2496     m_pendingSeek = std::make_unique<PendingSeek>(now, time, negativeTolerance, positiveTolerance);
2497     if (fromDOM) {
2498         LOG(Media, "HTMLMediaElement::seekWithTolerance(%p) - enqueuing seek from %s to %s", this, toString(now).utf8().data(), toString(time).utf8().data());
2499         m_seekTaskQueue.enqueueTask(std::bind(&HTMLMediaElement::seekTask, this));
2500     } else
2501         seekTask();
2502 }
2503
2504 void HTMLMediaElement::seekTask()
2505 {
2506     LOG(Media, "HTMLMediaElement::seekTask(%p)", this);
2507
2508     if (!m_player) {
2509         clearSeeking();
2510         return;
2511     }
2512
2513     ASSERT(m_pendingSeek);
2514     MediaTime now = m_pendingSeek->now;
2515     MediaTime time = m_pendingSeek->targetTime;
2516     MediaTime negativeTolerance = m_pendingSeek->negativeTolerance;
2517     MediaTime positiveTolerance = m_pendingSeek->positiveTolerance;
2518     m_pendingSeek = nullptr;
2519
2520     // 6 - If the new playback position is later than the end of the media resource, then let it be the end 
2521     // of the media resource instead.
2522     time = std::min(time, durationMediaTime());
2523
2524     // 7 - If the new playback position is less than the earliest possible position, let it be that position instead.
2525     MediaTime earliestTime = m_player->startTime();
2526     time = std::max(time, earliestTime);
2527
2528     // Ask the media engine for the time value in the movie's time scale before comparing with current time. This
2529     // is necessary because if the seek time is not equal to currentTime but the delta is less than the movie's
2530     // time scale, we will ask the media engine to "seek" to the current movie time, which may be a noop and
2531     // not generate a timechanged callback. This means m_seeking will never be cleared and we will never 
2532     // fire a 'seeked' event.
2533 #if !LOG_DISABLED
2534     MediaTime mediaTime = m_player->mediaTimeForTimeValue(time);
2535     if (time != mediaTime)
2536         LOG(Media, "HTMLMediaElement::seekTask(%p) - %s - media timeline equivalent is %s", this, toString(time).utf8().data(), toString(mediaTime).utf8().data());
2537 #endif
2538     time = m_player->mediaTimeForTimeValue(time);
2539
2540     // 8 - If the (possibly now changed) new playback position is not in one of the ranges given in the
2541     // seekable attribute, then let it be the position in one of the ranges given in the seekable attribute 
2542     // that is the nearest to the new playback position. ... If there are no ranges given in the seekable
2543     // attribute then set the seeking IDL attribute to false and abort these steps.
2544     RefPtr<TimeRanges> seekableRanges = seekable();
2545     bool noSeekRequired = !seekableRanges->length();
2546
2547     // Short circuit seeking to the current time by just firing the events if no seek is required.
2548     // Don't skip calling the media engine if 1) we are in poster mode (because a seek should always cancel
2549     // poster display), or 2) if there is a pending fast seek, or 3) if this seek is not an exact seek
2550     SeekType thisSeekType = (negativeTolerance == MediaTime::zeroTime() && positiveTolerance == MediaTime::zeroTime()) ? Precise : Fast;
2551     if (!noSeekRequired && time == now && thisSeekType == Precise && m_pendingSeekType != Fast && displayMode() != Poster)
2552         noSeekRequired = true;
2553
2554 #if ENABLE(MEDIA_SOURCE)
2555     // Always notify the media engine of a seek if the source is not closed. This ensures that the source is
2556     // always in a flushed state when the 'seeking' event fires.
2557     if (m_mediaSource && !m_mediaSource->isClosed())
2558         noSeekRequired = false;
2559 #endif
2560
2561     if (noSeekRequired) {
2562         LOG(Media, "HTMLMediaElement::seekTask(%p) - seek to %s ignored", this, toString(time).utf8().data());
2563         if (time == now) {
2564             scheduleEvent(eventNames().seekingEvent);
2565             scheduleTimeupdateEvent(false);
2566             scheduleEvent(eventNames().seekedEvent);
2567         }
2568         clearSeeking();
2569         return;
2570     }
2571     time = seekableRanges->ranges().nearest(time);
2572
2573     m_sentEndEvent = false;
2574     m_lastSeekTime = time;
2575     m_pendingSeekType = thisSeekType;
2576     m_seeking = true;
2577
2578     // 10 - Queue a task to fire a simple event named seeking at the element.
2579     scheduleEvent(eventNames().seekingEvent);
2580
2581     // 11 - Set the current playback position to the given new playback position
2582     m_player->seekWithTolerance(time, negativeTolerance, positiveTolerance);
2583
2584     // 12 - Wait until the user agent has established whether or not the media data for the new playback
2585     // position is available, and, if it is, until it has decoded enough data to play back that position.
2586     // 13 - Await a stable state. The synchronous section consists of all the remaining steps of this algorithm.
2587 }
2588
2589 void HTMLMediaElement::clearSeeking()
2590 {
2591     m_seeking = false;
2592     m_pendingSeekType = NoSeek;
2593     invalidateCachedTime();
2594 }
2595
2596 void HTMLMediaElement::finishSeek()
2597 {
2598     // 4.8.10.9 Seeking
2599     // 14 - Set the seeking IDL attribute to false.
2600     clearSeeking();
2601
2602     LOG(Media, "HTMLMediaElement::finishSeek(%p) - current time = %s", this, toString(currentMediaTime()).utf8().data());
2603
2604     // 15 - Run the time maches on steps.
2605     // Handled by mediaPlayerTimeChanged().
2606
2607     // 16 - Queue a task to fire a simple event named timeupdate at the element.
2608     scheduleEvent(eventNames().timeupdateEvent);
2609
2610     // 17 - Queue a task to fire a simple event named seeked at the element.
2611     scheduleEvent(eventNames().seekedEvent);
2612
2613 #if ENABLE(MEDIA_SOURCE)
2614     if (m_mediaSource)
2615         m_mediaSource->monitorSourceBuffers();
2616 #endif
2617 }
2618
2619 HTMLMediaElement::ReadyState HTMLMediaElement::readyState() const
2620 {
2621     return m_readyState;
2622 }
2623
2624 MediaPlayer::MovieLoadType HTMLMediaElement::movieLoadType() const
2625 {
2626     return m_player ? m_player->movieLoadType() : MediaPlayer::Unknown;
2627 }
2628
2629 bool HTMLMediaElement::hasAudio() const
2630 {
2631     return m_player ? m_player->hasAudio() : false;
2632 }
2633
2634 bool HTMLMediaElement::seeking() const
2635 {
2636     return m_seeking;
2637 }
2638
2639 void HTMLMediaElement::refreshCachedTime() const
2640 {
2641     if (!m_player)
2642         return;
2643
2644     m_cachedTime = m_player->currentTime();
2645     if (!m_cachedTime) {
2646         // Do not use m_cachedTime until the media engine returns a non-zero value because we can't 
2647         // estimate current time until playback actually begins. 
2648         invalidateCachedTime(); 
2649         return; 
2650     } 
2651
2652     m_clockTimeAtLastCachedTimeUpdate = monotonicallyIncreasingTime();
2653 }
2654
2655 void HTMLMediaElement::invalidateCachedTime() const
2656 {
2657     if (!m_player || !m_player->maximumDurationToCacheMediaTime())
2658         return;
2659
2660 #if !LOG_DISABLED
2661     if (m_cachedTime.isValid())
2662         LOG(Media, "HTMLMediaElement::invalidateCachedTime(%p)", this);
2663 #endif
2664
2665     // Don't try to cache movie time when playback first starts as the time reported by the engine
2666     // sometimes fluctuates for a short amount of time, so the cached time will be off if we take it
2667     // too early.
2668     static const double minimumTimePlayingBeforeCacheSnapshot = 0.5;
2669
2670     m_minimumClockTimeToUpdateCachedTime = monotonicallyIncreasingTime() + minimumTimePlayingBeforeCacheSnapshot;
2671     m_cachedTime = MediaTime::invalidTime();
2672 }
2673
2674 // playback state
2675 double HTMLMediaElement::currentTime() const
2676 {
2677     return currentMediaTime().toDouble();
2678 }
2679
2680 MediaTime HTMLMediaElement::currentMediaTime() const
2681 {
2682 #if LOG_CACHED_TIME_WARNINGS
2683     static const MediaTime minCachedDeltaForWarning = MediaTime::create(1, 100);
2684 #endif
2685
2686     if (!m_player)
2687         return MediaTime::zeroTime();
2688
2689     if (m_seeking) {
2690         LOG(Media, "HTMLMediaElement::currentTime(%p) - seeking, returning %s", this, toString(m_lastSeekTime).utf8().data());
2691         return m_lastSeekTime;
2692     }
2693
2694     if (m_cachedTime.isValid() && m_paused) {
2695 #if LOG_CACHED_TIME_WARNINGS
2696         MediaTime delta = m_cachedTime - m_player->currentTime();
2697         if (delta > minCachedDeltaForWarning)
2698             LOG(Media, "HTMLMediaElement::currentTime(%p) - WARNING, cached time is %s seconds off of media time when paused", this, toString(delta).utf8().data());
2699 #endif
2700         return m_cachedTime;
2701     }
2702
2703     // Is it too soon use a cached time?
2704     double now = monotonicallyIncreasingTime();
2705     double maximumDurationToCacheMediaTime = m_player->maximumDurationToCacheMediaTime();
2706
2707     if (maximumDurationToCacheMediaTime && m_cachedTime.isValid() && !m_paused && now > m_minimumClockTimeToUpdateCachedTime) {
2708         double clockDelta = now - m_clockTimeAtLastCachedTimeUpdate;
2709
2710         // Not too soon, use the cached time only if it hasn't expired.
2711         if (clockDelta < maximumDurationToCacheMediaTime) {
2712             MediaTime adjustedCacheTime = m_cachedTime + MediaTime::createWithDouble(effectivePlaybackRate() * clockDelta);
2713
2714 #if LOG_CACHED_TIME_WARNINGS
2715             MediaTime delta = adjustedCacheTime - m_player->currentTime();
2716             if (delta > minCachedDeltaForWarning)
2717                 LOG(Media, "HTMLMediaElement::currentTime(%p) - WARNING, cached time is %f seconds off of media time when playing", this, delta);
2718 #endif
2719             return adjustedCacheTime;
2720         }
2721     }
2722
2723 #if LOG_CACHED_TIME_WARNINGS
2724     if (maximumDurationToCacheMediaTime && now > m_minimumClockTimeToUpdateCachedTime && m_cachedTime != MediaPlayer::invalidTime()) {
2725         double clockDelta = now - m_clockTimeAtLastCachedTimeUpdate;
2726         MediaTime delta = m_cachedTime + MediaTime::createWithDouble(effectivePlaybackRate() * clockDelta) - m_player->currentTime();
2727         LOG(Media, "HTMLMediaElement::currentTime(%p) - cached time was %s seconds off of media time when it expired", this, toString(delta).utf8().data());
2728     }
2729 #endif
2730
2731     refreshCachedTime();
2732
2733     if (m_cachedTime.isInvalid())
2734         return MediaTime::zeroTime();
2735     
2736     return m_cachedTime;
2737 }
2738
2739 void HTMLMediaElement::setCurrentTime(double time)
2740 {
2741     setCurrentTime(MediaTime::createWithDouble(time));
2742 }
2743
2744 void HTMLMediaElement::setCurrentTime(const MediaTime& time)
2745 {
2746     if (m_mediaController)
2747         return;
2748
2749     seekInternal(time);
2750 }
2751
2752 void HTMLMediaElement::setCurrentTime(double time, ExceptionCode& ec)
2753 {
2754     // On setting, if the media element has a current media controller, then the user agent must
2755     // throw an InvalidStateError exception
2756     if (m_mediaController) {
2757         ec = INVALID_STATE_ERR;
2758         return;
2759     }
2760
2761     seek(MediaTime::createWithDouble(time));
2762 }
2763
2764 double HTMLMediaElement::duration() const
2765 {
2766     return durationMediaTime().toDouble();
2767 }
2768
2769 MediaTime HTMLMediaElement::durationMediaTime() const
2770 {
2771     if (m_player && m_readyState >= HAVE_METADATA)
2772         return m_player->duration();
2773
2774     return MediaTime::invalidTime();
2775 }
2776
2777 bool HTMLMediaElement::paused() const
2778 {
2779     // As of this writing, JavaScript garbage collection calls this function directly. In the past
2780     // we had problems where this was called on an object after a bad cast. The assertion below
2781     // made our regression test detect the problem, so we should keep it because of that. But note
2782     // that the value of the assertion relies on the compiler not being smart enough to know that
2783     // isHTMLUnknownElement is guaranteed to return false for an HTMLMediaElement.
2784     ASSERT(!isHTMLUnknownElement());
2785
2786     return m_paused;
2787 }
2788
2789 double HTMLMediaElement::defaultPlaybackRate() const
2790 {
2791     return m_defaultPlaybackRate;
2792 }
2793
2794 void HTMLMediaElement::setDefaultPlaybackRate(double rate)
2795 {
2796     if (m_defaultPlaybackRate != rate) {
2797         LOG(Media, "HTMLMediaElement::setDefaultPlaybackRate(%p) - %f", this, rate);
2798         m_defaultPlaybackRate = rate;
2799         scheduleEvent(eventNames().ratechangeEvent);
2800     }
2801 }
2802
2803 double HTMLMediaElement::effectivePlaybackRate() const
2804 {
2805     return m_mediaController ? m_mediaController->playbackRate() : m_reportedPlaybackRate;
2806 }
2807
2808 double HTMLMediaElement::requestedPlaybackRate() const
2809 {
2810     return m_mediaController ? m_mediaController->playbackRate() : m_requestedPlaybackRate;
2811 }
2812
2813 double HTMLMediaElement::playbackRate() const
2814 {
2815     return m_requestedPlaybackRate;
2816 }
2817
2818 void HTMLMediaElement::setPlaybackRate(double rate)
2819 {
2820     LOG(Media, "HTMLMediaElement::setPlaybackRate(%p) - %f", this, rate);
2821
2822     if (m_player && potentiallyPlaying() && m_player->rate() != rate && !m_mediaController)
2823         m_player->setRate(rate);
2824
2825     if (m_requestedPlaybackRate != rate) {
2826         m_reportedPlaybackRate = m_requestedPlaybackRate = rate;
2827         invalidateCachedTime();
2828         scheduleEvent(eventNames().ratechangeEvent);
2829     }
2830 }
2831
2832 void HTMLMediaElement::updatePlaybackRate()
2833 {
2834     double requestedRate = requestedPlaybackRate();
2835     if (m_player && potentiallyPlaying() && m_player->rate() != requestedRate)
2836         m_player->setRate(requestedRate);
2837 }
2838
2839 bool HTMLMediaElement::webkitPreservesPitch() const
2840 {
2841     return m_webkitPreservesPitch;
2842 }
2843
2844 void HTMLMediaElement::setWebkitPreservesPitch(bool preservesPitch)
2845 {
2846     LOG(Media, "HTMLMediaElement::setWebkitPreservesPitch(%p) - %s", this, boolString(preservesPitch));
2847
2848     m_webkitPreservesPitch = preservesPitch;
2849     
2850     if (!m_player)
2851         return;
2852
2853     m_player->setPreservesPitch(preservesPitch);
2854 }
2855
2856 bool HTMLMediaElement::ended() const
2857 {
2858     // 4.8.10.8 Playing the media resource
2859     // The ended attribute must return true if the media element has ended 
2860     // playback and the direction of playback is forwards, and false otherwise.
2861     return endedPlayback() && requestedPlaybackRate() > 0;
2862 }
2863
2864 bool HTMLMediaElement::autoplay() const
2865 {
2866     return fastHasAttribute(autoplayAttr);
2867 }
2868
2869 String HTMLMediaElement::preload() const
2870 {
2871     switch (m_preload) {
2872     case MediaPlayer::None:
2873         return ASCIILiteral("none");
2874     case MediaPlayer::MetaData:
2875         return ASCIILiteral("metadata");
2876     case MediaPlayer::Auto:
2877         return ASCIILiteral("auto");
2878     }
2879
2880     ASSERT_NOT_REACHED();
2881     return String();
2882 }
2883
2884 void HTMLMediaElement::setPreload(const String& preload)
2885 {
2886     LOG(Media, "HTMLMediaElement::setPreload(%p) - %s", this, preload.utf8().data());
2887     setAttribute(preloadAttr, preload);
2888 }
2889
2890 void HTMLMediaElement::play()
2891 {
2892     LOG(Media, "HTMLMediaElement::play(%p)", this);
2893
2894     if (!m_mediaSession->playbackPermitted(*this))
2895         return;
2896     if (ScriptController::processingUserGestureForMedia())
2897         removeBehaviorsRestrictionsAfterFirstUserGesture();
2898
2899     playInternal();
2900 }
2901
2902 void HTMLMediaElement::playInternal()
2903 {
2904     LOG(Media, "HTMLMediaElement::playInternal(%p)", this);
2905     
2906     if (!m_mediaSession->clientWillBeginPlayback()) {
2907         LOG(Media, "  returning because of interruption");
2908         return;
2909     }
2910
2911     // 4.8.10.9. Playing the media resource
2912     if (!m_player || m_networkState == NETWORK_EMPTY)
2913         scheduleDelayedAction(LoadMediaResource);
2914
2915     if (endedPlayback())
2916         seekInternal(MediaTime::zeroTime());
2917
2918     if (m_mediaController)
2919         m_mediaController->bringElementUpToSpeed(this);
2920
2921     if (m_paused) {
2922         m_paused = false;
2923         invalidateCachedTime();
2924         scheduleEvent(eventNames().playEvent);
2925
2926         if (m_readyState <= HAVE_CURRENT_DATA)
2927             scheduleEvent(eventNames().waitingEvent);
2928         else if (m_readyState >= HAVE_FUTURE_DATA)
2929             scheduleEvent(eventNames().playingEvent);
2930
2931 #if ENABLE(MEDIA_SESSION)
2932         // 6.3 Activating a media session from a media element
2933         // When the play() method is invoked, the paused attribute is true, and the readyState attribute has the value
2934         // HAVE_FUTURE_DATA or HAVE_ENOUGH_DATA, then
2935         // 1. Let media session be the value of the current media session.
2936         // 2. If we are not currently in media session's list of active participating media elements then append
2937         //    ourselves to this list.
2938         // 3. Let activated be the result of running the media session invocation algorithm for media session.
2939         // 4. If activated is failure, pause ourselves.
2940         if (m_readyState == HAVE_ENOUGH_DATA || m_readyState == HAVE_FUTURE_DATA) {
2941             if (m_session) {
2942                 m_session->addActiveMediaElement(*this);
2943
2944                 if (m_session->kindEnum() == MediaSession::Kind::Content) {
2945                     if (Page* page = document().page())
2946                         page->chrome().client().focusedContentMediaElementDidChange(m_elementID);
2947                 }
2948
2949                 if (!m_session->invoke()) {
2950                     pause();
2951                     return;
2952                 }
2953             }
2954         }
2955 #endif
2956     }
2957     m_autoplaying = false;
2958     updatePlayState();
2959     updateMediaController();
2960 }
2961
2962 void HTMLMediaElement::pause()
2963 {
2964     LOG(Media, "HTMLMediaElement::pause(%p)", this);
2965
2966     if (!m_mediaSession->playbackPermitted(*this))
2967         return;
2968
2969     pauseInternal();
2970 }
2971
2972
2973 void HTMLMediaElement::pauseInternal()
2974 {
2975     LOG(Media, "HTMLMediaElement::pauseInternal(%p)", this);
2976
2977     if (!m_mediaSession->clientWillPausePlayback()) {
2978         LOG(Media, "  returning because of interruption");
2979         return;
2980     }
2981
2982     // 4.8.10.9. Playing the media resource
2983     if (!m_player || m_networkState == NETWORK_EMPTY) {
2984         // Unless the restriction on media requiring user action has been lifted
2985         // don't trigger loading if a script calls pause().
2986         if (!m_mediaSession->playbackPermitted(*this))
2987             return;
2988         scheduleDelayedAction(LoadMediaResource);
2989     }
2990
2991     m_autoplaying = false;
2992
2993     if (!m_paused) {
2994         m_paused = true;
2995         scheduleTimeupdateEvent(false);
2996         scheduleEvent(eventNames().pauseEvent);
2997
2998         if (MemoryPressureHandler::singleton().isUnderMemoryPressure())
2999             purgeBufferedDataIfPossible();
3000     }
3001
3002     updatePlayState();
3003 }
3004
3005 #if ENABLE(MEDIA_SOURCE)
3006 void HTMLMediaElement::closeMediaSource()
3007 {
3008     if (!m_mediaSource)
3009         return;
3010
3011     m_mediaSource->close();
3012     m_mediaSource = nullptr;
3013 }
3014 #endif
3015
3016 #if ENABLE(ENCRYPTED_MEDIA)
3017 void HTMLMediaElement::webkitGenerateKeyRequest(const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionCode& ec)
3018 {
3019 #if ENABLE(ENCRYPTED_MEDIA_V2)
3020     static bool firstTime = true;
3021     if (firstTime && scriptExecutionContext()) {
3022         scriptExecutionContext()->addConsoleMessage(MessageSource::JS, MessageLevel::Warning, ASCIILiteral("'HTMLMediaElement.webkitGenerateKeyRequest()' is deprecated.  Use 'MediaKeys.createSession()' instead."));
3023         firstTime = false;
3024     }
3025 #endif
3026
3027     if (keySystem.isEmpty()) {
3028         ec = SYNTAX_ERR;
3029         return;
3030     }
3031
3032     if (!m_player) {
3033         ec = INVALID_STATE_ERR;
3034         return;
3035     }
3036
3037     const unsigned char* initDataPointer = 0;
3038     unsigned initDataLength = 0;
3039     if (initData) {
3040         initDataPointer = initData->data();
3041         initDataLength = initData->length();
3042     }
3043
3044     MediaPlayer::MediaKeyException result = m_player->generateKeyRequest(keySystem, initDataPointer, initDataLength);
3045     ec = exceptionCodeForMediaKeyException(result);
3046 }
3047
3048 void HTMLMediaElement::webkitGenerateKeyRequest(const String& keySystem, ExceptionCode& ec)
3049 {
3050     webkitGenerateKeyRequest(keySystem, Uint8Array::create(0), ec);
3051 }
3052
3053 void HTMLMediaElement::webkitAddKey(const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionCode& ec)
3054 {
3055 #if ENABLE(ENCRYPTED_MEDIA_V2)
3056     static bool firstTime = true;
3057     if (firstTime && scriptExecutionContext()) {
3058         scriptExecutionContext()->addConsoleMessage(MessageSource::JS, MessageLevel::Warning, ASCIILiteral("'HTMLMediaElement.webkitAddKey()' is deprecated.  Use 'MediaKeySession.update()' instead."));
3059         firstTime = false;
3060     }
3061 #endif
3062
3063     if (keySystem.isEmpty()) {
3064         ec = SYNTAX_ERR;
3065         return;
3066     }
3067
3068     if (!key) {
3069         ec = SYNTAX_ERR;
3070         return;
3071     }
3072
3073     if (!key->length()) {
3074         ec = TYPE_MISMATCH_ERR;
3075         return;
3076     }
3077
3078     if (!m_player) {
3079         ec = INVALID_STATE_ERR;
3080         return;
3081     }
3082
3083     const unsigned char* initDataPointer = 0;
3084     unsigned initDataLength = 0;
3085     if (initData) {
3086         initDataPointer = initData->data();
3087         initDataLength = initData->length();
3088     }
3089
3090     MediaPlayer::MediaKeyException result = m_player->addKey(keySystem, key->data(), key->length(), initDataPointer, initDataLength, sessionId);
3091     ec = exceptionCodeForMediaKeyException(result);
3092 }
3093
3094 void HTMLMediaElement::webkitAddKey(const String& keySystem, PassRefPtr<Uint8Array> key, ExceptionCode& ec)
3095 {
3096     webkitAddKey(keySystem, key, Uint8Array::create(0), String(), ec);
3097 }
3098
3099 void HTMLMediaElement::webkitCancelKeyRequest(const String& keySystem, const String& sessionId, ExceptionCode& ec)
3100 {
3101     if (keySystem.isEmpty()) {
3102         ec = SYNTAX_ERR;
3103         return;
3104     }
3105
3106     if (!m_player) {
3107         ec = INVALID_STATE_ERR;
3108         return;
3109     }
3110
3111     MediaPlayer::MediaKeyException result = m_player->cancelKeyRequest(keySystem, sessionId);
3112     ec = exceptionCodeForMediaKeyException(result);
3113 }
3114
3115 #endif
3116
3117 bool HTMLMediaElement::loop() const
3118 {
3119     return fastHasAttribute(loopAttr);
3120 }
3121
3122 void HTMLMediaElement::setLoop(bool b)
3123 {
3124     LOG(Media, "HTMLMediaElement::setLoop(%p) - %s", this, boolString(b));
3125     setBooleanAttribute(loopAttr, b);
3126 }
3127
3128 bool HTMLMediaElement::controls() const
3129 {
3130     Frame* frame = document().frame();
3131
3132     // always show controls when scripting is disabled
3133     if (frame && !frame->script().canExecuteScripts(NotAboutToExecuteScript))
3134         return true;
3135
3136     return fastHasAttribute(controlsAttr);
3137 }
3138
3139 void HTMLMediaElement::setControls(bool b)
3140 {
3141     LOG(Media, "HTMLMediaElement::setControls(%p) - %s", this, boolString(b));
3142     setBooleanAttribute(controlsAttr, b);
3143 }
3144
3145 double HTMLMediaElement::volume() const
3146 {
3147     return m_volume;
3148 }
3149
3150 void HTMLMediaElement::setVolume(double vol, ExceptionCode& ec)
3151 {
3152     LOG(Media, "HTMLMediaElement::setVolume(%p) - %f", this, vol);
3153
3154     if (vol < 0.0f || vol > 1.0f) {
3155         ec = INDEX_SIZE_ERR;
3156         return;
3157     }
3158     
3159 #if !PLATFORM(IOS)
3160     if (m_volume != vol) {
3161         m_volume = vol;
3162         m_volumeInitialized = true;
3163         updateVolume();
3164         scheduleEvent(eventNames().volumechangeEvent);
3165     }
3166 #endif
3167 }
3168
3169 bool HTMLMediaElement::muted() const
3170 {
3171     return m_explicitlyMuted ? m_muted : fastHasAttribute(mutedAttr);
3172 }
3173
3174 void HTMLMediaElement::setMuted(bool muted)
3175 {
3176     LOG(Media, "HTMLMediaElement::setMuted(%p) - %s", this, boolString(muted));
3177
3178 #if PLATFORM(IOS)
3179     UNUSED_PARAM(muted);
3180 #else
3181     if (m_muted != muted || !m_explicitlyMuted) {
3182         m_muted = muted;
3183         m_explicitlyMuted = true;
3184         // Avoid recursion when the player reports volume changes.
3185         if (!processingMediaPlayerCallback()) {
3186             if (m_player) {
3187                 m_player->setMuted(effectiveMuted());
3188                 if (hasMediaControls())
3189                     mediaControls()->changedMute();
3190             }
3191         }
3192         scheduleEvent(eventNames().volumechangeEvent);
3193
3194 #if ENABLE(MEDIA_SESSION)
3195         document().updateIsPlayingMedia(m_elementID);
3196 #else
3197         document().updateIsPlayingMedia();
3198 #endif
3199
3200 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
3201         updateMediaState(UpdateMediaState::Asynchronously);
3202 #endif
3203     }
3204 #endif
3205 }
3206
3207 void HTMLMediaElement::togglePlayState()
3208 {
3209     LOG(Media, "HTMLMediaElement::togglePlayState(%p) - canPlay() is %s", this, boolString(canPlay()));
3210
3211     // We can safely call the internal play/pause methods, which don't check restrictions, because
3212     // this method is only called from the built-in media controller
3213     if (canPlay()) {
3214         updatePlaybackRate();
3215         playInternal();
3216     } else 
3217         pauseInternal();
3218 }
3219
3220 void HTMLMediaElement::beginScrubbing()
3221 {
3222     LOG(Media, "HTMLMediaElement::beginScrubbing(%p) - paused() is %s", this, boolString(paused()));
3223
3224     if (!paused()) {
3225         if (ended()) {
3226             // Because a media element stays in non-paused state when it reaches end, playback resumes 
3227             // when the slider is dragged from the end to another position unless we pause first. Do 
3228             // a "hard pause" so an event is generated, since we want to stay paused after scrubbing finishes.
3229             pause();
3230         } else {
3231             // Not at the end but we still want to pause playback so the media engine doesn't try to
3232             // continue playing during scrubbing. Pause without generating an event as we will 
3233             // unpause after scrubbing finishes.
3234             setPausedInternal(true);
3235         }
3236     }
3237 }
3238
3239 void HTMLMediaElement::endScrubbing()
3240 {
3241     LOG(Media, "HTMLMediaElement::endScrubbing(%p) - m_pausedInternal is %s", this, boolString(m_pausedInternal));
3242
3243     if (m_pausedInternal)
3244         setPausedInternal(false);
3245 }
3246
3247 void HTMLMediaElement::beginScanning(ScanDirection direction)
3248 {
3249     m_scanType = supportsScanning() ? Scan : Seek;
3250     m_scanDirection = direction;
3251
3252     if (m_scanType == Seek) {
3253         // Scanning by seeking requires the video to be paused during scanning.
3254         m_actionAfterScan = paused() ? Nothing : Play;
3255         pause();
3256     } else {
3257         // Scanning by scanning requires the video to be playing during scanninging.
3258         m_actionAfterScan = paused() ? Pause : Nothing;
3259         play();
3260         setPlaybackRate(nextScanRate());
3261     }
3262
3263     m_scanTimer.start(0, m_scanType == Seek ? SeekRepeatDelay : ScanRepeatDelay);
3264 }
3265
3266 void HTMLMediaElement::endScanning()
3267 {
3268     if (m_scanType == Scan)
3269         setPlaybackRate(defaultPlaybackRate());
3270
3271     if (m_actionAfterScan == Play)
3272         play();
3273     else if (m_actionAfterScan == Pause)
3274         pause();
3275
3276     if (m_scanTimer.isActive())
3277         m_scanTimer.stop();
3278 }
3279
3280 double HTMLMediaElement::nextScanRate()
3281 {
3282     double rate = std::min(ScanMaximumRate, fabs(playbackRate() * 2));
3283     if (m_scanDirection == Backward)
3284         rate *= -1;
3285 #if PLATFORM(IOS)
3286     rate = std::min(std::max(rate, minFastReverseRate()), maxFastForwardRate());
3287 #endif
3288     return rate;
3289 }
3290
3291 void HTMLMediaElement::scanTimerFired()
3292 {
3293     if (m_scanType == Seek) {
3294         double seekTime = m_scanDirection == Forward ? SeekTime : -SeekTime;
3295         setCurrentTime(currentTime() + seekTime);
3296     } else
3297         setPlaybackRate(nextScanRate());
3298 }
3299
3300 // The spec says to fire periodic timeupdate events (those sent while playing) every
3301 // "15 to 250ms", we choose the slowest frequency
3302 static const double maxTimeupdateEventFrequency = 0.25;
3303
3304 void HTMLMediaElement::startPlaybackProgressTimer()
3305 {
3306     if (m_playbackProgressTimer.isActive())
3307         return;
3308
3309     m_previousProgressTime = monotonicallyIncreasingTime();
3310     m_playbackProgressTimer.startRepeating(maxTimeupdateEventFrequency);
3311 }
3312
3313 void HTMLMediaElement::playbackProgressTimerFired()
3314 {
3315     ASSERT(m_player);
3316
3317     if (m_fragmentEndTime.isValid() && currentMediaTime() >= m_fragmentEndTime && requestedPlaybackRate() > 0) {
3318         m_fragmentEndTime = MediaTime::invalidTime();
3319         if (!m_mediaController && !m_paused) {
3320             // changes paused to true and fires a simple event named pause at the media element.
3321             pauseInternal();
3322         }
3323     }
3324     
3325     scheduleTimeupdateEvent(true);
3326
3327     if (!requestedPlaybackRate())
3328         return;
3329
3330     if (!m_paused && hasMediaControls())
3331         mediaControls()->playbackProgressed();
3332
3333 #if ENABLE(VIDEO_TRACK)
3334     if (RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
3335         updateActiveTextTrackCues(currentMediaTime());
3336 #endif
3337
3338 #if ENABLE(MEDIA_SOURCE)
3339     if (m_mediaSource)
3340         m_mediaSource->monitorSourceBuffers();
3341 #endif
3342 }
3343
3344 void HTMLMediaElement::scheduleTimeupdateEvent(bool periodicEvent)
3345 {
3346     double now = monotonicallyIncreasingTime();
3347     double timedelta = now - m_clockTimeAtLastUpdateEvent;
3348
3349     // throttle the periodic events
3350     if (periodicEvent && timedelta < maxTimeupdateEventFrequency)
3351         return;
3352
3353     // Some media engines make multiple "time changed" callbacks at the same time, but we only want one
3354     // event at a given time so filter here
3355     MediaTime movieTime = currentMediaTime();
3356     if (movieTime != m_lastTimeUpdateEventMovieTime) {
3357         scheduleEvent(eventNames().timeupdateEvent);
3358         m_clockTimeAtLastUpdateEvent = now;
3359         m_lastTimeUpdateEventMovieTime = movieTime;
3360     }
3361 }
3362
3363 bool HTMLMediaElement::canPlay() const
3364 {
3365     return paused() || ended() || m_readyState < HAVE_METADATA;
3366 }
3367
3368 double HTMLMediaElement::percentLoaded() const
3369 {
3370     if (!m_player)
3371         return 0;
3372     MediaTime duration = m_player->duration();
3373
3374     if (!duration || duration.isPositiveInfinite() || duration.isNegativeInfinite())
3375         return 0;
3376
3377     MediaTime buffered = MediaTime::zeroTime();
3378     bool ignored;
3379     std::unique_ptr<PlatformTimeRanges> timeRanges = m_player->buffered();
3380     for (unsigned i = 0; i < timeRanges->length(); ++i) {
3381         MediaTime start = timeRanges->start(i, ignored);
3382         MediaTime end = timeRanges->end(i, ignored);
3383         buffered += end - start;
3384     }
3385     return buffered.toDouble() / duration.toDouble();
3386 }
3387
3388 #if ENABLE(VIDEO_TRACK)
3389
3390 void HTMLMediaElement::mediaPlayerDidAddAudioTrack(PassRefPtr<AudioTrackPrivate> prpTrack)
3391 {
3392     if (isPlaying() && !m_mediaSession->playbackPermitted(*this))
3393         pauseInternal();
3394
3395     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
3396         return;
3397
3398     addAudioTrack(AudioTrack::create(this, prpTrack));
3399 }
3400
3401 void HTMLMediaElement::mediaPlayerDidAddTextTrack(PassRefPtr<InbandTextTrackPrivate> prpTrack)
3402 {
3403     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
3404         return;
3405     
3406     // 4.8.10.12.2 Sourcing in-band text tracks
3407     // 1. Associate the relevant data with a new text track and its corresponding new TextTrack object.
3408     RefPtr<InbandTextTrack> textTrack = InbandTextTrack::create(ActiveDOMObject::scriptExecutionContext(), this, prpTrack);
3409     textTrack->setMediaElement(this);
3410     
3411     // 2. Set the new text track's kind, label, and language based on the semantics of the relevant data,
3412     // as defined by the relevant specification. If there is no label in that data, then the label must
3413     // be set to the empty string.
3414     // 3. Associate the text track list of cues with the rules for updating the text track rendering appropriate
3415     // for the format in question.
3416     // 4. If the new text track's kind is metadata, then set the text track in-band metadata track dispatch type
3417     // as follows, based on the type of the media resource:
3418     // 5. Populate the new text track's list of cues with the cues parsed so far, folllowing the guidelines for exposing
3419     // cues, and begin updating it dynamically as necessary.
3420     //   - Thess are all done by the media engine.
3421     
3422     // 6. Set the new text track's readiness state to loaded.
3423     textTrack->setReadinessState(TextTrack::Loaded);
3424     
3425     // 7. Set the new text track's mode to the mode consistent with the user's preferences and the requirements of
3426     // the relevant specification for the data.
3427     //  - This will happen in configureTextTracks()
3428     scheduleDelayedAction(ConfigureTextTracks);
3429     
3430     // 8. Add the new text track to the media element's list of text tracks.
3431     // 9. Fire an event with the name addtrack, that does not bubble and is not cancelable, and that uses the TrackEvent
3432     // interface, with the track attribute initialized to the text track's TextTrack object, at the media element's
3433     // textTracks attribute's TextTrackList object.
3434     addTextTrack(textTrack.release());
3435 }
3436
3437 void HTMLMediaElement::mediaPlayerDidAddVideoTrack(PassRefPtr<VideoTrackPrivate> prpTrack)
3438 {
3439     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
3440         return;
3441
3442     addVideoTrack(VideoTrack::create(this, prpTrack));
3443 }
3444
3445 void HTMLMediaElement::mediaPlayerDidRemoveAudioTrack(PassRefPtr<AudioTrackPrivate> prpTrack)
3446 {
3447     prpTrack->willBeRemoved();
3448 }
3449
3450 void HTMLMediaElement::mediaPlayerDidRemoveTextTrack(PassRefPtr<InbandTextTrackPrivate> prpTrack)
3451 {
3452     prpTrack->willBeRemoved();
3453 }
3454
3455 void HTMLMediaElement::mediaPlayerDidRemoveVideoTrack(PassRefPtr<VideoTrackPrivate> prpTrack)
3456 {
3457     prpTrack->willBeRemoved();
3458 }
3459
3460 void HTMLMediaElement::closeCaptionTracksChanged()
3461 {
3462     if (hasMediaControls())
3463         mediaControls()->closedCaptionTracksChanged();
3464 }
3465
3466 void HTMLMediaElement::addAudioTrack(PassRefPtr<AudioTrack> track)
3467 {
3468     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
3469         return;
3470
3471     audioTracks()->append(track);
3472 }
3473
3474 void HTMLMediaElement::addTextTrack(PassRefPtr<TextTrack> track)
3475 {
3476     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
3477         return;
3478
3479     if (!m_requireCaptionPreferencesChangedCallbacks) {
3480         m_requireCaptionPreferencesChangedCallbacks = true;
3481         document().registerForCaptionPreferencesChangedCallbacks(this);
3482     }
3483
3484     textTracks()->append(track);
3485
3486     closeCaptionTracksChanged();
3487 }
3488
3489 void HTMLMediaElement::addVideoTrack(PassRefPtr<VideoTrack> track)
3490 {
3491     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
3492         return;
3493
3494     videoTracks()->append(track);
3495 }
3496
3497 void HTMLMediaElement::removeAudioTrack(AudioTrack* track)
3498 {
3499     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
3500         return;
3501
3502     m_audioTracks->remove(track);
3503 }
3504
3505 void HTMLMediaElement::removeTextTrack(TextTrack* track, bool scheduleEvent)
3506 {
3507     if (!RuntimeEnabledFeatures::sharedFeatures().webkitVideoTrackEnabled())
3508         return;
3509
3510     TrackDisplayUpdateScope scope(this);
3511     if (TextTrackCueList* cues = track->cues())
3512         textTrackRemoveCues(track, cues);
3513     track->clearClient();
3514     if (m_textTracks)
3515         m_textTracks->remove(track, scheduleEvent);
3516