예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
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;
}
예제 #6
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();
}
예제 #7
0
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();
    }
}