bool MediaElementSession::playbackPermitted(const HTMLMediaElement& element) const { if (pageExplicitlyAllowsElementToAutoplayInline(element)) return true; if (requiresFullscreenForVideoPlayback(element) && !fullscreenPermitted(element)) { LOG(Media, "MediaElementSession::playbackPermitted - returning FALSE because of fullscreen restriction"); return false; } if (m_restrictions & OverrideUserGestureRequirementForMainContent && updateIsMainContent()) return true; if (m_restrictions & RequireUserGestureForVideoRateChange && element.isVideo() && !ScriptController::processingUserGestureForMedia()) { LOG(Media, "MediaElementSession::playbackPermitted - returning FALSE because of video rate change restriction"); return false; } if (m_restrictions & RequireUserGestureForAudioRateChange && (!element.isVideo() || element.hasAudio()) && !element.muted() && !ScriptController::processingUserGestureForMedia()) { LOG(Media, "MediaElementSession::playbackPermitted - returning FALSE because of audio rate change restriction"); return false; } return true; }
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; }
PassRefPtr<Widget> SubframeLoader::loadMediaPlayerProxyPlugin(Node* node, const URL& url, const Vector<String>& paramNames, const Vector<String>& paramValues) { ASSERT(node->hasTagName(videoTag) || isHTMLAudioElement(node)); URL completedURL; if (!url.isEmpty()) completedURL = completeURL(url); if (!m_frame.document()->securityOrigin()->canDisplay(completedURL)) { FrameLoader::reportLocalLoadFailed(m_frame, completedURL.string()); return 0; } if (!m_frame.document()->contentSecurityPolicy()->allowMediaFromSource(completedURL)) return 0; HTMLMediaElement* mediaElement = toHTMLMediaElement(node); RenderWidget* renderer = toRenderWidget(node->renderer()); IntSize size; if (renderer) size = roundedIntSize(LayoutSize(renderer->contentWidth(), renderer->contentHeight())); else if (mediaElement->isVideo()) size = RenderVideo::defaultSize(); if (!m_frame.loader().mixedContentChecker().canRunInsecureContent(m_frame.document()->securityOrigin(), completedURL)) return 0; RefPtr<Widget> widget = m_frame.loader().client().createMediaPlayerProxyPlugin(size, mediaElement, completedURL, paramNames, paramValues, "application/x-media-element-proxy-plugin"); if (widget && renderer) { renderer->setWidget(widget); renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange); } m_containsPlugins = true; return widget ? widget.release() : 0; }
void MediaPlayerPrivate::resizeSourceDimensions() { if (!m_webCorePlayer) return; HTMLMediaElement* client = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient()); if (!client || !client->isVideo()) return; RenderObject* o = client->renderer(); if (!o) return; // If we have an HTMLVideoElement but the source has no video, then we need to resize the media element. if (!hasVideo()) { IntRect rect = o->enclosingBox()->contentBoxRect(); static const int playbookMinAudioElementWidth = 300; static const int playbookMinAudioElementHeight = 32; // If the rect dimensions are less than the allowed minimum, use the minimum instead. int newWidth = max(rect.width(), playbookMinAudioElementWidth); int newHeight = max(rect.height(), playbookMinAudioElementHeight); char attrString[12]; sprintf(attrString, "%d", newWidth); client->setAttribute(HTMLNames::widthAttr, attrString); sprintf(attrString, "%d", newHeight); client->setAttribute(HTMLNames::heightAttr, attrString); } // If we don't know what the width and height of the video source is, then we need to set it to something sane. if (m_platformPlayer->sourceWidth() && m_platformPlayer->sourceHeight()) return; IntRect rect = o->enclosingBox()->contentBoxRect(); m_platformPlayer->setSourceDimension(rect.width(), rect.height()); }
PassRefPtr<Widget> SubframeLoader::loadMediaPlayerProxyPlugin(Node* node, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues) { ASSERT(node->hasTagName(videoTag) || node->hasTagName(audioTag)); if (!m_frame->script()->xssAuditor()->canLoadObject(url.string())) return 0; KURL completedURL; if (!url.isEmpty()) completedURL = completeURL(url); if (!m_frame->document()->securityOrigin()->canDisplay(completedURL)) { FrameLoader::reportLocalLoadFailed(m_frame, completedURL.string()); return 0; } HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node); RenderPart* renderer = toRenderPart(node->renderer()); IntSize size; if (renderer) size = IntSize(renderer->contentWidth(), renderer->contentHeight()); else if (mediaElement->isVideo()) size = RenderVideo::defaultSize(); m_frame->loader()->checkIfRunInsecureContent(m_frame->document()->securityOrigin(), completedURL); RefPtr<Widget> widget = m_frame->loader()->client()->createMediaPlayerProxyPlugin(size, mediaElement, completedURL, paramNames, paramValues, "application/x-media-element-proxy-plugin"); if (widget && renderer) { renderer->setWidget(widget); renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange); } m_containsPlugins = true; return widget ? widget.release() : 0; }
void MediaControlTextTrackContainerElement::updateDisplay() { HTMLMediaElement* mediaElement = toParentMediaElement(this); // 1. If the media element is an audio element, or is another playback // mechanism with no rendering area, abort these steps. There is nothing to // render. if (!mediaElement->isVideo()) return; // 2. Let video be the media element or other playback mechanism. HTMLVideoElement* video = static_cast<HTMLVideoElement*>(mediaElement); // 3. Let output be an empty list of absolutely positioned CSS block boxes. Vector<RefPtr<HTMLDivElement> > output; // 4. If the user agent is exposing a user interface for video, add to // output one or more completely transparent positioned CSS block boxes that // cover the same region as the user interface. // 5. If the last time these rules were run, the user agent was not exposing // a user interface for video, but now it is, let reset be true. Otherwise, // let reset be false. // There is nothing to be done explicitly for 4th and 5th steps, as // everything is handled through CSS. The caption box is on top of the // controls box, in a container set with the -webkit-box display property. // 6. Let tracks be the subset of video's list of text tracks that have as // their rules for updating the text track rendering these rules for // updating the display of WebVTT text tracks, and whose text track mode is // showing or showing by default. // 7. Let cues be an empty list of text track cues. // 8. For each track track in tracks, append to cues all the cues from // track's list of cues that have their text track cue active flag set. CueList activeCues = video->currentlyActiveCues(); // 9. If reset is false, then, for each text track cue cue in cues: if cue's // text track cue display state has a set of CSS boxes, then add those boxes // to output, and remove cue from cues. // There is nothing explicitly to be done here, as all the caching occurs // within the TextTrackCue instance itself. If parameters of the cue change, // the display tree is cleared. // 10. For each text track cue cue in cues that has not yet had // corresponding CSS boxes added to output, in text track cue order, run the // following substeps: for (size_t i = 0; i < activeCues.size(); ++i) { TextTrackCue* cue = activeCues[i].data(); ASSERT(cue->isActive()); if (!cue->track() || !cue->track()->isRendered()) continue; RefPtr<TextTrackCueBox> displayBox = cue->getDisplayTree(); if (displayBox->hasChildNodes() && !contains(static_cast<Node*>(displayBox.get()))) // Note: the display tree of a cue is removed when the active flag of the cue is unset. appendChild(displayBox, ASSERT_NO_EXCEPTION, false); } // 11. Return output. hasChildNodes() ? show() : hide(); }
void MediaControlTextTrackContainerElement::updateDisplay() { if (!mediaController()->closedCaptionsVisible()) removeChildren(); HTMLMediaElement* mediaElement = parentMediaElement(this); // 1. If the media element is an audio element, or is another playback // mechanism with no rendering area, abort these steps. There is nothing to // render. if (!mediaElement || !mediaElement->isVideo()) return; // 2. Let video be the media element or other playback mechanism. HTMLVideoElement* video = toHTMLVideoElement(mediaElement); // 3. Let output be an empty list of absolutely positioned CSS block boxes. Vector<RefPtr<HTMLDivElement>> output; // 4. If the user agent is exposing a user interface for video, add to // output one or more completely transparent positioned CSS block boxes that // cover the same region as the user interface. // 5. If the last time these rules were run, the user agent was not exposing // a user interface for video, but now it is, let reset be true. Otherwise, // let reset be false. // There is nothing to be done explicitly for 4th and 5th steps, as // everything is handled through CSS. The caption box is on top of the // controls box, in a container set with the -webkit-box display property. // 6. Let tracks be the subset of video's list of text tracks that have as // their rules for updating the text track rendering these rules for // updating the display of WebVTT text tracks, and whose text track mode is // showing or showing by default. // 7. Let cues be an empty list of text track cues. // 8. For each track track in tracks, append to cues all the cues from // track's list of cues that have their text track cue active flag set. CueList activeCues = video->currentlyActiveCues(); // 9. If reset is false, then, for each text track cue cue in cues: if cue's // text track cue display state has a set of CSS boxes, then add those boxes // to output, and remove cue from cues. // There is nothing explicitly to be done here, as all the caching occurs // within the TextTrackCue instance itself. If parameters of the cue change, // the display tree is cleared. // 10. For each text track cue cue in cues that has not yet had // corresponding CSS boxes added to output, in text track cue order, run the // following substeps: for (size_t i = 0; i < activeCues.size(); ++i) { TextTrackCue* cue = activeCues[i].data(); ASSERT(cue->isActive()); if (!cue->track() || !cue->track()->isRendered() || !cue->isActive() || cue->text().isEmpty()) continue; RefPtr<TextTrackCueBox> displayBox = cue->getDisplayTree(m_videoDisplaySize.size()); if (displayBox->hasChildNodes() && !contains(displayBox.get())) { // Note: the display tree of a cue is removed when the active flag of the cue is unset. appendChild(displayBox, ASSERT_NO_EXCEPTION, AttachNow); cue->setFontSize(m_fontSize, m_videoDisplaySize.size(), m_fontSizeIsImportant); } } // 11. Return output. if (hasChildNodes()) { show(); if (mediaElement->requiresTextTrackRepresentation()) { if (!m_textTrackRepresentation) m_textTrackRepresentation = TextTrackRepresentation::create(this); mediaElement->setTextTrackRepresentation(m_textTrackRepresentation.get()); if (Page* page = document().page()) m_textTrackRepresentation->setContentScale(page->deviceScaleFactor()); m_textTrackRepresentation->update(); setInlineStyleProperty(CSSPropertyWidth, m_videoDisplaySize.size().width(), CSSPrimitiveValue::CSS_PX); setInlineStyleProperty(CSSPropertyHeight, m_videoDisplaySize.size().height(), CSSPrimitiveValue::CSS_PX); } } else { hide(); clearTextTrackRepresentation(); } }