2 * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, 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 COMPUTER, 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.
27 #include "core/html/HTMLVideoElement.h"
29 #include "CSSPropertyNames.h"
30 #include "HTMLNames.h"
31 #include "bindings/v8/ExceptionState.h"
32 #include "core/dom/Attribute.h"
33 #include "core/dom/Document.h"
34 #include "core/dom/ExceptionCode.h"
35 #include "core/html/HTMLImageLoader.h"
36 #include "core/html/parser/HTMLParserIdioms.h"
37 #include "core/frame/Settings.h"
38 #include "core/rendering/RenderImage.h"
39 #include "core/rendering/RenderVideo.h"
40 #include "platform/UserGestureIndicator.h"
44 using namespace HTMLNames;
46 inline HTMLVideoElement::HTMLVideoElement(Document& document)
47 : HTMLMediaElement(videoTag, document)
49 ScriptWrappable::init(this);
50 if (document.settings())
51 m_defaultPosterURL = AtomicString(document.settings()->defaultVideoPosterURL());
54 PassRefPtr<HTMLVideoElement> HTMLVideoElement::create(Document& document)
56 RefPtr<HTMLVideoElement> videoElement(adoptRef(new HTMLVideoElement(document)));
57 videoElement->suspendIfNeeded();
58 return videoElement.release();
61 bool HTMLVideoElement::rendererIsNeeded(const RenderStyle& style)
63 return HTMLElement::rendererIsNeeded(style);
66 RenderObject* HTMLVideoElement::createRenderer(RenderStyle*)
68 return new RenderVideo(this);
71 void HTMLVideoElement::attach(const AttachContext& context)
73 HTMLMediaElement::attach(context);
76 if (shouldDisplayPosterImage()) {
78 m_imageLoader = adoptPtr(new HTMLImageLoader(this));
79 m_imageLoader->updateFromElement();
81 toRenderImage(renderer())->imageResource()->setImageResource(m_imageLoader->image());
85 void HTMLVideoElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
87 if (name == widthAttr)
88 addHTMLLengthToStyle(style, CSSPropertyWidth, value);
89 else if (name == heightAttr)
90 addHTMLLengthToStyle(style, CSSPropertyHeight, value);
92 HTMLMediaElement::collectStyleForPresentationAttribute(name, value, style);
95 bool HTMLVideoElement::isPresentationAttribute(const QualifiedName& name) const
97 if (name == widthAttr || name == heightAttr)
99 return HTMLMediaElement::isPresentationAttribute(name);
102 void HTMLVideoElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
104 if (name == posterAttr) {
105 // Force a poster recalc by setting m_displayMode to Unknown directly before calling updateDisplayState.
106 HTMLMediaElement::setDisplayMode(Unknown);
107 updateDisplayState();
108 if (shouldDisplayPosterImage()) {
110 m_imageLoader = adoptPtr(new HTMLImageLoader(this));
111 m_imageLoader->updateFromElementIgnoringPreviousError();
114 toRenderImage(renderer())->imageResource()->setImageResource(0);
116 // Notify the player when the poster image URL changes.
118 player()->setPoster(posterImageURL());
120 HTMLMediaElement::parseAttribute(name, value);
123 bool HTMLVideoElement::supportsFullscreen() const
125 if (!document().page())
134 unsigned HTMLVideoElement::videoWidth() const
138 return player()->naturalSize().width();
141 unsigned HTMLVideoElement::videoHeight() const
145 return player()->naturalSize().height();
148 bool HTMLVideoElement::isURLAttribute(const Attribute& attribute) const
150 return attribute.name() == posterAttr || HTMLMediaElement::isURLAttribute(attribute);
153 const AtomicString HTMLVideoElement::imageSourceURL() const
155 const AtomicString& url = getAttribute(posterAttr);
156 if (!stripLeadingAndTrailingHTMLSpaces(url).isEmpty())
158 return m_defaultPosterURL;
161 void HTMLVideoElement::setDisplayMode(DisplayMode mode)
163 DisplayMode oldMode = displayMode();
164 KURL poster = posterImageURL();
166 if (!poster.isEmpty()) {
167 // We have a poster path, but only show it until the user triggers display by playing or seeking and the
168 // media engine has something to display.
169 if (mode == Video && !hasAvailableVideoFrame())
170 mode = PosterWaitingForVideo;
173 HTMLMediaElement::setDisplayMode(mode);
175 if (renderer() && displayMode() != oldMode)
176 renderer()->updateFromElement();
179 void HTMLVideoElement::updateDisplayState()
181 if (posterImageURL().isEmpty())
182 setDisplayMode(Video);
183 else if (displayMode() < Poster)
184 setDisplayMode(Poster);
187 void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& destRect)
189 MediaPlayer* player = HTMLMediaElement::player();
192 player->paint(context, destRect);
195 bool HTMLVideoElement::copyVideoTextureToPlatformTexture(blink::WebGraphicsContext3D* context, Platform3DObject texture, GLint level, GLenum type, GLenum internalFormat, bool premultiplyAlpha, bool flipY)
199 return player()->copyVideoTextureToPlatformTexture(context, texture, level, type, internalFormat, premultiplyAlpha, flipY);
202 bool HTMLVideoElement::hasAvailableVideoFrame() const
207 return player()->hasVideo() && player()->readyState() >= MediaPlayer::HaveCurrentData;
210 void HTMLVideoElement::webkitEnterFullscreen(ExceptionState& exceptionState)
215 // Generate an exception if this isn't called in response to a user gesture, or if the
216 // element does not support fullscreen.
217 if (userGestureRequiredForFullscreen() && !UserGestureIndicator::processingUserGesture()) {
218 exceptionState.throwDOMException(InvalidStateError, "This element may only enter fullscreen mode in response to a user gesture ('click', for example).");
221 if (!supportsFullscreen()) {
222 exceptionState.throwDOMException(InvalidStateError, "This element does not support fullscreen mode.");
229 void HTMLVideoElement::webkitExitFullscreen()
235 bool HTMLVideoElement::webkitSupportsFullscreen()
237 return supportsFullscreen();
240 bool HTMLVideoElement::webkitDisplayingFullscreen()
242 return isFullscreen();
245 void HTMLVideoElement::didMoveToNewDocument(Document& oldDocument)
248 m_imageLoader->elementDidMoveToNewDocument();
249 HTMLMediaElement::didMoveToNewDocument(oldDocument);
252 unsigned HTMLVideoElement::webkitDecodedFrameCount() const
257 return player()->decodedFrameCount();
260 unsigned HTMLVideoElement::webkitDroppedFrameCount() const
265 return player()->droppedFrameCount();
268 KURL HTMLVideoElement::posterImageURL() const
270 String url = stripLeadingAndTrailingHTMLSpaces(imageSourceURL());
273 return document().completeURL(url);
276 KURL HTMLVideoElement::mediaPlayerPosterURL()
278 return posterImageURL();