• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007, 2008, 2009, 2010 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 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.
24  */
25 
26 #include "config.h"
27 #include "core/html/HTMLVideoElement.h"
28 
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"
41 
42 namespace WebCore {
43 
44 using namespace HTMLNames;
45 
HTMLVideoElement(Document & document,bool createdByParser)46 inline HTMLVideoElement::HTMLVideoElement(Document& document, bool createdByParser)
47     : HTMLMediaElement(videoTag, document, createdByParser)
48 {
49     ScriptWrappable::init(this);
50     if (document.settings())
51         m_defaultPosterURL = document.settings()->defaultVideoPosterURL();
52 }
53 
create(Document & document,bool createdByParser)54 PassRefPtr<HTMLVideoElement> HTMLVideoElement::create(Document& document, bool createdByParser)
55 {
56     RefPtr<HTMLVideoElement> videoElement(adoptRef(new HTMLVideoElement(document, createdByParser)));
57     videoElement->suspendIfNeeded();
58     return videoElement.release();
59 }
60 
rendererIsNeeded(const RenderStyle & style)61 bool HTMLVideoElement::rendererIsNeeded(const RenderStyle& style)
62 {
63     return HTMLElement::rendererIsNeeded(style);
64 }
65 
createRenderer(RenderStyle *)66 RenderObject* HTMLVideoElement::createRenderer(RenderStyle*)
67 {
68     return new RenderVideo(this);
69 }
70 
attach(const AttachContext & context)71 void HTMLVideoElement::attach(const AttachContext& context)
72 {
73     HTMLMediaElement::attach(context);
74 
75     updateDisplayState();
76     if (shouldDisplayPosterImage()) {
77         if (!m_imageLoader)
78             m_imageLoader = adoptPtr(new HTMLImageLoader(this));
79         m_imageLoader->updateFromElement();
80         if (renderer())
81             toRenderImage(renderer())->imageResource()->setImageResource(m_imageLoader->image());
82     }
83 }
84 
collectStyleForPresentationAttribute(const QualifiedName & name,const AtomicString & value,MutableStylePropertySet * style)85 void HTMLVideoElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
86 {
87     if (name == widthAttr)
88         addHTMLLengthToStyle(style, CSSPropertyWidth, value);
89     else if (name == heightAttr)
90         addHTMLLengthToStyle(style, CSSPropertyHeight, value);
91     else
92         HTMLMediaElement::collectStyleForPresentationAttribute(name, value, style);
93 }
94 
isPresentationAttribute(const QualifiedName & name) const95 bool HTMLVideoElement::isPresentationAttribute(const QualifiedName& name) const
96 {
97     if (name == widthAttr || name == heightAttr)
98         return true;
99     return HTMLMediaElement::isPresentationAttribute(name);
100 }
101 
parseAttribute(const QualifiedName & name,const AtomicString & value)102 void HTMLVideoElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
103 {
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()) {
109             if (!m_imageLoader)
110                 m_imageLoader = adoptPtr(new HTMLImageLoader(this));
111             m_imageLoader->updateFromElementIgnoringPreviousError();
112         } else {
113             if (renderer())
114                 toRenderImage(renderer())->imageResource()->setImageResource(0);
115         }
116     } else
117         HTMLMediaElement::parseAttribute(name, value);
118 }
119 
supportsFullscreen() const120 bool HTMLVideoElement::supportsFullscreen() const
121 {
122     if (!document().page())
123         return false;
124 
125     if (!player() || !player()->supportsFullscreen())
126         return false;
127 
128     return true;
129 }
130 
videoWidth() const131 unsigned HTMLVideoElement::videoWidth() const
132 {
133     if (!player())
134         return 0;
135     return player()->naturalSize().width();
136 }
137 
videoHeight() const138 unsigned HTMLVideoElement::videoHeight() const
139 {
140     if (!player())
141         return 0;
142     return player()->naturalSize().height();
143 }
144 
isURLAttribute(const Attribute & attribute) const145 bool HTMLVideoElement::isURLAttribute(const Attribute& attribute) const
146 {
147     return attribute.name() == posterAttr || HTMLMediaElement::isURLAttribute(attribute);
148 }
149 
imageSourceURL() const150 const AtomicString HTMLVideoElement::imageSourceURL() const
151 {
152     const AtomicString& url = getAttribute(posterAttr);
153     if (!stripLeadingAndTrailingHTMLSpaces(url).isEmpty())
154         return url;
155     return m_defaultPosterURL;
156 }
157 
setDisplayMode(DisplayMode mode)158 void HTMLVideoElement::setDisplayMode(DisplayMode mode)
159 {
160     DisplayMode oldMode = displayMode();
161     KURL poster = posterImageURL();
162 
163     if (!poster.isEmpty()) {
164         // We have a poster path, but only show it until the user triggers display by playing or seeking and the
165         // media engine has something to display.
166         if (mode == Video && !hasAvailableVideoFrame())
167             mode = PosterWaitingForVideo;
168     }
169 
170     HTMLMediaElement::setDisplayMode(mode);
171 
172     if (renderer() && displayMode() != oldMode)
173         renderer()->updateFromElement();
174 }
175 
updateDisplayState()176 void HTMLVideoElement::updateDisplayState()
177 {
178     if (posterImageURL().isEmpty())
179         setDisplayMode(Video);
180     else if (displayMode() < Poster)
181         setDisplayMode(Poster);
182 }
183 
paintCurrentFrameInContext(GraphicsContext * context,const IntRect & destRect)184 void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& destRect)
185 {
186     MediaPlayer* player = HTMLMediaElement::player();
187     if (!player)
188         return;
189     player->paint(context, destRect);
190 }
191 
copyVideoTextureToPlatformTexture(GraphicsContext3D * context,Platform3DObject texture,GC3Dint level,GC3Denum type,GC3Denum internalFormat,bool premultiplyAlpha,bool flipY)192 bool HTMLVideoElement::copyVideoTextureToPlatformTexture(GraphicsContext3D* context, Platform3DObject texture, GC3Dint level, GC3Denum type, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY)
193 {
194     if (!player())
195         return false;
196     return player()->copyVideoTextureToPlatformTexture(context, texture, level, type, internalFormat, premultiplyAlpha, flipY);
197 }
198 
hasAvailableVideoFrame() const199 bool HTMLVideoElement::hasAvailableVideoFrame() const
200 {
201     if (!player())
202         return false;
203 
204     return player()->hasVideo() && player()->readyState() >= MediaPlayer::HaveCurrentData;
205 }
206 
webkitEnterFullscreen(ExceptionState & exceptionState)207 void HTMLVideoElement::webkitEnterFullscreen(ExceptionState& exceptionState)
208 {
209     if (isFullscreen())
210         return;
211 
212     // Generate an exception if this isn't called in response to a user gesture, or if the
213     // element does not support fullscreen.
214     if (userGestureRequiredForFullscreen() && !UserGestureIndicator::processingUserGesture()) {
215         exceptionState.throwDOMException(InvalidStateError, "This element may only enter fullscreen mode in response to a user gesture ('click', for example).");
216         return;
217     }
218     if (!supportsFullscreen()) {
219         exceptionState.throwDOMException(InvalidStateError, "This element does not support fullscreen mode.");
220         return;
221     }
222 
223     enterFullscreen();
224 }
225 
webkitExitFullscreen()226 void HTMLVideoElement::webkitExitFullscreen()
227 {
228     if (isFullscreen())
229         exitFullscreen();
230 }
231 
webkitSupportsFullscreen()232 bool HTMLVideoElement::webkitSupportsFullscreen()
233 {
234     return supportsFullscreen();
235 }
236 
webkitDisplayingFullscreen()237 bool HTMLVideoElement::webkitDisplayingFullscreen()
238 {
239     return isFullscreen();
240 }
241 
didMoveToNewDocument(Document & oldDocument)242 void HTMLVideoElement::didMoveToNewDocument(Document& oldDocument)
243 {
244     if (m_imageLoader)
245         m_imageLoader->elementDidMoveToNewDocument();
246     HTMLMediaElement::didMoveToNewDocument(oldDocument);
247 }
248 
webkitDecodedFrameCount() const249 unsigned HTMLVideoElement::webkitDecodedFrameCount() const
250 {
251     if (!player())
252         return 0;
253 
254     return player()->decodedFrameCount();
255 }
256 
webkitDroppedFrameCount() const257 unsigned HTMLVideoElement::webkitDroppedFrameCount() const
258 {
259     if (!player())
260         return 0;
261 
262     return player()->droppedFrameCount();
263 }
264 
posterImageURL() const265 KURL HTMLVideoElement::posterImageURL() const
266 {
267     String url = stripLeadingAndTrailingHTMLSpaces(imageSourceURL());
268     if (url.isEmpty())
269         return KURL();
270     return document().completeURL(url);
271 }
272 
273 }
274