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 "Chrome.h"
32 #include "ChromeClient.h"
33 #include "CSSHelper.h"
34 #include "CSSPropertyNames.h"
35 #include "Document.h"
36 #include "ExceptionCode.h"
37 #include "HTMLImageLoader.h"
38 #include "HTMLNames.h"
39 #include "MappedAttribute.h"
40 #include "Page.h"
41 #include "RenderImage.h"
42 #include "RenderVideo.h"
43
44 namespace WebCore {
45
46 using namespace HTMLNames;
47
HTMLVideoElement(const QualifiedName & tagName,Document * doc)48 HTMLVideoElement::HTMLVideoElement(const QualifiedName& tagName, Document* doc)
49 : HTMLMediaElement(tagName, doc)
50 , m_shouldDisplayPosterImage(false)
51 {
52 ASSERT(hasTagName(videoTag));
53 }
54
rendererIsNeeded(RenderStyle * style)55 bool HTMLVideoElement::rendererIsNeeded(RenderStyle* style)
56 {
57 return HTMLElement::rendererIsNeeded(style);
58 }
59
60 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
createRenderer(RenderArena * arena,RenderStyle *)61 RenderObject* HTMLVideoElement::createRenderer(RenderArena* arena, RenderStyle*)
62 {
63 return new (arena) RenderVideo(this);
64 }
65 #endif
66
attach()67 void HTMLVideoElement::attach()
68 {
69 HTMLMediaElement::attach();
70
71 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
72 updatePosterImage();
73 if (m_shouldDisplayPosterImage) {
74 if (!m_imageLoader)
75 m_imageLoader.set(new HTMLImageLoader(this));
76 m_imageLoader->updateFromElement();
77 if (renderer()) {
78 RenderImage* imageRenderer = toRenderImage(renderer());
79 imageRenderer->setCachedImage(m_imageLoader->image());
80 }
81 }
82 #endif
83 }
84
detach()85 void HTMLVideoElement::detach()
86 {
87 HTMLMediaElement::detach();
88
89 if (!m_shouldDisplayPosterImage)
90 if (m_imageLoader)
91 m_imageLoader.clear();
92 }
93
parseMappedAttribute(MappedAttribute * attr)94 void HTMLVideoElement::parseMappedAttribute(MappedAttribute* attr)
95 {
96 const QualifiedName& attrName = attr->name();
97
98 if (attrName == posterAttr) {
99 m_posterURL = document()->completeURL(attr->value());
100 updatePosterImage();
101 if (m_shouldDisplayPosterImage) {
102 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
103 if (!m_imageLoader)
104 m_imageLoader.set(new HTMLImageLoader(this));
105 m_imageLoader->updateFromElementIgnoringPreviousError();
106 #else
107 if (m_player)
108 m_player->setPoster(poster());
109 #endif
110 }
111 } else if (attrName == widthAttr)
112 addCSSLength(attr, CSSPropertyWidth, attr->value());
113 else if (attrName == heightAttr)
114 addCSSLength(attr, CSSPropertyHeight, attr->value());
115 else
116 HTMLMediaElement::parseMappedAttribute(attr);
117 }
118
supportsFullscreen() const119 bool HTMLVideoElement::supportsFullscreen() const
120 {
121 Page* page = document() ? document()->page() : 0;
122 if (!page)
123 return false;
124
125 if (!m_player || !m_player->supportsFullscreen() || !m_player->hasVideo())
126 return false;
127
128 // Check with the platform client.
129 return page->chrome()->client()->supportsFullscreenForNode(this);
130 }
131
videoWidth() const132 unsigned HTMLVideoElement::videoWidth() const
133 {
134 if (!m_player)
135 return 0;
136 return m_player->naturalSize().width();
137 }
138
videoHeight() const139 unsigned HTMLVideoElement::videoHeight() const
140 {
141 if (!m_player)
142 return 0;
143 return m_player->naturalSize().height();
144 }
145
width() const146 unsigned HTMLVideoElement::width() const
147 {
148 bool ok;
149 unsigned w = getAttribute(widthAttr).string().toUInt(&ok);
150 return ok ? w : 0;
151 }
152
setWidth(unsigned value)153 void HTMLVideoElement::setWidth(unsigned value)
154 {
155 setAttribute(widthAttr, String::number(value));
156 }
157
height() const158 unsigned HTMLVideoElement::height() const
159 {
160 bool ok;
161 unsigned h = getAttribute(heightAttr).string().toUInt(&ok);
162 return ok ? h : 0;
163 }
164
setHeight(unsigned value)165 void HTMLVideoElement::setHeight(unsigned value)
166 {
167 setAttribute(heightAttr, String::number(value));
168 }
169
setPoster(const String & value)170 void HTMLVideoElement::setPoster(const String& value)
171 {
172 setAttribute(posterAttr, value);
173 }
174
isURLAttribute(Attribute * attr) const175 bool HTMLVideoElement::isURLAttribute(Attribute* attr) const
176 {
177 return attr->name() == posterAttr;
178 }
179
imageSourceAttributeName() const180 const QualifiedName& HTMLVideoElement::imageSourceAttributeName() const
181 {
182 return posterAttr;
183 }
184
updatePosterImage()185 void HTMLVideoElement::updatePosterImage()
186 {
187 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
188 bool oldShouldShowPosterImage = m_shouldDisplayPosterImage;
189 #endif
190
191 m_shouldDisplayPosterImage = !poster().isEmpty() && !hasAvailableVideoFrame();
192
193 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
194 if (renderer() && oldShouldShowPosterImage != m_shouldDisplayPosterImage)
195 renderer()->updateFromElement();
196 #endif
197 }
198
paint(GraphicsContext * context,const IntRect & destRect)199 void HTMLVideoElement::paint(GraphicsContext* context, const IntRect& destRect)
200 {
201 MediaPlayer* player = HTMLMediaElement::player();
202 if (!player)
203 return;
204
205 player->setVisible(true); // Make player visible or it won't draw.
206 player->paint(context, destRect);
207 }
208
paintCurrentFrameInContext(GraphicsContext * context,const IntRect & destRect)209 void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& destRect)
210 {
211 MediaPlayer* player = HTMLMediaElement::player();
212 if (!player)
213 return;
214
215 player->setVisible(true); // Make player visible or it won't draw.
216 player->paintCurrentFrameInContext(context, destRect);
217 }
218
hasAvailableVideoFrame() const219 bool HTMLVideoElement::hasAvailableVideoFrame() const
220 {
221 if (!m_player)
222 return false;
223
224 return m_player->hasAvailableVideoFrame();
225 }
226
webkitEnterFullScreen(bool isUserGesture,ExceptionCode & ec)227 void HTMLVideoElement::webkitEnterFullScreen(bool isUserGesture, ExceptionCode& ec)
228 {
229 if (m_isFullscreen)
230 return;
231
232 // Generate an exception if this isn't called in response to a user gesture, or if the
233 // element does not support fullscreen.
234 if (!isUserGesture || !supportsFullscreen()) {
235 ec = INVALID_STATE_ERR;
236 return;
237 }
238
239 enterFullscreen();
240 }
241
webkitExitFullScreen()242 void HTMLVideoElement::webkitExitFullScreen()
243 {
244 if (m_isFullscreen)
245 exitFullscreen();
246 }
247
webkitSupportsFullscreen()248 bool HTMLVideoElement::webkitSupportsFullscreen()
249 {
250 return supportsFullscreen();
251 }
252
webkitDisplayingFullscreen()253 bool HTMLVideoElement::webkitDisplayingFullscreen()
254 {
255 return m_isFullscreen;
256 }
257
258
259 }
260 #endif
261