MediaControls::MediaControls(HTMLMediaElement& mediaElement) : HTMLDivElement(mediaElement.document()), m_mediaElement(&mediaElement), m_overlayEnclosure(nullptr), m_overlayPlayButton(nullptr), m_overlayCastButton(nullptr), m_enclosure(nullptr), m_panel(nullptr), m_playButton(nullptr), m_timeline(nullptr), m_currentTimeDisplay(nullptr), m_durationDisplay(nullptr), m_muteButton(nullptr), m_volumeSlider(nullptr), m_toggleClosedCaptionsButton(nullptr), m_textTrackList(nullptr), m_overflowList(nullptr), m_castButton(nullptr), m_fullscreenButton(nullptr), m_downloadButton(nullptr), m_mediaEventListener(new MediaControlsMediaEventListener(this)), m_windowEventListener(MediaControlsWindowEventListener::create( this, WTF::bind(&MediaControls::hideAllMenus, wrapWeakPersistent(this)))), m_hideMediaControlsTimer(this, &MediaControls::hideMediaControlsTimerFired), m_hideTimerBehaviorFlags(IgnoreNone), m_isMouseOverControls(false), m_isPausedForScrubbing(false), m_panelWidthChangedTimer(this, &MediaControls::panelWidthChangedTimerFired), m_panelWidth(0), m_keepShowingUntilTimerFires(false) {}
MediaControls::MediaControls(HTMLMediaElement& mediaElement) : HTMLDivElement(mediaElement.document()) , m_mediaElement(&mediaElement) , m_overlayEnclosure(nullptr) , m_overlayPlayButton(nullptr) , m_overlayCastButton(nullptr) , m_enclosure(nullptr) , m_panel(nullptr) , m_playButton(nullptr) , m_timeline(nullptr) , m_currentTimeDisplay(nullptr) , m_durationDisplay(nullptr) , m_muteButton(nullptr) , m_volumeSlider(nullptr) , m_toggleClosedCaptionsButton(nullptr) , m_castButton(nullptr) , m_fullScreenButton(nullptr) , m_hideMediaControlsTimer(this, &MediaControls::hideMediaControlsTimerFired) , m_hideTimerBehaviorFlags(IgnoreNone) , m_isMouseOverControls(false) , m_isPausedForScrubbing(false) , m_panelWidthChangedTimer(this, &MediaControls::panelWidthChangedTimerFired) , m_panelWidth(0) , m_allowHiddenVolumeControls(RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) , m_keepMuteButton(false) { }
void HTMLMediaSession::showPlaybackTargetPicker(const HTMLMediaElement& element) { LOG(Media, "HTMLMediaSession::showPlaybackTargetPicker"); if (m_restrictions & RequireUserGestureToShowPlaybackTargetPicker && !ScriptController::processingUserGesture()) { LOG(Media, "HTMLMediaSession::showPlaybackTargetPicker - returning early because of permissions"); return; } if (!element.document().page()) { LOG(Media, "HTMLMediaSession::showingPlaybackTargetPickerPermitted - returning early because page is NULL"); return; } element.document().showPlaybackTargetPicker(*this, is<HTMLVideoElement>(element)); }
void WebMediaPlayerProxy::initEngine() { HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_mediaPlayer->mediaPlayerClient()); String url = element->initialURL(); if (url.isEmpty()) return; Frame* frame = element->document()->frame(); Vector<String> paramNames; Vector<String> paramValues; String serviceType; // add all attributes set on the embed object if (NamedNodeMap* attributes = element->attributes()) { for (unsigned i = 0; i < attributes->length(); ++i) { Attribute* it = attributes->attributeItem(i); paramNames.append(it->name().localName().string()); paramValues.append(it->value().string()); } } serviceType = "application/x-mplayer2"; frame->loader()->requestObject(static_cast<RenderPartObject*>(element->renderer()), url, nullAtom, serviceType, paramNames, paramValues); m_init = true; }
bool MediaElementSession::wirelessVideoPlaybackDisabled(const HTMLMediaElement& element) const { Settings* settings = element.document().settings(); if (!settings || !settings->allowsAirPlayForMediaPlayback()) { LOG(Media, "MediaElementSession::wirelessVideoPlaybackDisabled - returning TRUE because of settings"); return true; } if (element.fastHasAttribute(HTMLNames::webkitwirelessvideoplaybackdisabledAttr)) { LOG(Media, "MediaElementSession::wirelessVideoPlaybackDisabled - returning TRUE because of attribute"); return true; } #if PLATFORM(IOS) String legacyAirplayAttributeValue = element.fastGetAttribute(HTMLNames::webkitairplayAttr); if (equalLettersIgnoringASCIICase(legacyAirplayAttributeValue, "deny")) { LOG(Media, "MediaElementSession::wirelessVideoPlaybackDisabled - returning TRUE because of legacy attribute"); return true; } if (equalLettersIgnoringASCIICase(legacyAirplayAttributeValue, "allow")) { LOG(Media, "MediaElementSession::wirelessVideoPlaybackDisabled - returning FALSE because of legacy attribute"); return false; } #endif MediaPlayer* player = element.player(); if (!player) return true; bool disabled = player->wirelessVideoPlaybackDisabled(); LOG(Media, "MediaElementSession::wirelessVideoPlaybackDisabled - returning %s because media engine says so", disabled ? "TRUE" : "FALSE"); return disabled; }
void HTMLMediaSession::unregisterWithDocument(const HTMLMediaElement& element) { #if ENABLE(WIRELESS_PLAYBACK_TARGET) element.document().removePlaybackTargetPickerClient(*this); #else UNUSED_PARAM(element); #endif }
void InbandTextTrack::addWebVTTCue(double start, double end, const WebString& id, const WebString& content, const WebString& settings) { HTMLMediaElement* owner = mediaElement(); ASSERT(owner); RefPtrWillBeRawPtr<VTTCue> cue = VTTCue::create(owner->document(), start, end, content); cue->setId(id); cue->parseSettings(settings); addCue(cue); }
bool MediaElementSession::pageAllowsPlaybackAfterResuming(const HTMLMediaElement& element) const { Page* page = element.document().page(); if (m_restrictions & RequirePageConsentToResumeMedia && page && !page->canStartMedia()) { LOG(Media, "MediaElementSession::pageAllowsPlaybackAfterResuming - returning FALSE"); return false; } return true; }
bool HTMLMediaSession::pageAllowsDataLoading(const HTMLMediaElement& element) const { Page* page = element.document().page(); if (m_restrictions & RequirePageConsentToLoadMedia && page && !page->canStartMedia()) { LOG(Media, "HTMLMediaSession::pageAllowsDataLoading - returning FALSE"); return false; } return true; }
// This function returns the user agent string associated with the // frame loader client of our HTMLMediaElement. The call below will // end up in FrameLoaderClientBlackBerry::userAgent(). String MediaPlayerPrivate::userAgent(const String& url) const { HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient()); Document* topdoc = element->document()->topDocument(); ASSERT(topdoc->frame()); ASSERT(topdoc->frame()->loader()); if (topdoc->frame()) return topdoc->frame()->loader()->userAgent(KURL(KURL(), url)); return String(); }
bool MediaElementSession::allowsAutomaticMediaDataLoading(const HTMLMediaElement& element) const { if (pageExplicitlyAllowsElementToAutoplayInline(element)) return true; Settings* settings = element.document().settings(); if (settings && settings->mediaDataLoadsAutomatically()) return true; return false; }
void HTMLMediaSession::showPlaybackTargetPicker(const HTMLMediaElement& element) { LOG(Media, "HTMLMediaSession::showPlaybackTargetPicker"); if (!showingPlaybackTargetPickerPermitted(element)) return; #if PLATFORM(IOS) element.document().frame()->page()->chrome().client().showPlaybackTargetPicker(element.hasVideo()); #endif }
FrameView* MediaPlayerPrivate::frameView() const { // We previously used m_webCorePlayer->frameView(), but this method returns // a null frameView until quite late in the media player initialization, // and starting quite early in the media player destruction (because // it may be set to zero by the destructor in RenderVideo.cpp before // our destructor is called, leaving us unable to clean up child windows // in mmrDisconnect). HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient()); return element->document()->view(); }
bool MediaElementSession::canControlControlsManager(const HTMLMediaElement& element) const { if (!element.hasAudio()) { LOG(Media, "MediaElementSession::canControlControlsManager - returning FALSE: No audio"); return false; } if (element.muted()) { LOG(Media, "MediaElementSession::canControlControlsManager - returning FALSE: Muted"); return false; } if (element.ended()) { LOG(Media, "MediaElementSession::canControlControlsManager - returning FALSE: Ended"); return false; } if (element.document().activeDOMObjectsAreSuspended()) { LOG(Media, "MediaElementSession::canControlControlsManager - returning FALSE: activeDOMObjectsAreSuspended()"); return false; } if (!playbackPermitted(element)) { LOG(Media, "MediaElementSession::canControlControlsManager - returning FALSE: Playback not permitted"); return false; } if (element.isVideo()) { if (!element.renderer()) { LOG(Media, "MediaElementSession::canControlControlsManager - returning FALSE: No renderer"); return false; } if (!element.hasVideo()) { LOG(Media, "MediaElementSession::canControlControlsManager - returning FALSE: No video"); return false; } if (isElementLargeEnoughForMainContent(element)) { LOG(Media, "MediaElementSession::canControlControlsManager - returning TRUE: Is main content"); return true; } } if (m_restrictions & RequireUserGestureToControlControlsManager && !ScriptController::processingUserGestureForMedia()) { LOG(Media, "MediaElementSession::canControlControlsManager - returning FALSE: No user gesture"); return false; } LOG(Media, "MediaElementSession::canControlControlsManager - returning TRUE: All criteria met"); return true; }
void MediaElementSession::setHasPlaybackTargetAvailabilityListeners(const HTMLMediaElement& element, bool hasListeners) { LOG(Media, "MediaElementSession::setHasPlaybackTargetAvailabilityListeners - hasListeners %s", hasListeners ? "TRUE" : "FALSE"); #if PLATFORM(IOS) UNUSED_PARAM(element); m_hasPlaybackTargetAvailabilityListeners = hasListeners; PlatformMediaSessionManager::sharedManager().configureWireLessTargetMonitoring(); #else UNUSED_PARAM(hasListeners); element.document().playbackTargetPickerClientStateDidChange(*this, element.mediaState()); #endif }
bool HTMLMediaSession::showingPlaybackTargetPickerPermitted(const HTMLMediaElement& element) const { if (m_restrictions & RequireUserGestureToShowPlaybackTargetPicker && !ScriptController::processingUserGesture()) { LOG(Media, "HTMLMediaSession::showingPlaybackTargetPickerPermitted - returning FALSE because of permissions"); return false; } if (!element.document().page()) { LOG(Media, "HTMLMediaSession::showingPlaybackTargetPickerPermitted - returning FALSE because page is NULL"); return false; } return !wirelessVideoPlaybackDisabled(element); }
void MediaElementSession::showPlaybackTargetPicker(const HTMLMediaElement& element) { LOG(Media, "MediaElementSession::showPlaybackTargetPicker"); if (m_restrictions & RequireUserGestureToShowPlaybackTargetPicker && !ScriptController::processingUserGestureForMedia()) { LOG(Media, "MediaElementSession::showPlaybackTargetPicker - returning early because of permissions"); return; } if (!element.document().page()) { LOG(Media, "MediaElementSession::showingPlaybackTargetPickerPermitted - returning early because page is NULL"); return; } #if !PLATFORM(IOS) if (element.readyState() < HTMLMediaElementEnums::HAVE_METADATA) { LOG(Media, "MediaElementSession::showPlaybackTargetPicker - returning early because element is not playable"); return; } #endif element.document().showPlaybackTargetPicker(*this, is<HTMLVideoElement>(element)); }
bool MediaElementSession::requiresFullscreenForVideoPlayback(const HTMLMediaElement& element) const { if (pageExplicitlyAllowsElementToAutoplayInline(element)) return false; if (is<HTMLAudioElement>(element)) return false; Settings* settings = element.document().settings(); if (!settings || !settings->allowsInlineMediaPlayback()) return true; return settings->inlineMediaPlaybackRequiresPlaysInlineAttribute() && !element.fastHasAttribute(HTMLNames::webkit_playsinlineAttr); }
static bool isMainContent(const HTMLMediaElement& element) { if (!element.hasAudio() || !element.hasVideo()) return false; // Elements which have not yet been laid out, or which are not yet in the DOM, cannot be main content. RenderBox* renderer = downcast<RenderBox>(element.renderer()); if (!renderer) return false; if (!isElementLargeEnoughForMainContent(element)) return false; // Elements which are hidden by style, or have been scrolled out of view, cannot be main content. // But elements which have audio & video and are already playing should not stop playing because // they are scrolled off the page. if (renderer->style().visibility() != VISIBLE || (renderer->visibleInViewportState() != RenderElement::VisibleInViewport && !element.isPlaying()) ) { return false; } // Main content elements must be in the main frame. Document& document = element.document(); if (!document.frame() || !document.frame()->isMainFrame()) return false; MainFrame& mainFrame = document.frame()->mainFrame(); if (!mainFrame.view() || !mainFrame.view()->renderView()) return false; RenderView& mainRenderView = *mainFrame.view()->renderView(); // Hit test the area of the main frame where the element appears, to determine if the element is being obscured. IntRect rectRelativeToView = element.clientRect(); ScrollPosition scrollPosition = mainFrame.view()->documentScrollPositionRelativeToViewOrigin(); IntRect rectRelativeToTopDocument(rectRelativeToView.location() + scrollPosition, rectRelativeToView.size()); HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowUserAgentShadowContent); HitTestResult result(rectRelativeToTopDocument.center()); // Elements which are obscured by other elements cannot be main content. mainRenderView.hitTest(request, result); result.setToNonUserAgentShadowAncestor(); Element* hitElement = result.innerElement(); if (hitElement != &element) return false; return true; }
std::unique_ptr<WebMediaPlayer> FrameLoaderClientImpl::createWebMediaPlayer( HTMLMediaElement& htmlMediaElement, const WebMediaPlayerSource& source, WebMediaPlayerClient* client) { WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(htmlMediaElement.document().frame()); if (!webFrame || !webFrame->client()) return nullptr; HTMLMediaElementEncryptedMedia& encryptedMedia = HTMLMediaElementEncryptedMedia::from(htmlMediaElement); WebString sinkId(HTMLMediaElementAudioOutputDevice::sinkId(htmlMediaElement)); return wrapUnique(webFrame->client()->createMediaPlayer( source, client, &encryptedMedia, encryptedMedia.contentDecryptionModule(), sinkId)); }
static bool shouldShowFullscreenButton(const HTMLMediaElement& mediaElement) { // Unconditionally allow the user to exit fullscreen if we are in it // now. Especially on android, when we might not yet know if // fullscreen is supported, we sometimes guess incorrectly and show // the button earlier, and we don't want to remove it here if the // user chose to enter fullscreen. crbug.com/500732 . if (mediaElement.isFullscreen()) return true; if (!mediaElement.hasVideo()) return false; if (!Fullscreen::fullscreenEnabled(mediaElement.document())) return false; return true; }
bool HTMLMediaSession::requiresFullscreenForVideoPlayback(const HTMLMediaElement& element) const { if (!MediaSessionManager::sharedManager().sessionRestrictsInlineVideoPlayback(*this)) return false; Settings* settings = element.document().settings(); if (!settings || !settings->mediaPlaybackAllowsInline()) return true; if (element.fastHasAttribute(HTMLNames::webkit_playsinlineAttr)) return false; #if PLATFORM(IOS) if (applicationIsDumpRenderTree()) return false; #endif return true; }
int MediaPlayerPrivate::showErrorDialog(MMRPlayer::Error type) { using namespace BlackBerry::WebKit; WebPageClient::AlertType atype; switch (type) { case MMRPlayer::MediaOK: atype = WebPageClient::MediaOK; break; case MMRPlayer::MediaDecodeError: atype = WebPageClient::MediaDecodeError; break; case MMRPlayer::MediaMetaDataError: atype = WebPageClient::MediaMetaDataError; break; case MMRPlayer::MediaMetaDataTimeoutError: atype = WebPageClient::MediaMetaDataTimeoutError; break; case MMRPlayer::MediaNoMetaDataError: atype = WebPageClient::MediaNoMetaDataError; break; case MMRPlayer::MediaVideoReceiveError: atype = WebPageClient::MediaVideoReceiveError; break; case MMRPlayer::MediaAudioReceiveError: atype = WebPageClient::MediaAudioReceiveError; break; case MMRPlayer::MediaInvalidError: atype = WebPageClient::MediaInvalidError; break; default: LOG(Media, "Alert type does not exist."); return -1; } int rc = 0; HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient()); Document* topdoc = element->document()->topDocument(); if (topdoc->view() && topdoc->view()->hostWindow()) rc = topdoc->view()->hostWindow()->platformPageClient()->showAlertDialog(atype); return rc; }
static bool isElementLargeRelativeToMainFrame(const HTMLMediaElement& element) { static const double minimumPercentageOfMainFrameAreaForMainContent = 0.9; auto* renderer = element.renderer(); if (!renderer) return false; auto* documentFrame = element.document().frame(); if (!documentFrame) return false; if (!documentFrame->mainFrame().view()) return false; auto& mainFrameView = *documentFrame->mainFrame().view(); auto maxVisibleClientWidth = std::min(renderer->clientWidth().toInt(), mainFrameView.visibleWidth()); auto maxVisibleClientHeight = std::min(renderer->clientHeight().toInt(), mainFrameView.visibleHeight()); return maxVisibleClientWidth * maxVisibleClientHeight > minimumPercentageOfMainFrameAreaForMainContent * mainFrameView.visibleWidth() * mainFrameView.visibleHeight(); }
bool MediaElementSession::requiresFullscreenForVideoPlayback(const HTMLMediaElement& element) const { if (pageExplicitlyAllowsElementToAutoplayInline(element)) return false; if (is<HTMLAudioElement>(element)) return false; Settings* settings = element.document().settings(); if (!settings || !settings->allowsInlineMediaPlayback()) return true; if (!settings->inlineMediaPlaybackRequiresPlaysInlineAttribute()) return false; #if PLATFORM(IOS) if (dyld_get_program_sdk_version() < DYLD_IOS_VERSION_10_0) return !element.hasAttributeWithoutSynchronization(HTMLNames::webkit_playsinlineAttr); #endif return !element.hasAttributeWithoutSynchronization(HTMLNames::playsinlineAttr); }
MediaControls::MediaControls(HTMLMediaElement& mediaElement) : HTMLDivElement(mediaElement.document()) , m_mediaElement(&mediaElement) , m_panel(nullptr) , m_textDisplayContainer(nullptr) , m_overlayPlayButton(nullptr) , m_overlayEnclosure(nullptr) , m_playButton(nullptr) , m_currentTimeDisplay(nullptr) , m_timeline(nullptr) , m_muteButton(nullptr) , m_volumeSlider(nullptr) , m_toggleClosedCaptionsButton(nullptr) , m_fullScreenButton(nullptr) , m_durationDisplay(nullptr) , m_enclosure(nullptr) , m_hideMediaControlsTimer(this, &MediaControls::hideMediaControlsTimerFired) , m_isMouseOverControls(false) , m_isPausedForScrubbing(false) { }
void HTMLMediaSession::showPlaybackTargetPicker(const HTMLMediaElement& element) { LOG(Media, "HTMLMediaSession::showPlaybackTargetPicker"); if (!showingPlaybackTargetPickerPermitted(element)) return; #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) if (element.shouldUseVideoPluginProxy()) { MediaPlayer* player = element.player(); if (!player) return; player->showPlaybackTargetPicker(); return; } #endif #if PLATFORM(IOS) element.document().frame()->page()->chrome().client().showPlaybackTargetPicker(element.hasVideo()); #endif }
void MediaPlayerPrivate::load(const String& url) { // We are now loading if (m_networkState != MediaPlayer::Loading) { m_networkState = MediaPlayer::Loading; m_player->networkStateChanged(); } // And we don't have any data yet if (m_readyState != MediaPlayer::HaveNothing) { m_readyState = MediaPlayer::HaveNothing; m_player->readyStateChanged(); } const QUrl rUrl = QUrl(QString(url)); const QString scheme = rUrl.scheme().toLower(); // Grab the client media element HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_player->mediaPlayerClient()); // Construct the media content with a network request if the resource is http[s] if (scheme == "http" || scheme == "https") { QNetworkRequest request = QNetworkRequest(rUrl); // Grab the current document Document* document = element->document(); if (!document) document = element->ownerDocument(); // Grab the frame and network manager Frame* frame = document ? document->frame() : 0; FrameLoaderClientQt* frameLoader = frame ? static_cast<FrameLoaderClientQt*>(frame->loader()->client()) : 0; QNetworkAccessManager* manager = frameLoader ? frameLoader->webFrame()->page()->networkAccessManager() : 0; if (document && manager) { // Set the cookies QNetworkCookieJar* jar = manager->cookieJar(); QList<QNetworkCookie> cookies = jar->cookiesForUrl(rUrl); // Don't set the header if there are no cookies. // This prevents a warning from being emitted. if (!cookies.isEmpty()) request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies)); // Set the refferer, but not when requesting insecure content from a secure page QUrl documentUrl = QUrl(QString(document->documentURI())); if (documentUrl.scheme().toLower() == "http" || scheme == "https") request.setRawHeader("Referer", documentUrl.toEncoded()); // Set the user agent request.setRawHeader("User-Agent", frameLoader->userAgent(rUrl).utf8().data()); } m_mediaPlayer->setMedia(QMediaContent(request)); } else { // Otherwise, just use the URL m_mediaPlayer->setMedia(QMediaContent(rUrl)); } // Set the current volume and mute status // We get these from the element, rather than the player, in case we have // transitioned from a media engine which doesn't support muting, to a media // engine which does. m_mediaPlayer->setMuted(element->muted()); m_mediaPlayer->setVolume(static_cast<int>(element->volume() * 100.0)); }
static bool pageExplicitlyAllowsElementToAutoplayInline(const HTMLMediaElement& element) { Document& document = element.document(); Page* page = document.page(); return document.isMediaDocument() && !document.ownerElement() && page && page->allowsMediaDocumentInlinePlayback(); }
bool MediaElementSession::allowsPictureInPicture(const HTMLMediaElement& element) const { Settings* settings = element.document().settings(); return settings && settings->allowsPictureInPictureMediaPlayback() && !element.webkitCurrentPlaybackTargetIsWireless(); }