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 44namespace WebCore { 45 46using namespace HTMLNames; 47 48HTMLVideoElement::HTMLVideoElement(const QualifiedName& tagName, Document* doc) 49 : HTMLMediaElement(tagName, doc) 50 , m_shouldDisplayPosterImage(false) 51{ 52 ASSERT(hasTagName(videoTag)); 53} 54 55bool HTMLVideoElement::rendererIsNeeded(RenderStyle* style) 56{ 57 return HTMLElement::rendererIsNeeded(style); 58} 59 60#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO) 61RenderObject* HTMLVideoElement::createRenderer(RenderArena* arena, RenderStyle*) 62{ 63 return new (arena) RenderVideo(this); 64} 65#endif 66 67void 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 85void HTMLVideoElement::detach() 86{ 87 HTMLMediaElement::detach(); 88 89 if (!m_shouldDisplayPosterImage) 90 if (m_imageLoader) 91 m_imageLoader.clear(); 92} 93 94void 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 119bool 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 132unsigned HTMLVideoElement::videoWidth() const 133{ 134 if (!m_player) 135 return 0; 136 return m_player->naturalSize().width(); 137} 138 139unsigned HTMLVideoElement::videoHeight() const 140{ 141 if (!m_player) 142 return 0; 143 return m_player->naturalSize().height(); 144} 145 146unsigned HTMLVideoElement::width() const 147{ 148 bool ok; 149 unsigned w = getAttribute(widthAttr).string().toUInt(&ok); 150 return ok ? w : 0; 151} 152 153void HTMLVideoElement::setWidth(unsigned value) 154{ 155 setAttribute(widthAttr, String::number(value)); 156} 157 158unsigned HTMLVideoElement::height() const 159{ 160 bool ok; 161 unsigned h = getAttribute(heightAttr).string().toUInt(&ok); 162 return ok ? h : 0; 163} 164 165void HTMLVideoElement::setHeight(unsigned value) 166{ 167 setAttribute(heightAttr, String::number(value)); 168} 169 170void HTMLVideoElement::setPoster(const String& value) 171{ 172 setAttribute(posterAttr, value); 173} 174 175bool HTMLVideoElement::isURLAttribute(Attribute* attr) const 176{ 177 return attr->name() == posterAttr; 178} 179 180const QualifiedName& HTMLVideoElement::imageSourceAttributeName() const 181{ 182 return posterAttr; 183} 184 185void 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 199void 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 209void 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 219bool HTMLVideoElement::hasAvailableVideoFrame() const 220{ 221 if (!m_player) 222 return false; 223 224 return m_player->hasAvailableVideoFrame(); 225} 226 227void 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 242void HTMLVideoElement::webkitExitFullScreen() 243{ 244 if (m_isFullscreen) 245 exitFullscreen(); 246} 247 248bool HTMLVideoElement::webkitSupportsFullscreen() 249{ 250 return supportsFullscreen(); 251} 252 253bool HTMLVideoElement::webkitDisplayingFullscreen() 254{ 255 return m_isFullscreen; 256} 257 258 259} 260#endif 261