• 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 
28 #if ENABLE(VIDEO)
29 #include "HTMLVideoElement.h"
30 
31 #include "Attribute.h"
32 #include "CSSPropertyNames.h"
33 #include "Chrome.h"
34 #include "ChromeClient.h"
35 #include "Document.h"
36 #include "ExceptionCode.h"
37 #include "HTMLImageLoader.h"
38 #include "HTMLNames.h"
39 #include "Page.h"
40 #include "RenderImage.h"
41 #include "RenderVideo.h"
42 
43 namespace WebCore {
44 
45 using namespace HTMLNames;
46 
HTMLVideoElement(const QualifiedName & tagName,Document * document)47 inline HTMLVideoElement::HTMLVideoElement(const QualifiedName& tagName, Document* document)
48     : HTMLMediaElement(tagName, document)
49 {
50     ASSERT(hasTagName(videoTag));
51 }
52 
create(const QualifiedName & tagName,Document * document)53 PassRefPtr<HTMLVideoElement> HTMLVideoElement::create(const QualifiedName& tagName, Document* document)
54 {
55     return adoptRef(new HTMLVideoElement(tagName, document));
56 }
57 
rendererIsNeeded(RenderStyle * style)58 bool HTMLVideoElement::rendererIsNeeded(RenderStyle* style)
59 {
60     return HTMLElement::rendererIsNeeded(style);
61 }
62 
63 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
createRenderer(RenderArena * arena,RenderStyle *)64 RenderObject* HTMLVideoElement::createRenderer(RenderArena* arena, RenderStyle*)
65 {
66     return new (arena) RenderVideo(this);
67 }
68 #endif
69 
attach()70 void HTMLVideoElement::attach()
71 {
72     HTMLMediaElement::attach();
73 
74 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
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()->setCachedImage(m_imageLoader->image());
82     }
83 #endif
84 }
85 
detach()86 void HTMLVideoElement::detach()
87 {
88     HTMLMediaElement::detach();
89 
90     if (!shouldDisplayPosterImage() && m_imageLoader)
91         m_imageLoader.clear();
92 }
93 
parseMappedAttribute(Attribute * attr)94 void HTMLVideoElement::parseMappedAttribute(Attribute* attr)
95 {
96     const QualifiedName& attrName = attr->name();
97 
98     if (attrName == posterAttr) {
99         // Force a poster recalc by setting m_displayMode to Unknown directly before calling updateDisplayState.
100         HTMLMediaElement::setDisplayMode(Unknown);
101         updateDisplayState();
102 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
103         if (shouldDisplayPosterImage()) {
104             if (!m_imageLoader)
105                 m_imageLoader = adoptPtr(new HTMLImageLoader(this));
106             m_imageLoader->updateFromElementIgnoringPreviousError();
107         } else {
108             if (m_imageLoader)
109                 m_imageLoader.clear();
110             if (renderer())
111                 toRenderImage(renderer())->imageResource()->setCachedImage(0);
112         }
113 #endif
114     } else if (attrName == widthAttr)
115         addCSSLength(attr, CSSPropertyWidth, attr->value());
116     else if (attrName == heightAttr)
117         addCSSLength(attr, CSSPropertyHeight, attr->value());
118     else
119         HTMLMediaElement::parseMappedAttribute(attr);
120 }
121 
supportsFullscreen() const122 bool HTMLVideoElement::supportsFullscreen() const
123 {
124     Page* page = document() ? document()->page() : 0;
125     if (!page)
126         return false;
127 
128     if (!player() || !player()->supportsFullscreen() || !player()->hasVideo())
129         return false;
130 
131     // Check with the platform client.
132 #if ENABLE(FULLSCREEN_API)
133     if (page->chrome()->client()->supportsFullScreenForElement(this, false))
134         return true;
135 #endif
136 
137     return page->chrome()->client()->supportsFullscreenForNode(this);
138 }
139 
videoWidth() const140 unsigned HTMLVideoElement::videoWidth() const
141 {
142     if (!player())
143         return 0;
144     return player()->naturalSize().width();
145 }
146 
videoHeight() const147 unsigned HTMLVideoElement::videoHeight() const
148 {
149     if (!player())
150         return 0;
151     return player()->naturalSize().height();
152 }
153 
width() const154 unsigned HTMLVideoElement::width() const
155 {
156     bool ok;
157     unsigned w = getAttribute(widthAttr).string().toUInt(&ok);
158     return ok ? w : 0;
159 }
160 
height() const161 unsigned HTMLVideoElement::height() const
162 {
163     bool ok;
164     unsigned h = getAttribute(heightAttr).string().toUInt(&ok);
165     return ok ? h : 0;
166 }
167 
isURLAttribute(Attribute * attribute) const168 bool HTMLVideoElement::isURLAttribute(Attribute* attribute) const
169 {
170     return HTMLMediaElement::isURLAttribute(attribute)
171         || attribute->name() == posterAttr;
172 }
173 
imageSourceAttributeName() const174 const QualifiedName& HTMLVideoElement::imageSourceAttributeName() const
175 {
176     return posterAttr;
177 }
178 
setDisplayMode(DisplayMode mode)179 void HTMLVideoElement::setDisplayMode(DisplayMode mode)
180 {
181     DisplayMode oldMode = displayMode();
182     KURL poster = getNonEmptyURLAttribute(posterAttr);
183 
184     if (!poster.isEmpty()) {
185         // We have a poster path, but only show it until the user triggers display by playing or seeking and the
186         // media engine has something to display.
187         if (mode == Video) {
188             if (oldMode != Video && player())
189                 player()->prepareForRendering();
190             if (!hasAvailableVideoFrame())
191                 mode = PosterWaitingForVideo;
192         }
193     } else if (oldMode != Video && player())
194         player()->prepareForRendering();
195 
196     HTMLMediaElement::setDisplayMode(mode);
197 
198     if (player() && player()->canLoadPoster())
199         player()->setPoster(poster);
200 
201 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
202     if (renderer() && displayMode() != oldMode)
203         renderer()->updateFromElement();
204 #endif
205 }
206 
updateDisplayState()207 void HTMLVideoElement::updateDisplayState()
208 {
209     if (getNonEmptyURLAttribute(posterAttr).isEmpty())
210         setDisplayMode(Video);
211     else if (displayMode() < Poster)
212         setDisplayMode(Poster);
213 }
214 
paintCurrentFrameInContext(GraphicsContext * context,const IntRect & destRect)215 void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& destRect)
216 {
217     MediaPlayer* player = HTMLMediaElement::player();
218     if (!player)
219         return;
220 
221     player->setVisible(true); // Make player visible or it won't draw.
222     player->paintCurrentFrameInContext(context, destRect);
223 }
224 
hasAvailableVideoFrame() const225 bool HTMLVideoElement::hasAvailableVideoFrame() const
226 {
227     if (!player())
228         return false;
229 
230     return player()->hasAvailableVideoFrame();
231 }
232 
webkitEnterFullscreen(bool isUserGesture,ExceptionCode & ec)233 void HTMLVideoElement::webkitEnterFullscreen(bool isUserGesture, ExceptionCode& ec)
234 {
235     if (isFullscreen())
236         return;
237 
238     // Generate an exception if this isn't called in response to a user gesture, or if the
239     // element does not support fullscreen.
240     if ((requireUserGestureForFullScreen() && !isUserGesture) || !supportsFullscreen()) {
241         ec = INVALID_STATE_ERR;
242         return;
243     }
244 
245     enterFullscreen();
246 }
247 
webkitExitFullscreen()248 void HTMLVideoElement::webkitExitFullscreen()
249 {
250     if (isFullscreen())
251         exitFullscreen();
252 }
253 
webkitSupportsFullscreen()254 bool HTMLVideoElement::webkitSupportsFullscreen()
255 {
256     return supportsFullscreen();
257 }
258 
webkitDisplayingFullscreen()259 bool HTMLVideoElement::webkitDisplayingFullscreen()
260 {
261     return isFullscreen();
262 }
263 
willMoveToNewOwnerDocument()264 void HTMLVideoElement::willMoveToNewOwnerDocument()
265 {
266     if (m_imageLoader)
267         m_imageLoader->elementWillMoveToNewOwnerDocument();
268     HTMLMediaElement::willMoveToNewOwnerDocument();
269 }
270 
271 #if ENABLE(MEDIA_STATISTICS)
webkitDecodedFrameCount() const272 unsigned HTMLVideoElement::webkitDecodedFrameCount() const
273 {
274     if (!player())
275         return 0;
276 
277     return player()->decodedFrameCount();
278 }
279 
webkitDroppedFrameCount() const280 unsigned HTMLVideoElement::webkitDroppedFrameCount() const
281 {
282     if (!player())
283         return 0;
284 
285     return player()->droppedFrameCount();
286 }
287 #endif
288 
289 }
290 
291 #endif
292