summaryrefslogtreecommitdiffstats
path: root/WebCore/html
diff options
context:
space:
mode:
authorFeng Qian <>2009-04-10 18:11:29 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-04-10 18:11:29 -0700
commit8f72e70a9fd78eec56623b3a62e68f16b7b27e28 (patch)
tree181bf9a400c30a1bf34ea6d72560e8d00111d549 /WebCore/html
parent7ed56f225e0ade046e1c2178977f72b2d896f196 (diff)
downloadexternal_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.zip
external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.gz
external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.bz2
AI 145796: Land the WebKit merge @r42026.
Automated import of CL 145796
Diffstat (limited to 'WebCore/html')
-rw-r--r--WebCore/html/CanvasGradient.cpp5
-rw-r--r--WebCore/html/CanvasGradient.h5
-rw-r--r--WebCore/html/CanvasRenderingContext2D.cpp26
-rw-r--r--WebCore/html/CanvasRenderingContext2D.h3
-rw-r--r--WebCore/html/CanvasStyle.cpp19
-rw-r--r--WebCore/html/HTMLAnchorElement.cpp21
-rw-r--r--WebCore/html/HTMLAppletElement.cpp13
-rw-r--r--WebCore/html/HTMLAreaElement.cpp31
-rw-r--r--WebCore/html/HTMLAreaElement.h27
-rw-r--r--WebCore/html/HTMLCanvasElement.cpp2
-rw-r--r--WebCore/html/HTMLCanvasElement.idl2
-rw-r--r--WebCore/html/HTMLDocument.cpp8
-rw-r--r--WebCore/html/HTMLDocument.h1
-rw-r--r--WebCore/html/HTMLElement.cpp31
-rw-r--r--WebCore/html/HTMLElement.h2
-rw-r--r--WebCore/html/HTMLElementFactory.cpp510
-rw-r--r--WebCore/html/HTMLElementFactory.h47
-rw-r--r--WebCore/html/HTMLEmbedElement.cpp4
-rw-r--r--WebCore/html/HTMLFormControlElement.cpp7
-rw-r--r--WebCore/html/HTMLFormControlElement.h2
-rw-r--r--WebCore/html/HTMLFormElement.cpp22
-rw-r--r--WebCore/html/HTMLImageElement.cpp4
-rw-r--r--WebCore/html/HTMLImageLoader.cpp5
-rw-r--r--WebCore/html/HTMLInputElement.cpp103
-rw-r--r--WebCore/html/HTMLInputElement.h9
-rw-r--r--WebCore/html/HTMLInputElement.idl8
-rw-r--r--WebCore/html/HTMLLegendElement.cpp9
-rw-r--r--WebCore/html/HTMLLegendElement.h1
-rw-r--r--WebCore/html/HTMLMediaElement.cpp1282
-rw-r--r--WebCore/html/HTMLMediaElement.h184
-rw-r--r--WebCore/html/HTMLMediaElement.idl44
-rw-r--r--WebCore/html/HTMLObjectElement.cpp11
-rw-r--r--WebCore/html/HTMLOptGroupElement.cpp10
-rw-r--r--WebCore/html/HTMLOptionElement.cpp11
-rw-r--r--WebCore/html/HTMLOptionElement.h2
-rw-r--r--WebCore/html/HTMLParser.cpp374
-rw-r--r--WebCore/html/HTMLParser.h23
-rw-r--r--WebCore/html/HTMLQuoteElement.cpp8
-rw-r--r--WebCore/html/HTMLQuoteElement.h2
-rw-r--r--WebCore/html/HTMLSelectElement.cpp109
-rw-r--r--WebCore/html/HTMLSelectElement.h5
-rw-r--r--WebCore/html/HTMLSourceElement.cpp2
-rw-r--r--WebCore/html/HTMLTagNames.in2
-rw-r--r--WebCore/html/HTMLTextAreaElement.cpp31
-rw-r--r--WebCore/html/HTMLTextAreaElement.h4
-rw-r--r--WebCore/html/HTMLTokenizer.cpp30
-rw-r--r--WebCore/html/HTMLTokenizer.h2
-rw-r--r--WebCore/html/HTMLVideoElement.cpp22
-rw-r--r--WebCore/html/HTMLVideoElement.h3
-rw-r--r--WebCore/html/HTMLViewSourceDocument.cpp14
-rw-r--r--WebCore/html/MediaError.h2
-rw-r--r--WebCore/html/MediaError.idl1
-rw-r--r--WebCore/html/PreloadScanner.cpp7
53 files changed, 1528 insertions, 1584 deletions
diff --git a/WebCore/html/CanvasGradient.cpp b/WebCore/html/CanvasGradient.cpp
index 693d8f7..fd48194 100644
--- a/WebCore/html/CanvasGradient.cpp
+++ b/WebCore/html/CanvasGradient.cpp
@@ -34,11 +34,13 @@ namespace WebCore {
CanvasGradient::CanvasGradient(const FloatPoint& p0, const FloatPoint& p1)
: m_gradient(Gradient::create(p0, p1))
+ , m_dashbardCompatibilityMode(false)
{
}
CanvasGradient::CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1)
: m_gradient(Gradient::create(p0, r0, p1, r1))
+ , m_dashbardCompatibilityMode(false)
{
}
@@ -51,7 +53,8 @@ void CanvasGradient::addColorStop(float value, const String& color, ExceptionCod
RGBA32 rgba = 0;
if (!CSSParser::parseColor(rgba, color)) {
- ec = SYNTAX_ERR;
+ if (!m_dashbardCompatibilityMode)
+ ec = SYNTAX_ERR;
return;
}
diff --git a/WebCore/html/CanvasGradient.h b/WebCore/html/CanvasGradient.h
index 3b81dbd..0a77652 100644
--- a/WebCore/html/CanvasGradient.h
+++ b/WebCore/html/CanvasGradient.h
@@ -54,11 +54,16 @@ namespace WebCore {
void getColor(float value, float* r, float* g, float* b, float* a) const { m_gradient->getColor(value, r, g, b, a); }
+#if ENABLE(DASHBOARD_SUPPORT)
+ void setDashboardCompatibilityMode() { m_dashbardCompatibilityMode = true; }
+#endif
+
private:
CanvasGradient(const FloatPoint& p0, const FloatPoint& p1);
CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1);
RefPtr<Gradient> m_gradient;
+ bool m_dashbardCompatibilityMode;
};
} //namespace
diff --git a/WebCore/html/CanvasRenderingContext2D.cpp b/WebCore/html/CanvasRenderingContext2D.cpp
index 373301a..82680bd 100644
--- a/WebCore/html/CanvasRenderingContext2D.cpp
+++ b/WebCore/html/CanvasRenderingContext2D.cpp
@@ -357,7 +357,7 @@ void CanvasRenderingContext2D::scale(float sx, float sy)
return;
TransformationMatrix newTransform = state().m_transform;
- newTransform.scale(sx, sy);
+ newTransform.scaleNonUniform(sx, sy);
if (!newTransform.isInvertible()) {
state().m_invertibleCTM = false;
return;
@@ -365,7 +365,7 @@ void CanvasRenderingContext2D::scale(float sx, float sy)
state().m_transform = newTransform;
c->scale(FloatSize(sx, sy));
- m_path.transform(TransformationMatrix().scale(1.0/sx, 1.0/sy));
+ m_path.transform(TransformationMatrix().scaleNonUniform(1.0/sx, 1.0/sy));
}
void CanvasRenderingContext2D::rotate(float angleInRadians)
@@ -867,7 +867,6 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur,
GraphicsContext* dc = drawingContext();
if (!dc)
return;
- // FIXME: Do this through platform-independent GraphicsContext API.
#if PLATFORM(CG)
const CGFloat components[5] = { c, m, y, k, a };
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceCMYK();
@@ -875,6 +874,8 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur,
CGColorSpaceRelease(colorSpace);
CGContextSetShadowWithColor(dc->platformContext(), adjustedShadowSize(width, -height), blur, shadowColor);
CGColorRelease(shadowColor);
+#else
+ dc->setShadow(IntSize(width, -height), blur, Color(c, m, y, k, a));
#endif
}
@@ -1078,6 +1079,15 @@ void CanvasRenderingContext2D::setCompositeOperation(const String& operation)
setGlobalCompositeOperation(operation);
}
+void CanvasRenderingContext2D::prepareGradientForDashboard(CanvasGradient* gradient) const
+{
+#if ENABLE(DASHBOARD_SUPPORT)
+ if (Settings* settings = m_canvas->document()->settings())
+ if (settings->usesDashboardBackwardCompatibilityMode())
+ gradient->setDashboardCompatibilityMode();
+#endif
+}
+
PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1, ExceptionCode& ec)
{
if (!isfinite(x0) || !isfinite(y0) || !isfinite(x1) || !isfinite(y1)) {
@@ -1085,7 +1095,9 @@ PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float
return 0;
}
- return CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1));
+ PassRefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1));
+ prepareGradientForDashboard(gradient.get());
+ return gradient;
}
PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionCode& ec)
@@ -1095,7 +1107,9 @@ PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float
ec = NOT_SUPPORTED_ERR;
return 0;
}
- return CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1);
+ PassRefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1);
+ prepareGradientForDashboard(gradient.get());
+ return gradient;
}
PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElement* image,
@@ -1422,6 +1436,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo
m_canvas->willDraw(FloatRect(0, 0, m_canvas->width(), m_canvas->height()));
}
+#if PLATFORM(CG)
CanvasStyle* drawStyle = fill ? state().m_fillStyle.get() : state().m_strokeStyle.get();
if (drawStyle->canvasGradient() || drawStyle->canvasPattern()) {
// FIXME: The rect is not big enough for miters on stroked text.
@@ -1451,6 +1466,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo
return;
}
+#endif
c->setTextDrawingMode(fill ? cTextFill : cTextStroke);
c->drawBidiText(font, textRun, location);
diff --git a/WebCore/html/CanvasRenderingContext2D.h b/WebCore/html/CanvasRenderingContext2D.h
index 8d05b92..d74659e 100644
--- a/WebCore/html/CanvasRenderingContext2D.h
+++ b/WebCore/html/CanvasRenderingContext2D.h
@@ -251,7 +251,8 @@ namespace WebCore {
#if ENABLE(DASHBOARD_SUPPORT)
void clearPathForDashboardBackwardCompatibilityMode();
#endif
-
+
+ void prepareGradientForDashboard(CanvasGradient* gradient) const;
void checkOrigin(const KURL&);
HTMLCanvasElement* m_canvas;
diff --git a/WebCore/html/CanvasStyle.cpp b/WebCore/html/CanvasStyle.cpp
index d82643f..0aaaab2 100644
--- a/WebCore/html/CanvasStyle.cpp
+++ b/WebCore/html/CanvasStyle.cpp
@@ -78,12 +78,21 @@ CanvasStyle::CanvasStyle(float grayLevel, float alpha)
}
CanvasStyle::CanvasStyle(float r, float g, float b, float a)
- : m_type(RGBA), m_alpha(a), m_red(r), m_green(g), m_blue(b)
+ : m_type(RGBA)
+ , m_alpha(a)
+ , m_red(r)
+ , m_green(g)
+ , m_blue(b)
{
}
CanvasStyle::CanvasStyle(float c, float m, float y, float k, float a)
- : m_type(CMYKA), m_alpha(a), m_cyan(c), m_magenta(m), m_yellow(y), m_black(k)
+ : m_type(CMYKA)
+ , m_alpha(a)
+ , m_cyan(c)
+ , m_magenta(m)
+ , m_yellow(y)
+ , m_black(k)
{
}
@@ -146,10 +155,10 @@ void CanvasStyle::applyStrokeColor(GraphicsContext* context)
clr.setCmykF(m_cyan, m_magenta, m_yellow, m_black, m_alpha);
currentPen.setColor(clr);
context->platformContext()->setPen(currentPen);
-#elif PLATFORM(CAIRO)
- notImplemented();
#elif PLATFORM(SGL)
context->setCMYKAStrokeColor(m_cyan, m_magenta, m_yellow, m_black, m_alpha);
+#else
+ context->setStrokeColor(Color(m_cyan, m_magenta, m_yellow, m_black, m_alpha));
#endif
break;
}
@@ -211,6 +220,8 @@ void CanvasStyle::applyFillColor(GraphicsContext* context)
context->platformContext()->setBrush(currentBrush);
#elif PLATFORM(SGL)
context->setCMYKAFillColor(m_cyan, m_magenta, m_yellow, m_black, m_alpha);
+#else
+ context->setFillColor(Color(m_cyan, m_magenta, m_yellow, m_black, m_alpha));
#endif
break;
}
diff --git a/WebCore/html/HTMLAnchorElement.cpp b/WebCore/html/HTMLAnchorElement.cpp
index 4122168..c6b2a95 100644
--- a/WebCore/html/HTMLAnchorElement.cpp
+++ b/WebCore/html/HTMLAnchorElement.cpp
@@ -38,7 +38,8 @@
#include "KeyboardEvent.h"
#include "MouseEvent.h"
#include "MutationEvent.h"
-#include "RenderFlow.h"
+#include "Page.h"
+#include "RenderBox.h"
#include "RenderImage.h"
#include "ResourceRequest.h"
#include "SelectionController.h"
@@ -107,18 +108,14 @@ bool HTMLAnchorElement::isKeyboardFocusable(KeyboardEvent* event) const
if (!document()->frame()->eventHandler()->tabsToLinks(event))
return false;
- if (!renderer() || !renderer()->isBox())
+ if (!renderer() || !renderer()->isBoxModelObject())
return false;
// Before calling absoluteRects, check for the common case where the renderer
- // or one of the continuations is non-empty, since this is a faster check and
- // almost always returns true.
- RenderBox* box = toRenderBox(renderer());
+ // is non-empty, since this is a faster check and almost always returns true.
+ RenderBoxModelObject* box = toRenderBoxModelObject(renderer());
if (!box->borderBoundingBox().isEmpty())
return true;
- for (RenderFlow* r = box->virtualContinuation(); r; r = r->continuation())
- if (!r->borderBoundingBox().isEmpty())
- return true;
Vector<IntRect> rects;
FloatPoint absPos = renderer()->localToAbsolute();
@@ -203,7 +200,7 @@ void HTMLAnchorElement::defaultEventHandler(Event* evt)
if (evt->target()->toNode()->hasTagName(imgTag)) {
HTMLImageElement* img = static_cast<HTMLImageElement*>(evt->target()->toNode());
if (img && img->isServerMap()) {
- RenderImage* r = static_cast<RenderImage*>(img->renderer());
+ RenderImage* r = toRenderImage(img->renderer());
if (r && e) {
// FIXME: broken with transforms
FloatPoint absPos = r->localToAbsolute();
@@ -434,7 +431,8 @@ void HTMLAnchorElement::setType(const AtomicString& value)
String HTMLAnchorElement::hash() const
{
- return "#" + href().ref();
+ String ref = href().ref();
+ return ref.isEmpty() ? "" : "#" + ref;
}
String HTMLAnchorElement::host() const
@@ -467,7 +465,8 @@ String HTMLAnchorElement::protocol() const
String HTMLAnchorElement::search() const
{
- return href().query();
+ String query = href().query();
+ return query.isEmpty() ? "" : "?" + query;
}
String HTMLAnchorElement::text() const
diff --git a/WebCore/html/HTMLAppletElement.cpp b/WebCore/html/HTMLAppletElement.cpp
index 9d7ab6a..de8e1cf 100644
--- a/WebCore/html/HTMLAppletElement.cpp
+++ b/WebCore/html/HTMLAppletElement.cpp
@@ -99,9 +99,12 @@ void HTMLAppletElement::removedFromDocument()
HTMLPlugInElement::removedFromDocument();
}
-bool HTMLAppletElement::rendererIsNeeded(RenderStyle*)
+bool HTMLAppletElement::rendererIsNeeded(RenderStyle* style)
{
- return !getAttribute(codeAttr).isNull();
+ if (getAttribute(codeAttr).isNull())
+ return false;
+
+ return HTMLPlugInElement::rendererIsNeeded(style);
}
RenderObject* HTMLAppletElement::createRenderer(RenderArena*, RenderStyle* style)
@@ -112,9 +115,13 @@ RenderObject* HTMLAppletElement::createRenderer(RenderArena*, RenderStyle* style
HashMap<String, String> args;
args.set("code", getAttribute(codeAttr));
+
const AtomicString& codeBase = getAttribute(codebaseAttr);
- if(!codeBase.isNull())
+ if (!codeBase.isNull())
args.set("codeBase", codeBase);
+ else
+ args.set("codeBase", document()->baseURL().baseAsString());
+
const AtomicString& name = getAttribute(document()->isHTMLDocument() ? nameAttr : idAttr);
if (!name.isNull())
args.set("name", name);
diff --git a/WebCore/html/HTMLAreaElement.cpp b/WebCore/html/HTMLAreaElement.cpp
index 7a3c9e0..9db50b7 100644
--- a/WebCore/html/HTMLAreaElement.cpp
+++ b/WebCore/html/HTMLAreaElement.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,6 +27,7 @@
#include "HTMLNames.h"
#include "HitTestResult.h"
#include "Length.h"
+#include "Path.h"
#include "RenderObject.h"
using namespace std;
@@ -35,8 +36,8 @@ namespace WebCore {
using namespace HTMLNames;
-HTMLAreaElement::HTMLAreaElement(const QualifiedName& tagName, Document *doc)
- : HTMLAnchorElement(tagName, doc)
+HTMLAreaElement::HTMLAreaElement(const QualifiedName& tagName, Document* document)
+ : HTMLAnchorElement(tagName, document)
, m_coords(0)
, m_coordsLen(0)
, m_lastSize(-1, -1)
@@ -73,11 +74,11 @@ void HTMLAreaElement::parseMappedAttribute(MappedAttribute *attr)
bool HTMLAreaElement::mapMouseEvent(int x, int y, const IntSize& size, HitTestResult& result)
{
if (m_lastSize != size) {
- region = getRegion(size);
+ m_region.set(new Path(getRegion(size)));
m_lastSize = size;
}
- if (!region.contains(IntPoint(x, y)))
+ if (!m_region->contains(IntPoint(x, y)))
return false;
result.setInnerNode(this);
@@ -150,32 +151,32 @@ Path HTMLAreaElement::getRegion(const IntSize& size) const
return path;
}
-String HTMLAreaElement::accessKey() const
+const AtomicString& HTMLAreaElement::accessKey() const
{
return getAttribute(accesskeyAttr);
}
-void HTMLAreaElement::setAccessKey(const String& value)
+void HTMLAreaElement::setAccessKey(const AtomicString& value)
{
setAttribute(accesskeyAttr, value);
}
-String HTMLAreaElement::alt() const
+const AtomicString& HTMLAreaElement::alt() const
{
return getAttribute(altAttr);
}
-void HTMLAreaElement::setAlt(const String& value)
+void HTMLAreaElement::setAlt(const AtomicString& value)
{
setAttribute(altAttr, value);
}
-String HTMLAreaElement::coords() const
+const AtomicString& HTMLAreaElement::coords() const
{
return getAttribute(coordsAttr);
}
-void HTMLAreaElement::setCoords(const String& value)
+void HTMLAreaElement::setCoords(const AtomicString& value)
{
setAttribute(coordsAttr, value);
}
@@ -185,7 +186,7 @@ KURL HTMLAreaElement::href() const
return document()->completeURL(getAttribute(hrefAttr));
}
-void HTMLAreaElement::setHref(const String& value)
+void HTMLAreaElement::setHref(const AtomicString& value)
{
setAttribute(hrefAttr, value);
}
@@ -200,12 +201,12 @@ void HTMLAreaElement::setNoHref(bool noHref)
setAttribute(nohrefAttr, noHref ? "" : 0);
}
-String HTMLAreaElement::shape() const
+const AtomicString& HTMLAreaElement::shape() const
{
return getAttribute(shapeAttr);
}
-void HTMLAreaElement::setShape(const String& value)
+void HTMLAreaElement::setShape(const AtomicString& value)
{
setAttribute(shapeAttr, value);
}
@@ -220,7 +221,7 @@ String HTMLAreaElement::target() const
return getAttribute(targetAttr);
}
-void HTMLAreaElement::setTarget(const String& value)
+void HTMLAreaElement::setTarget(const AtomicString& value)
{
setAttribute(targetAttr, value);
}
diff --git a/WebCore/html/HTMLAreaElement.h b/WebCore/html/HTMLAreaElement.h
index 7de5832..19533b1 100644
--- a/WebCore/html/HTMLAreaElement.h
+++ b/WebCore/html/HTMLAreaElement.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -25,11 +25,11 @@
#include "HTMLAnchorElement.h"
#include "IntSize.h"
-#include "Path.h"
namespace WebCore {
class HitTestResult;
+class Path;
class HTMLAreaElement : public HTMLAnchorElement {
public:
@@ -47,33 +47,34 @@ public:
virtual IntRect getRect(RenderObject*) const;
- String accessKey() const;
- void setAccessKey(const String&);
+ const AtomicString& accessKey() const;
+ void setAccessKey(const AtomicString&);
- String alt() const;
- void setAlt(const String&);
+ const AtomicString& alt() const;
+ void setAlt(const AtomicString&);
- String coords() const;
- void setCoords(const String&);
+ const AtomicString& coords() const;
+ void setCoords(const AtomicString&);
KURL href() const;
- void setHref(const String&);
+ void setHref(const AtomicString&);
bool noHref() const;
void setNoHref(bool);
- String shape() const;
- void setShape(const String&);
+ const AtomicString& shape() const;
+ void setShape(const AtomicString&);
virtual bool isFocusable() const;
virtual String target() const;
- void setTarget(const String&);
+ void setTarget(const AtomicString&);
private:
enum Shape { Default, Poly, Rect, Circle, Unknown };
Path getRegion(const IntSize&) const;
- Path region;
+
+ OwnPtr<Path> m_region;
Length* m_coords;
int m_coordsLen;
IntSize m_lastSize;
diff --git a/WebCore/html/HTMLCanvasElement.cpp b/WebCore/html/HTMLCanvasElement.cpp
index 7481d96..1cd2796 100644
--- a/WebCore/html/HTMLCanvasElement.cpp
+++ b/WebCore/html/HTMLCanvasElement.cpp
@@ -280,7 +280,7 @@ TransformationMatrix HTMLCanvasElement::baseTransform() const
IntSize size = convertLogicalToDevice(unscaledSize);
TransformationMatrix transform;
if (size.width() && size.height())
- transform.scale(size.width() / unscaledSize.width(), size.height() / unscaledSize.height());
+ transform.scaleNonUniform(size.width() / unscaledSize.width(), size.height() / unscaledSize.height());
transform.multiply(m_imageBuffer->baseTransform());
return transform;
}
diff --git a/WebCore/html/HTMLCanvasElement.idl b/WebCore/html/HTMLCanvasElement.idl
index e457c15..bf69ac0 100644
--- a/WebCore/html/HTMLCanvasElement.idl
+++ b/WebCore/html/HTMLCanvasElement.idl
@@ -38,7 +38,7 @@ module html {
raises(DOMException);
#if !defined(LANGUAGE_OBJECTIVE_C)
- DOMObject getContext(in DOMString contextId);
+ [V8Custom] DOMObject getContext(in DOMString contextId);
#endif
};
diff --git a/WebCore/html/HTMLDocument.cpp b/WebCore/html/HTMLDocument.cpp
index a987c76..01f151c 100644
--- a/WebCore/html/HTMLDocument.cpp
+++ b/WebCore/html/HTMLDocument.cpp
@@ -433,5 +433,11 @@ void HTMLDocument::clear()
// We've long had a comment saying that IE doesn't support this.
// But I do see it in the documentation for Mozilla.
}
-
+
+bool HTMLDocument::isFrameSet() const
+{
+ HTMLElement* bodyElement = body();
+ return bodyElement && bodyElement->renderer() && bodyElement->hasTagName(framesetTag);
+}
+
}
diff --git a/WebCore/html/HTMLDocument.h b/WebCore/html/HTMLDocument.h
index de84c70..ab5da50 100644
--- a/WebCore/html/HTMLDocument.h
+++ b/WebCore/html/HTMLDocument.h
@@ -88,6 +88,7 @@ protected:
private:
virtual bool isHTMLDocument() const { return true; }
+ virtual bool isFrameSet() const;
virtual Tokenizer* createTokenizer();
virtual void determineParseMode();
diff --git a/WebCore/html/HTMLElement.cpp b/WebCore/html/HTMLElement.cpp
index 4394bc8..906f847 100644
--- a/WebCore/html/HTMLElement.cpp
+++ b/WebCore/html/HTMLElement.cpp
@@ -96,23 +96,6 @@ int HTMLElement::tagPriority() const
return 1;
}
-PassRefPtr<Node> HTMLElement::cloneNode(bool deep)
-{
- RefPtr<HTMLElement> clone = HTMLElementFactory::createHTMLElement(tagQName(), document(), 0, false);
- if (!clone)
- return 0;
-
- if (namedAttrMap)
- clone->attributes()->setAttributes(*namedAttrMap);
-
- clone->copyNonAttributeProperties(this);
-
- if (deep)
- cloneChildNodes(clone.get());
-
- return clone.release();
-}
-
bool HTMLElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
{
if (attrName == alignAttr ||
@@ -947,8 +930,18 @@ bool HTMLElement::inEitherTagList(const Node* newChild)
if (newChild->isHTMLElement()) {
const HTMLElement* child = static_cast<const HTMLElement*>(newChild);
- if (inlineTagList()->contains(child->tagQName().localName().impl()))
+ if (inlineTagList()->contains(child->tagQName().localName().impl())) {
+#if PLATFORM(MAC)
+ if (child->tagQName().localName() == styleTag) {
+ // Leopard Mail doesn't expect <style> to be in the body of the document, so don't allow it in that case.
+ // See <rdar://problem/6621310>
+ Settings* settings = newChild->document() ? newChild->document()->settings() : 0;
+ if (settings && settings->needsLeopardMailQuirks())
+ return false;
+ }
+#endif
return true;
+ }
if (blockTagList()->contains(child->tagQName().localName().impl()))
return true;
return !isRecognizedTagName(child->tagQName()); // Accept custom html tags
@@ -999,7 +992,7 @@ bool HTMLElement::rendererIsNeeded(RenderStyle *style)
if (settings && settings->isJavaScriptEnabled())
return false;
}
- return (document()->documentElement() == this) || (style->display() != NONE);
+ return StyledElement::rendererIsNeeded(style);
}
RenderObject* HTMLElement::createRenderer(RenderArena* arena, RenderStyle* style)
diff --git a/WebCore/html/HTMLElement.h b/WebCore/html/HTMLElement.h
index 3d84e8b..60152cd 100644
--- a/WebCore/html/HTMLElement.h
+++ b/WebCore/html/HTMLElement.h
@@ -45,8 +45,6 @@ public:
virtual bool mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const;
virtual void parseMappedAttribute(MappedAttribute*);
- virtual PassRefPtr<Node> cloneNode(bool deep);
-
PassRefPtr<HTMLCollection> children();
String id() const;
diff --git a/WebCore/html/HTMLElementFactory.cpp b/WebCore/html/HTMLElementFactory.cpp
deleted file mode 100644
index 16c2b99..0000000
--- a/WebCore/html/HTMLElementFactory.cpp
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * This file is part of the HTML DOM implementation for KDE.
- *
- * Copyright (C) 2005 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "HTMLElementFactory.h"
-
-#include "HTMLAnchorElement.h"
-#include "HTMLAppletElement.h"
-#include "HTMLAreaElement.h"
-#include "HTMLAudioElement.h"
-#include "HTMLBRElement.h"
-#include "HTMLBaseElement.h"
-#include "HTMLBaseFontElement.h"
-#include "HTMLBlockquoteElement.h"
-#include "HTMLBodyElement.h"
-#include "HTMLButtonElement.h"
-#include "HTMLCanvasElement.h"
-#include "HTMLDListElement.h"
-#include "HTMLDirectoryElement.h"
-#include "HTMLDivElement.h"
-#include "HTMLDocument.h"
-#include "HTMLEmbedElement.h"
-#include "HTMLFieldSetElement.h"
-#include "HTMLFontElement.h"
-#include "HTMLFormElement.h"
-#include "HTMLFrameElement.h"
-#include "HTMLFrameSetElement.h"
-#include "HTMLHRElement.h"
-#include "HTMLHeadElement.h"
-#include "HTMLHeadingElement.h"
-#include "HTMLHtmlElement.h"
-#include "HTMLIFrameElement.h"
-#include "HTMLImageElement.h"
-#include "HTMLIsIndexElement.h"
-#include "HTMLKeygenElement.h"
-#include "HTMLLIElement.h"
-#include "HTMLLabelElement.h"
-#include "HTMLLegendElement.h"
-#include "HTMLLinkElement.h"
-#include "HTMLMapElement.h"
-#include "HTMLMarqueeElement.h"
-#include "HTMLMenuElement.h"
-#include "HTMLMetaElement.h"
-#include "HTMLModElement.h"
-#include "HTMLNames.h"
-#include "HTMLOListElement.h"
-#include "HTMLObjectElement.h"
-#include "HTMLOptGroupElement.h"
-#include "HTMLOptionElement.h"
-#include "HTMLParagraphElement.h"
-#include "HTMLParamElement.h"
-#include "HTMLPreElement.h"
-#include "HTMLQuoteElement.h"
-#include "HTMLScriptElement.h"
-#include "HTMLSelectElement.h"
-#include "HTMLSourceElement.h"
-#include "HTMLStyleElement.h"
-#include "HTMLTableCaptionElement.h"
-#include "HTMLTableCellElement.h"
-#include "HTMLTableColElement.h"
-#include "HTMLTableElement.h"
-#include "HTMLTableRowElement.h"
-#include "HTMLTableSectionElement.h"
-#include "HTMLTextAreaElement.h"
-#include "HTMLTitleElement.h"
-#include "HTMLUListElement.h"
-#include "HTMLVideoElement.h"
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-typedef PassRefPtr<HTMLElement> (*ConstructorFunc)(const QualifiedName& tagName, Document*, HTMLFormElement*, bool createdByParser);
-typedef HashMap<AtomicStringImpl*, ConstructorFunc> FunctionMap;
-static FunctionMap* gFunctionMap;
-
-static PassRefPtr<HTMLElement> htmlConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLHtmlElement(htmlTag, doc);
-}
-
-static PassRefPtr<HTMLElement> headConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLHeadElement(headTag, doc);
-}
-
-static PassRefPtr<HTMLElement> bodyConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLBodyElement(bodyTag, doc);
-}
-
-static PassRefPtr<HTMLElement> baseConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLBaseElement(baseTag, doc);
-}
-
-static PassRefPtr<HTMLElement> linkConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool createdByParser)
-{
- return new HTMLLinkElement(linkTag, doc, createdByParser);
-}
-
-static PassRefPtr<HTMLElement> metaConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLMetaElement(metaTag, doc);
-}
-
-static PassRefPtr<HTMLElement> styleConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool createdByParser)
-{
- return new HTMLStyleElement(styleTag, doc, createdByParser);
-}
-
-static PassRefPtr<HTMLElement> titleConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLTitleElement(titleTag, doc);
-}
-
-static PassRefPtr<HTMLElement> frameConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool createdByParser)
-{
- return new HTMLFrameElement(frameTag, doc, createdByParser);
-}
-
-static PassRefPtr<HTMLElement> framesetConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLFrameSetElement(framesetTag, doc);
-}
-
-static PassRefPtr<HTMLElement> iframeConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool createdByParser)
-{
- return new HTMLIFrameElement(iframeTag, doc, createdByParser);
-}
-
-static PassRefPtr<HTMLElement> formConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLFormElement(formTag, doc);
-}
-
-static PassRefPtr<HTMLElement> buttonConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLButtonElement(buttonTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> inputConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLInputElement(inputTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> isindexConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLIsIndexElement(isindexTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> fieldsetConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLFieldSetElement(fieldsetTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> keygenConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLKeygenElement(keygenTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> labelConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLLabelElement(labelTag, doc);
-}
-
-static PassRefPtr<HTMLElement> legendConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLLegendElement(legendTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> optgroupConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLOptGroupElement(optgroupTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> optionConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLOptionElement(optionTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> selectConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLSelectElement(selectTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> textareaConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLTextAreaElement(textareaTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> dlConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLDListElement(dlTag, doc);
-}
-
-static PassRefPtr<HTMLElement> ulConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLUListElement(ulTag, doc);
-}
-
-static PassRefPtr<HTMLElement> olConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLOListElement(olTag, doc);
-}
-
-static PassRefPtr<HTMLElement> dirConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLDirectoryElement(dirTag, doc);
-}
-
-static PassRefPtr<HTMLElement> menuConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLMenuElement(menuTag, doc);
-}
-
-static PassRefPtr<HTMLElement> liConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLLIElement(liTag, doc);
-}
-
-static PassRefPtr<HTMLElement> blockquoteConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLBlockquoteElement(blockquoteTag, doc);
-}
-
-static PassRefPtr<HTMLElement> divConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLDivElement(divTag, doc);
-}
-
-static PassRefPtr<HTMLElement> headingConstructor(const QualifiedName& tagName, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLHeadingElement(tagName, doc);
-}
-
-static PassRefPtr<HTMLElement> hrConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLHRElement(hrTag, doc);
-}
-
-static PassRefPtr<HTMLElement> paragraphConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLParagraphElement(pTag, doc);
-}
-
-static PassRefPtr<HTMLElement> preConstructor(const QualifiedName& tagName, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLPreElement(tagName, doc);
-}
-
-static PassRefPtr<HTMLElement> basefontConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLBaseFontElement(basefontTag, doc);
-}
-
-static PassRefPtr<HTMLElement> fontConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLFontElement(fontTag, doc);
-}
-
-static PassRefPtr<HTMLElement> modConstructor(const QualifiedName& tagName, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLModElement(tagName, doc);
-}
-
-static PassRefPtr<HTMLElement> anchorConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLAnchorElement(aTag, doc);
-}
-
-static PassRefPtr<HTMLElement> imageConstructor(const QualifiedName&, Document* doc, HTMLFormElement* form, bool)
-{
- return new HTMLImageElement(imgTag, doc, form);
-}
-
-static PassRefPtr<HTMLElement> mapConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLMapElement(mapTag, doc);
-}
-
-static PassRefPtr<HTMLElement> areaConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLAreaElement(areaTag, doc);
-}
-
-static PassRefPtr<HTMLElement> canvasConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLCanvasElement(canvasTag, doc);
-}
-
-static PassRefPtr<HTMLElement> appletConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLAppletElement(appletTag, doc);
-}
-
-static PassRefPtr<HTMLElement> embedConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLEmbedElement(embedTag, doc);
-}
-
-static PassRefPtr<HTMLElement> objectConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool createdByParser)
-{
- return new HTMLObjectElement(objectTag, doc, createdByParser);
-}
-
-static PassRefPtr<HTMLElement> paramConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLParamElement(paramTag, doc);
-}
-
-static PassRefPtr<HTMLElement> scriptConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool createdByParser)
-{
- return new HTMLScriptElement(scriptTag, doc, createdByParser);
-}
-
-static PassRefPtr<HTMLElement> tableConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLTableElement(tableTag, doc);
-}
-
-static PassRefPtr<HTMLElement> tableCaptionConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLTableCaptionElement(captionTag, doc);
-}
-
-static PassRefPtr<HTMLElement> tableColConstructor(const QualifiedName& tagName, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLTableColElement(tagName, doc);
-}
-
-static PassRefPtr<HTMLElement> tableRowConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLTableRowElement(trTag, doc);
-}
-
-static PassRefPtr<HTMLElement> tableCellConstructor(const QualifiedName& tagName, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLTableCellElement(tagName, doc);
-}
-
-static PassRefPtr<HTMLElement> tableSectionConstructor(const QualifiedName& tagName, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLTableSectionElement(tagName, doc);
-}
-
-static PassRefPtr<HTMLElement> brConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLBRElement(brTag, doc);
-}
-
-static PassRefPtr<HTMLElement> quoteConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- doc->setUsesBeforeAfterRules(true);
- return new HTMLQuoteElement(qTag, doc);
-}
-
-static PassRefPtr<HTMLElement> marqueeConstructor(const QualifiedName&, Document* doc, HTMLFormElement*, bool)
-{
- return new HTMLMarqueeElement(marqueeTag, doc);
-}
-
-#if ENABLE(VIDEO)
-static PassRefPtr<HTMLElement> audioConstructor(const QualifiedName& tagName, Document* doc, HTMLFormElement*, bool)
-{
- if (!MediaPlayer::isAvailable())
- return new HTMLElement(tagName, doc);
- return new HTMLAudioElement(audioTag, doc);
-}
-
-static PassRefPtr<HTMLElement> videoConstructor(const QualifiedName& tagName, Document* doc, HTMLFormElement*, bool)
-{
- if (!MediaPlayer::isAvailable())
- return new HTMLElement(tagName, doc);
- return new HTMLVideoElement(videoTag, doc);
-}
-
-static PassRefPtr<HTMLElement> sourceConstructor(const QualifiedName& tagName, Document* doc, HTMLFormElement*, bool)
-{
- if (!MediaPlayer::isAvailable())
- return new HTMLElement(tagName, doc);
- return new HTMLSourceElement(sourceTag, doc);
-}
-#endif
-
-static void addTag(const QualifiedName& tag, ConstructorFunc func)
-{
- gFunctionMap->set(tag.localName().impl(), func);
-}
-
-static void createFunctionMap()
-{
- // Create the table.
- gFunctionMap = new FunctionMap;
-
- // Populate it with constructor functions.
- addTag(aTag, anchorConstructor);
- addTag(appletTag, appletConstructor);
- addTag(areaTag, areaConstructor);
- addTag(baseTag, baseConstructor);
- addTag(basefontTag, basefontConstructor);
- addTag(blockquoteTag, blockquoteConstructor);
- addTag(bodyTag, bodyConstructor);
- addTag(brTag, brConstructor);
- addTag(buttonTag, buttonConstructor);
- addTag(canvasTag, canvasConstructor);
- addTag(captionTag, tableCaptionConstructor);
- addTag(colTag, tableColConstructor);
- addTag(colgroupTag, tableColConstructor);
- addTag(delTag, modConstructor);
- addTag(dirTag, dirConstructor);
- addTag(divTag, divConstructor);
- addTag(dlTag, dlConstructor);
- addTag(embedTag, embedConstructor);
- addTag(fieldsetTag, fieldsetConstructor);
- addTag(fontTag, fontConstructor);
- addTag(formTag, formConstructor);
- addTag(frameTag, frameConstructor);
- addTag(framesetTag, framesetConstructor);
- addTag(h1Tag, headingConstructor);
- addTag(h2Tag, headingConstructor);
- addTag(h3Tag, headingConstructor);
- addTag(h4Tag, headingConstructor);
- addTag(h5Tag, headingConstructor);
- addTag(h6Tag, headingConstructor);
- addTag(headTag, headConstructor);
- addTag(hrTag, hrConstructor);
- addTag(htmlTag, htmlConstructor);
- addTag(iframeTag, iframeConstructor);
- addTag(imageTag, imageConstructor);
- addTag(imgTag, imageConstructor);
- addTag(inputTag, inputConstructor);
- addTag(insTag, modConstructor);
- addTag(isindexTag, isindexConstructor);
- addTag(keygenTag, keygenConstructor);
- addTag(labelTag, labelConstructor);
- addTag(legendTag, legendConstructor);
- addTag(liTag, liConstructor);
- addTag(linkTag, linkConstructor);
- addTag(listingTag, preConstructor);
- addTag(mapTag, mapConstructor);
- addTag(marqueeTag, marqueeConstructor);
- addTag(menuTag, menuConstructor);
- addTag(metaTag, metaConstructor);
- addTag(objectTag, objectConstructor);
- addTag(olTag, olConstructor);
- addTag(optgroupTag, optgroupConstructor);
- addTag(optionTag, optionConstructor);
- addTag(pTag, paragraphConstructor);
- addTag(paramTag, paramConstructor);
- addTag(preTag, preConstructor);
- addTag(qTag, quoteConstructor);
- addTag(scriptTag, scriptConstructor);
- addTag(selectTag, selectConstructor);
- addTag(styleTag, styleConstructor);
- addTag(tableTag, tableConstructor);
- addTag(tbodyTag, tableSectionConstructor);
- addTag(tdTag, tableCellConstructor);
- addTag(textareaTag, textareaConstructor);
- addTag(tfootTag, tableSectionConstructor);
- addTag(thTag, tableCellConstructor);
- addTag(theadTag, tableSectionConstructor);
- addTag(titleTag, titleConstructor);
- addTag(trTag, tableRowConstructor);
- addTag(ulTag, ulConstructor);
- addTag(xmpTag, preConstructor);
-#if ENABLE(VIDEO)
- addTag(audioTag, audioConstructor);
- addTag(sourceTag, sourceConstructor);
- addTag(videoTag, videoConstructor);
-#endif
-}
-
-PassRefPtr<HTMLElement> HTMLElementFactory::createHTMLElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* form, bool createdByParser)
-{
- if (!doc)
- return 0; // Don't allow elements to ever be made without having a doc.
-
- if (!gFunctionMap)
- createFunctionMap();
-
- ConstructorFunc func = gFunctionMap->get(tagName.localName().impl());
- if (func)
- return func(tagName, doc, form, createdByParser);
-
- // elements with no special representation in the DOM
- return new HTMLElement(tagName, doc);
-}
-
-}
-
diff --git a/WebCore/html/HTMLElementFactory.h b/WebCore/html/HTMLElementFactory.h
deleted file mode 100644
index 539d070..0000000
--- a/WebCore/html/HTMLElementFactory.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * This file is part of the HTML DOM implementation for KDE.
- *
- * Copyright (C) 2005, 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef HTMLElementFactory_h
-#define HTMLElementFactory_h
-
-#include <wtf/Forward.h>
-
-namespace WebCore {
-
-class AtomicString;
-class Document;
-class Element;
-class HTMLElement;
-class HTMLFormElement;
-class QualifiedName;
-
-// The idea behind this class is that there will eventually be a mapping from namespace URIs to ElementFactories that can dispense elements.
-// In a compound document world, the generic createElement function (will end up being virtual) will be called.
-class HTMLElementFactory {
-public:
- PassRefPtr<Element> createElement(const QualifiedName&, Document*, bool createdByParser = true);
- static PassRefPtr<HTMLElement> createHTMLElement(const QualifiedName& tagName, Document*, HTMLFormElement* = 0, bool createdByParser = true);
-};
-
-}
-
-#endif
diff --git a/WebCore/html/HTMLEmbedElement.cpp b/WebCore/html/HTMLEmbedElement.cpp
index 1af7147..f467849 100644
--- a/WebCore/html/HTMLEmbedElement.cpp
+++ b/WebCore/html/HTMLEmbedElement.cpp
@@ -137,7 +137,7 @@ bool HTMLEmbedElement::rendererIsNeeded(RenderStyle* style)
return false;
}
- return true;
+ return HTMLPlugInElement::rendererIsNeeded(style);
}
RenderObject* HTMLEmbedElement::createRenderer(RenderArena* arena, RenderStyle*)
@@ -164,7 +164,7 @@ void HTMLEmbedElement::attach()
m_imageLoader->updateFromElement();
if (renderer())
- static_cast<RenderImage*>(renderer())->setCachedImage(m_imageLoader->image());
+ toRenderImage(renderer())->setCachedImage(m_imageLoader->image());
}
}
diff --git a/WebCore/html/HTMLFormControlElement.cpp b/WebCore/html/HTMLFormControlElement.cpp
index 0295f39..5238ad5 100644
--- a/WebCore/html/HTMLFormControlElement.cpp
+++ b/WebCore/html/HTMLFormControlElement.cpp
@@ -34,6 +34,7 @@
#include "HTMLNames.h"
#include "HTMLParser.h"
#include "HTMLTokenizer.h"
+#include "RenderBox.h"
#include "RenderTheme.h"
namespace WebCore {
@@ -98,8 +99,12 @@ void HTMLFormControlElement::attach()
// Focus the element if it should honour its autofocus attribute.
// We have to determine if the element is a TextArea/Input/Button/Select,
// if input type hidden ignore autofocus. So if disabled or readonly.
+ bool isInputTypeHidden = false;
+ if (hasTagName(inputTag))
+ isInputTypeHidden = static_cast<HTMLInputElement*>(this)->isInputTypeHidden();
+
if (autofocus() && renderer() && !document()->ignoreAutofocus() && !isReadOnlyControl() &&
- ((hasTagName(inputTag) && !isInputTypeHidden()) || hasTagName(selectTag) ||
+ ((hasTagName(inputTag) && !isInputTypeHidden) || hasTagName(selectTag) ||
hasTagName(buttonTag) || hasTagName(textareaTag)))
focus();
}
diff --git a/WebCore/html/HTMLFormControlElement.h b/WebCore/html/HTMLFormControlElement.h
index 0d1b31a..7430df7 100644
--- a/WebCore/html/HTMLFormControlElement.h
+++ b/WebCore/html/HTMLFormControlElement.h
@@ -45,7 +45,7 @@ public:
virtual const AtomicString& type() const = 0;
- virtual bool isControl() const { return true; }
+ virtual bool isTextControl() const { return false; }
virtual bool isEnabled() const { return !disabled(); }
virtual void parseMappedAttribute(MappedAttribute*);
diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp
index afc9c1e..df4e541 100644
--- a/WebCore/html/HTMLFormElement.cpp
+++ b/WebCore/html/HTMLFormElement.cpp
@@ -44,6 +44,7 @@
#include "MIMETypeRegistry.h"
#include "Page.h"
#include "RenderTextControl.h"
+#include <wtf/CurrentTime.h>
#include <wtf/RandomNumber.h>
#include <limits>
@@ -61,6 +62,14 @@ namespace WebCore {
using namespace HTMLNames;
+static int64_t generateFormDataIdentifier()
+{
+ // Initialize to the current time to reduce the likelihood of generating
+ // identifiers that overlap with those from past/future browser sessions.
+ static int64_t nextIdentifier = static_cast<int64_t>(currentTime() * 1000000.0);
+ return ++nextIdentifier;
+}
+
HTMLFormElement::HTMLFormElement(const QualifiedName& tagName, Document* doc)
: HTMLElement(tagName, doc)
, m_elementAliases(0)
@@ -116,7 +125,7 @@ void HTMLFormElement::removedFromDocument()
void HTMLFormElement::handleLocalEvents(Event* event, bool useCapture)
{
- EventTargetNode* targetNode = event->target()->toNode();
+ Node* targetNode = event->target()->toNode();
if (!useCapture && targetNode && targetNode != this && (event->type() == eventNames().submitEvent || event->type() == eventNames().resetEvent)) {
event->stopPropagation();
return;
@@ -202,7 +211,8 @@ PassRefPtr<FormData> HTMLFormElement::createFormData(const CString& boundary)
if (!path.isEmpty()) {
if (Page* page = document()->page()) {
String generatedFileName;
- if (shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName))
+ shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName);
+ if (shouldGenerateFile)
fileName = generatedFileName;
}
}
@@ -240,6 +250,8 @@ PassRefPtr<FormData> HTMLFormElement::createFormData(const CString& boundary)
m_formDataBuilder.addBoundaryToMultiPartHeader(encodedData, boundary, true);
result->appendData(encodedData.data(), encodedData.size());
+
+ result->setIdentifier(generateFormDataIdentifier());
return result;
}
@@ -625,9 +637,11 @@ void HTMLFormElement::CheckedRadioButtons::removeButton(HTMLFormControlElement*
if (it == m_nameToCheckedRadioButtonMap->end() || it->second != element)
return;
+ InputElement* inputElement = toInputElement(element);
+ ASSERT_UNUSED(inputElement, inputElement);
+ ASSERT(inputElement->isChecked());
ASSERT(element->isRadioButton());
- ASSERT(element->isChecked());
-
+
m_nameToCheckedRadioButtonMap->remove(it);
if (m_nameToCheckedRadioButtonMap->isEmpty())
m_nameToCheckedRadioButtonMap.clear();
diff --git a/WebCore/html/HTMLImageElement.cpp b/WebCore/html/HTMLImageElement.cpp
index 599cbee..c4e7608 100644
--- a/WebCore/html/HTMLImageElement.cpp
+++ b/WebCore/html/HTMLImageElement.cpp
@@ -80,7 +80,7 @@ void HTMLImageElement::parseMappedAttribute(MappedAttribute* attr)
const QualifiedName& attrName = attr->name();
if (attrName == altAttr) {
if (renderer() && renderer()->isImage())
- static_cast<RenderImage*>(renderer())->updateAltText();
+ toRenderImage(renderer())->updateAltText();
} else if (attrName == srcAttr)
m_imageLoader.updateFromElementIgnoringPreviousError();
else if (attrName == widthAttr)
@@ -166,7 +166,7 @@ void HTMLImageElement::attach()
HTMLElement::attach();
if (renderer() && renderer()->isImage()) {
- RenderImage* imageObj = static_cast<RenderImage*>(renderer());
+ RenderImage* imageObj = toRenderImage(renderer());
if (imageObj->hasImage())
return;
imageObj->setCachedImage(m_imageLoader.image());
diff --git a/WebCore/html/HTMLImageLoader.cpp b/WebCore/html/HTMLImageLoader.cpp
index 22e3abc..5dac8bf 100644
--- a/WebCore/html/HTMLImageLoader.cpp
+++ b/WebCore/html/HTMLImageLoader.cpp
@@ -42,10 +42,7 @@ HTMLImageLoader::~HTMLImageLoader()
void HTMLImageLoader::dispatchLoadEvent()
{
- if (!haveFiredLoadEvent() && image()) {
- setHaveFiredLoadEvent(true);
- element()->dispatchEventForType(image()->errorOccurred() ? eventNames().errorEvent : eventNames().loadEvent, false, false);
- }
+ element()->dispatchEventForType(image()->errorOccurred() ? eventNames().errorEvent : eventNames().loadEvent, false, false);
}
String HTMLImageLoader::sourceURI(const AtomicString& attr) const
diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp
index c451680..103b740 100644
--- a/WebCore/html/HTMLInputElement.cpp
+++ b/WebCore/html/HTMLInputElement.cpp
@@ -53,9 +53,6 @@
#include "RenderTextControlSingleLine.h"
#include "RenderTheme.h"
#include "TextEvent.h"
-#if USE(LOW_BANDWIDTH_DISPLAY)
-#include "FrameLoader.h"
-#endif
#ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
#include "WebViewCore.h"
#endif
@@ -447,7 +444,7 @@ int HTMLInputElement::selectionStart() const
return m_data.cachedSelectionStart();
if (!renderer())
return 0;
- return static_cast<RenderTextControl*>(renderer())->selectionStart();
+ return toRenderTextControl(renderer())->selectionStart();
}
int HTMLInputElement::selectionEnd() const
@@ -458,7 +455,7 @@ int HTMLInputElement::selectionEnd() const
return m_data.cachedSelectionEnd();
if (!renderer())
return 0;
- return static_cast<RenderTextControl*>(renderer())->selectionEnd();
+ return toRenderTextControl(renderer())->selectionEnd();
}
void HTMLInputElement::setSelectionStart(int start)
@@ -467,7 +464,7 @@ void HTMLInputElement::setSelectionStart(int start)
return;
if (!renderer())
return;
- static_cast<RenderTextControl*>(renderer())->setSelectionStart(start);
+ toRenderTextControl(renderer())->setSelectionStart(start);
}
void HTMLInputElement::setSelectionEnd(int end)
@@ -476,7 +473,7 @@ void HTMLInputElement::setSelectionEnd(int end)
return;
if (!renderer())
return;
- static_cast<RenderTextControl*>(renderer())->setSelectionEnd(end);
+ toRenderTextControl(renderer())->setSelectionEnd(end);
}
void HTMLInputElement::select()
@@ -485,7 +482,7 @@ void HTMLInputElement::select()
return;
if (!renderer())
return;
- static_cast<RenderTextControl*>(renderer())->select();
+ toRenderTextControl(renderer())->select();
}
void HTMLInputElement::setSelectionRange(int start, int end)
@@ -578,7 +575,7 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr)
InputElement::parseSizeAttribute(m_data, attr);
else if (attr->name() == altAttr) {
if (renderer() && inputType() == IMAGE)
- static_cast<RenderImage*>(renderer())->updateAltText();
+ toRenderImage(renderer())->updateAltText();
} else if (attr->name() == srcAttr) {
if (renderer() && inputType() == IMAGE) {
if (!m_imageLoader)
@@ -644,13 +641,6 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr)
bool HTMLInputElement::rendererIsNeeded(RenderStyle *style)
{
-#if USE(LOW_BANDWIDTH_DISPLAY)
- if (document()->inLowBandwidthDisplay()) {
- document()->frame()->loader()->needToSwitchOutLowBandwidthDisplay();
- return false;
- }
-#endif
-
switch (inputType()) {
case BUTTON:
case CHECKBOX:
@@ -715,7 +705,7 @@ void HTMLInputElement::attach()
m_imageLoader.set(new HTMLImageLoader(this));
m_imageLoader->updateFromElement();
if (renderer()) {
- RenderImage* imageObj = static_cast<RenderImage*>(renderer());
+ RenderImage* imageObj = toRenderImage(renderer());
imageObj->setCachedImage(m_imageLoader->image());
// If we have no image at all because we have no src attribute, set
@@ -956,17 +946,17 @@ void HTMLInputElement::setValue(const String& value)
if (inputType() == FILE && !value.isEmpty())
return;
- if (isTextField())
- InputElement::updatePlaceholderVisibility(m_data, document());
-
setValueMatchesRenderer(false);
if (storesValueSeparateFromAttribute()) {
if (inputType() == FILE)
m_fileList->clear();
else {
m_data.setValue(constrainValue(value));
- if (isTextField() && inDocument())
- document()->updateRendering();
+ if (isTextField()) {
+ InputElement::updatePlaceholderVisibility(m_data, document());
+ if (inDocument())
+ document()->updateRendering();
+ }
}
if (renderer())
renderer()->updateFromElement();
@@ -1113,6 +1103,9 @@ void HTMLInputElement::postDispatchEventHandler(Event *evt, void* data)
void HTMLInputElement::defaultEventHandler(Event* evt)
{
+ // FIXME: It would be better to refactor this for the different types of input element.
+ // Having them all in one giant function makes this hard to read, and almost all the handling is type-specific.
+
bool clickDefaultFormButton = false;
if (isTextField() && evt->type() == eventNames().textInputEvent && evt->isTextEvent() && static_cast<TextEvent*>(evt)->data() == "\n")
@@ -1128,26 +1121,36 @@ void HTMLInputElement::defaultEventHandler(Event* evt)
m_yPos = 0;
} else {
// FIXME: This doesn't work correctly with transforms.
+ // FIXME: pageX/pageY need adjusting for pageZoomFactor(). Use actualPageLocation()?
IntPoint absOffset = roundedIntPoint(renderer()->localToAbsolute());
m_xPos = me->pageX() - absOffset.x();
m_yPos = me->pageY() - absOffset.y();
}
}
- if (isTextField() && evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent() && focused() && document()->frame()
- && document()->frame()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) {
+ if (isTextField()
+ && evt->type() == eventNames().keydownEvent
+ && evt->isKeyboardEvent()
+ && focused()
+ && document()->frame()
+ && document()->frame()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) {
evt->setDefaultHandled();
return;
}
- if (inputType() == RADIO && evt->isMouseEvent()
- && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
+ if (inputType() == RADIO
+ && evt->isMouseEvent()
+ && evt->type() == eventNames().clickEvent
+ && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
evt->setDefaultHandled();
return;
}
- // Let the key handling done in EventTargetNode take precedence over the event handling here for editable text fields
- if (!clickDefaultFormButton) {
+ // Call the base event handler before any of our own event handling for almost all events in text fields.
+ // Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
+ bool callBaseClassEarly = isTextField() && !clickDefaultFormButton
+ && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
+ if (callBaseClassEarly) {
HTMLFormControlElementWithState::defaultEventHandler(evt);
if (evt->defaultHandled())
return;
@@ -1246,7 +1249,8 @@ void HTMLInputElement::defaultEventHandler(Event* evt)
case SUBMIT:
case RADIO:
setActive(true, true);
- // No setDefaultHandled() - IE dispatches a keypress in this case.
+ // No setDefaultHandled(), because IE dispatches a keypress in this case
+ // and the caller will only dispatch a keypress if we don't call setDefaultHandled.
return;
default:
break;
@@ -1337,12 +1341,12 @@ void HTMLInputElement::defaultEventHandler(Event* evt)
}
// Fire onChange for text fields.
RenderObject* r = renderer();
- if (r && r->isTextField() && r->isEdited()) {
+ if (r && r->isTextField() && toRenderTextControl(r)->isEdited()) {
onChange();
// Refetch the renderer since arbitrary JS code run during onchange can do anything, including destroying it.
r = renderer();
- if (r)
- r->setEdited(false);
+ if (r && r->isTextField())
+ toRenderTextControl(r)->setEdited(false);
}
// Form may never have been present, or may have been destroyed by the change event.
if (form())
@@ -1357,20 +1361,11 @@ void HTMLInputElement::defaultEventHandler(Event* evt)
if (isTextField() && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == eventNames().blurEvent || evt->type() == eventNames().focusEvent))
static_cast<RenderTextControlSingleLine*>(renderer())->forwardEvent(evt);
- if (inputType() == RANGE && renderer()) {
- RenderSlider* slider = static_cast<RenderSlider*>(renderer());
- if (evt->isMouseEvent() && evt->type() == eventNames().mousedownEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
- MouseEvent* mEvt = static_cast<MouseEvent*>(evt);
- if (!slider->mouseEventIsInThumb(mEvt)) {
- IntPoint eventOffset(mEvt->offsetX(), mEvt->offsetY());
- if (mEvt->target() != this) // Does this ever happen now? Was added for <video> controls
- eventOffset = roundedIntPoint(renderer()->absoluteToLocal(FloatPoint(mEvt->pageX(), mEvt->pageY()), false, true));
- slider->setValueForPosition(slider->positionForOffset(eventOffset));
- }
- }
- if (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent())
- slider->forwardEvent(evt);
- }
+ if (inputType() == RANGE && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent()))
+ static_cast<RenderSlider*>(renderer())->forwardEvent(evt);
+
+ if (!callBaseClassEarly && !evt->defaultHandled())
+ HTMLFormControlElementWithState::defaultEventHandler(evt);
}
bool HTMLInputElement::isURLAttribute(Attribute *attr) const
@@ -1453,6 +1448,16 @@ void HTMLInputElement::setMaxLength(int _maxLength)
setAttribute(maxlengthAttr, String::number(_maxLength));
}
+bool HTMLInputElement::multiple() const
+{
+ return !getAttribute(multipleAttr).isNull();
+}
+
+void HTMLInputElement::setMultiple(bool multiple)
+{
+ setAttribute(multipleAttr, multiple ? "" : 0);
+}
+
void HTMLInputElement::setSize(unsigned _size)
{
setAttribute(sizeAttr, String::number(_size));
@@ -1537,11 +1542,11 @@ void HTMLInputElement::onSearch()
dispatchEventForType(eventNames().searchEvent, true, false);
}
-Selection HTMLInputElement::selection() const
+VisibleSelection HTMLInputElement::selection() const
{
if (!renderer() || !isTextField() || m_data.cachedSelectionStart() == -1 || m_data.cachedSelectionEnd() == -1)
- return Selection();
- return static_cast<RenderTextControl*>(renderer())->selection(m_data.cachedSelectionStart(), m_data.cachedSelectionEnd());
+ return VisibleSelection();
+ return toRenderTextControl(renderer())->selection(m_data.cachedSelectionStart(), m_data.cachedSelectionEnd());
}
void HTMLInputElement::documentDidBecomeActive()
diff --git a/WebCore/html/HTMLInputElement.h b/WebCore/html/HTMLInputElement.h
index fd7ce03..5b6a5d6 100644
--- a/WebCore/html/HTMLInputElement.h
+++ b/WebCore/html/HTMLInputElement.h
@@ -33,7 +33,7 @@ namespace WebCore {
class FileList;
class HTMLImageLoader;
class KURL;
-class Selection;
+class VisibleSelection;
class HTMLInputElement : public HTMLFormControlElementWithState, public InputElement {
public:
@@ -188,10 +188,13 @@ public:
int maxLength() const;
void setMaxLength(int);
+ bool multiple() const;
+ void setMultiple(bool);
+
String useMap() const;
void setUseMap(const String&);
- bool isAutofilled() const { return m_autofilled; }
+ virtual bool isAutofilled() const { return m_autofilled; }
void setAutofilled(bool value = true);
FileList* files();
@@ -200,7 +203,7 @@ public:
void addSearchResult();
void onSearch();
- Selection selection() const;
+ VisibleSelection selection() const;
virtual String constrainValue(const String& proposedValue) const;
diff --git a/WebCore/html/HTMLInputElement.idl b/WebCore/html/HTMLInputElement.idl
index a9b6d2c..0734e6a 100644
--- a/WebCore/html/HTMLInputElement.idl
+++ b/WebCore/html/HTMLInputElement.idl
@@ -21,7 +21,6 @@
module html {
interface [
- CustomGetOwnPropertySlot,
GenerateConstructor,
InterfaceUUID=8f388ea3-1c31-4cca-8edd-449d14e222e1,
ImplementationUUID=aeb56b87-a90e-4d9d-a4d5-7eec3687c338
@@ -37,6 +36,7 @@ module html {
attribute boolean disabled;
attribute boolean autofocus;
attribute long maxLength;
+ attribute boolean multiple;
attribute [ConvertNullToNullString] DOMString name;
attribute boolean readOnly;
#if defined(LANGUAGE_OBJECTIVE_C)
@@ -58,9 +58,9 @@ module html {
// WinIE & FireFox extension:
- attribute [CustomGetter] long selectionStart;
- attribute [CustomGetter] long selectionEnd;
- void setSelectionRange(in long start, in long end);
+ attribute [Custom] long selectionStart;
+ attribute [Custom] long selectionEnd;
+ [Custom] void setSelectionRange(in long start, in long end);
#if defined(LANGUAGE_OBJECTIVE_C)
// Objective-C extension:
diff --git a/WebCore/html/HTMLLegendElement.cpp b/WebCore/html/HTMLLegendElement.cpp
index 9f7e645..4092643 100644
--- a/WebCore/html/HTMLLegendElement.cpp
+++ b/WebCore/html/HTMLLegendElement.cpp
@@ -26,7 +26,6 @@
#include "HTMLLegendElement.h"
#include "HTMLNames.h"
-#include "RenderLegend.h"
#include <wtf/StdLibExtras.h>
namespace WebCore {
@@ -48,14 +47,6 @@ bool HTMLLegendElement::isFocusable() const
return HTMLElement::isFocusable();
}
-RenderObject* HTMLLegendElement::createRenderer(RenderArena* arena, RenderStyle* style)
-{
- if (style->contentData())
- return RenderObject::createObject(this, style);
-
- return new (arena) RenderLegend(this);
-}
-
const AtomicString& HTMLLegendElement::type() const
{
DEFINE_STATIC_LOCAL(const AtomicString, legend, ("legend"));
diff --git a/WebCore/html/HTMLLegendElement.h b/WebCore/html/HTMLLegendElement.h
index b2ee51a..6d01dce 100644
--- a/WebCore/html/HTMLLegendElement.h
+++ b/WebCore/html/HTMLLegendElement.h
@@ -34,7 +34,6 @@ public:
virtual ~HTMLLegendElement();
virtual bool isFocusable() const;
- virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual const AtomicString& type() const;
virtual void accessKeyAction(bool sendToAnyElement);
diff --git a/WebCore/html/HTMLMediaElement.cpp b/WebCore/html/HTMLMediaElement.cpp
index 8d9cabb..df0ed04 100644
--- a/WebCore/html/HTMLMediaElement.cpp
+++ b/WebCore/html/HTMLMediaElement.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,12 +28,15 @@
#if ENABLE(VIDEO)
#include "HTMLMediaElement.h"
+#include "ContentType.h"
#include "CSSHelper.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
#include "Event.h"
#include "EventNames.h"
#include "ExceptionCode.h"
+#include "Frame.h"
+#include "FrameLoader.h"
#include "HTMLDocument.h"
#include "HTMLNames.h"
#include "HTMLSourceElement.h"
@@ -45,10 +48,18 @@
#include "MIMETypeRegistry.h"
#include "MediaPlayer.h"
#include "Page.h"
+#include "ProgressEvent.h"
#include "RenderVideo.h"
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+#include "RenderPartObject.h"
+#endif
#include "TimeRanges.h"
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+#include "Widget.h"
+#endif
#include <wtf/CurrentTime.h>
#include <wtf/MathExtras.h>
+#include <limits>
using namespace std;
@@ -61,27 +72,37 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* doc)
, m_loadTimer(this, &HTMLMediaElement::loadTimerFired)
, m_asyncEventTimer(this, &HTMLMediaElement::asyncEventTimerFired)
, m_progressEventTimer(this, &HTMLMediaElement::progressEventTimerFired)
+ , m_playbackProgressTimer(this, &HTMLMediaElement::playbackProgressTimerFired)
+ , m_playbackRate(1.0f)
, m_defaultPlaybackRate(1.0f)
- , m_networkState(EMPTY)
- , m_readyState(DATA_UNAVAILABLE)
- , m_begun(false)
- , m_loadedFirstFrame(false)
- , m_autoplaying(true)
- , m_currentLoop(0)
+ , m_networkState(NETWORK_EMPTY)
+ , m_readyState(HAVE_NOTHING)
, m_volume(1.0f)
- , m_muted(false)
- , m_paused(true)
- , m_seeking(false)
, m_currentTimeDuringSeek(0)
, m_previousProgress(0)
, m_previousProgressTime(numeric_limits<double>::max())
+ , m_lastTimeUpdateEventWallTime(0)
+ , m_lastTimeUpdateEventMovieTime(numeric_limits<float>::max())
+ , m_loadState(WaitingForSource)
+ , m_currentSourceNode(0)
+ , m_player(0)
+ , m_restrictions(NoRestrictions)
+ , m_processingMediaPlayerCallback(0)
+ , m_processingLoad(false)
+ , m_delayingTheLoadEvent(false)
+ , m_haveFiredLoadedData(false)
+ , m_inActiveDocument(true)
+ , m_autoplaying(true)
+ , m_muted(false)
+ , m_paused(true)
+ , m_seeking(false)
, m_sentStalledEvent(false)
- , m_bufferingRate(0)
- , m_loadNestingLevel(0)
- , m_terminateLoadBelowNestingLevel(0)
+ , m_sentEndEvent(false)
, m_pausedInternal(false)
- , m_inActiveDocument(true)
- , m_player(0)
+ , m_sendProgressEvents(true)
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ , m_needWidgetUpdate(false)
+#endif
{
document()->registerForDocumentActivationCallbacks(this);
document()->registerForMediaVolumeCallbacks(this);
@@ -104,11 +125,12 @@ void HTMLMediaElement::attributeChanged(Attribute* attr, bool preserveDecls)
const QualifiedName& attrName = attr->name();
if (attrName == srcAttr) {
- // 3.14.9.2.
- // change to src attribute triggers load()
- if (inDocument() && m_networkState == EMPTY)
+ // don't have a src or any <source> children, trigger load
+ if (inDocument() && m_loadState == WaitingForSource)
scheduleLoad();
- } if (attrName == controlsAttr) {
+ }
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ else if (attrName == controlsAttr) {
if (!isVideo() && attached() && (controls() != (renderer() != 0))) {
detach();
attach();
@@ -116,16 +138,30 @@ void HTMLMediaElement::attributeChanged(Attribute* attr, bool preserveDecls)
if (renderer())
renderer()->updateFromElement();
}
+#endif
}
bool HTMLMediaElement::rendererIsNeeded(RenderStyle* style)
{
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ UNUSED_PARAM(style);
+ Frame* frame = document()->frame();
+ if (!frame)
+ return false;
+
+ return true;
+#else
return controls() ? HTMLElement::rendererIsNeeded(style) : false;
+#endif
}
RenderObject* HTMLMediaElement::createRenderer(RenderArena* arena, RenderStyle*)
{
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ return new (arena) RenderPartObject(this);
+#else
return new (arena) RenderMedia(this);
+#endif
}
void HTMLMediaElement::insertedIntoDocument()
@@ -137,10 +173,8 @@ void HTMLMediaElement::insertedIntoDocument()
void HTMLMediaElement::removedFromDocument()
{
- // FIXME: pause() may invoke load() which seem like a strange thing to do as a side effect
- // of removing an element. This might need to be fixed in the spec.
- ExceptionCode ec;
- pause(ec);
+ if (m_networkState > NETWORK_EMPTY)
+ pause();
HTMLElement::removedFromDocument();
}
@@ -148,6 +182,10 @@ void HTMLMediaElement::attach()
{
ASSERT(!attached());
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ m_needWidgetUpdate = true;
+#endif
+
HTMLElement::attach();
if (renderer())
@@ -167,36 +205,53 @@ void HTMLMediaElement::scheduleLoad()
m_loadTimer.startOneShot(0);
}
-void HTMLMediaElement::initAndDispatchProgressEvent(const AtomicString& eventName)
+void HTMLMediaElement::scheduleProgressEvent(const AtomicString& eventName)
{
+ if (!m_sendProgressEvents)
+ return;
+
+ // FIXME: don't schedule timeupdate or progress events unless there are registered listeners
+
bool totalKnown = m_player && m_player->totalBytesKnown();
unsigned loaded = m_player ? m_player->bytesLoaded() : 0;
unsigned total = m_player ? m_player->totalBytes() : 0;
- dispatchProgressEvent(eventName, totalKnown, loaded, total);
+
+ RefPtr<ProgressEvent> evt = ProgressEvent::create(eventName, totalKnown, loaded, total);
+ enqueueEvent(evt);
+
if (renderer())
renderer()->updateFromElement();
}
-void HTMLMediaElement::dispatchEventAsync(const AtomicString& eventName)
+void HTMLMediaElement::scheduleEvent(const AtomicString& eventName)
+{
+ enqueueEvent(Event::create(eventName, false, true));
+}
+
+void HTMLMediaElement::enqueueEvent(RefPtr<Event> event)
{
- m_asyncEventsToDispatch.append(eventName);
+ m_pendingEvents.append(event);
if (!m_asyncEventTimer.isActive())
m_asyncEventTimer.startOneShot(0);
}
-void HTMLMediaElement::loadTimerFired(Timer<HTMLMediaElement>*)
+void HTMLMediaElement::asyncEventTimerFired(Timer<HTMLMediaElement>*)
{
- ExceptionCode ec;
- load(ec);
+ Vector<RefPtr<Event> > pendingEvents;
+ ExceptionCode ec = 0;
+
+ m_pendingEvents.swap(pendingEvents);
+ unsigned count = pendingEvents.size();
+ for (unsigned ndx = 0; ndx < count; ++ndx)
+ dispatchEvent(pendingEvents[ndx].release(), ec);
}
-void HTMLMediaElement::asyncEventTimerFired(Timer<HTMLMediaElement>*)
+void HTMLMediaElement::loadTimerFired(Timer<HTMLMediaElement>*)
{
- Vector<AtomicString> asyncEventsToDispatch;
- m_asyncEventsToDispatch.swap(asyncEventsToDispatch);
- unsigned count = asyncEventsToDispatch.size();
- for (unsigned n = 0; n < count; ++n)
- dispatchEventForType(asyncEventsToDispatch[n], false, true);
+ if (m_loadState == LoadingFromSourceElement)
+ loadNextSourceChild();
+ else
+ loadInternal();
}
static String serializeTimeOffset(float time)
@@ -260,252 +315,420 @@ HTMLMediaElement::NetworkState HTMLMediaElement::networkState() const
return m_networkState;
}
-float HTMLMediaElement::bufferingRate()
+String HTMLMediaElement::canPlayType(const String& mimeType) const
{
- if (!m_player)
- return 0;
- return m_bufferingRate;
- //return m_player->dataRate();
+ MediaPlayer::SupportsType support = MediaPlayer::supportsType(ContentType(mimeType));
+ String canPlay;
+
+ // 4.8.10.3
+ switch (support)
+ {
+ case MediaPlayer::IsNotSupported:
+ canPlay = "no";
+ break;
+ case MediaPlayer::MayBeSupported:
+ canPlay = "maybe";
+ break;
+ case MediaPlayer::IsSupported:
+ canPlay = "probably";
+ break;
+ }
+
+ return canPlay;
}
void HTMLMediaElement::load(ExceptionCode& ec)
{
- String mediaSrc;
-
- // 3.14.9.4. Loading the media resource
- // 1
- // if an event generated during load() ends up re-entering load(), terminate previous instances
- m_loadNestingLevel++;
- m_terminateLoadBelowNestingLevel = m_loadNestingLevel;
-
- m_progressEventTimer.stop();
- m_sentStalledEvent = false;
- m_bufferingRate = 0;
+ if (m_restrictions & RequireUserGestureForLoadRestriction && !processingUserGesture())
+ ec = INVALID_STATE_ERR;
+ else
+ loadInternal();
+}
+
+void HTMLMediaElement::loadInternal()
+{
+ // 1 - If the load() method for this element is already being invoked, then abort these steps.
+ if (m_processingLoad)
+ return;
+ m_processingLoad = true;
+ stopPeriodicTimers();
m_loadTimer.stop();
+ m_sentStalledEvent = false;
+ m_haveFiredLoadedData = false;
+
+ // 2 - Abort any already-running instance of the resource selection algorithm for this element.
+ m_currentSourceNode = 0;
+
+ // 3 - If there are any tasks from the media element's media element event task source in
+ // one of the task queues, then remove those tasks.
+ m_pendingEvents.clear();
- // 2
- if (m_begun) {
- m_begun = false;
+ // 4 - If the media element's networkState is set to NETWORK_LOADING or NETWORK_IDLE, set the
+ // error attribute to a new MediaError object whose code attribute is set to MEDIA_ERR_ABORTED,
+ // and fire a progress event called abort at the media element.
+ if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE) {
m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED);
- initAndDispatchProgressEvent(eventNames().abortEvent);
- if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel)
- goto end;
+
+ // fire synchronous 'abort'
+ bool totalKnown = m_player && m_player->totalBytesKnown();
+ unsigned loaded = m_player ? m_player->bytesLoaded() : 0;
+ unsigned total = m_player ? m_player->totalBytes() : 0;
+ dispatchProgressEvent(eventNames().abortEvent, totalKnown, loaded, total);
}
- // 3
+ // 5
m_error = 0;
- m_loadedFirstFrame = false;
m_autoplaying = true;
+
+ // 6
+ setPlaybackRate(defaultPlaybackRate());
- // 4
- setPlaybackRate(defaultPlaybackRate(), ec);
-
- // 5
- if (networkState() != EMPTY) {
- m_networkState = EMPTY;
- m_readyState = DATA_UNAVAILABLE;
+ // 7
+ if (m_networkState != NETWORK_EMPTY) {
+ m_networkState = NETWORK_EMPTY;
+ m_readyState = HAVE_NOTHING;
m_paused = true;
m_seeking = false;
if (m_player) {
m_player->pause();
m_player->seek(0);
}
- m_currentLoop = 0;
dispatchEventForType(eventNames().emptiedEvent, false, true);
- if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel)
- goto end;
}
- // 6
- mediaSrc = pickMedia();
+ selectMediaResource();
+ m_processingLoad = false;
+}
+
+void HTMLMediaElement::selectMediaResource()
+{
+ // 1 - If the media element has neither a src attribute nor any source element children, run these substeps
+ String mediaSrc = getAttribute(srcAttr);
+ if (!mediaSrc && !havePotentialSourceChild()) {
+ m_loadState = WaitingForSource;
+
+ // 1 - Set the networkState to NETWORK_NO_SOURCE
+ m_networkState = NETWORK_NO_SOURCE;
+
+ // 2 - While the media element has neither a src attribute nor any source element children,
+ // wait. (This steps might wait forever.)
+
+ m_delayingTheLoadEvent = false;
+ return;
+ }
+
+ // 2
+ m_delayingTheLoadEvent = true;
+
+ // 3
+ m_networkState = NETWORK_LOADING;
+
+ // 4
+ scheduleProgressEvent(eventNames().loadstartEvent);
+
+ // 5 - If the media element has a src attribute, then run these substeps
+ ContentType contentType("");
+ if (!mediaSrc.isEmpty()) {
+ mediaSrc = document()->completeURL(mediaSrc).string();
+ m_loadState = LoadingFromSrcAttr;
+ loadResource(mediaSrc, contentType);
+ return;
+ }
+
+ // Otherwise, the source elements will be used
+ m_currentSourceNode = 0;
+ loadNextSourceChild();
+}
+
+void HTMLMediaElement::loadNextSourceChild()
+{
+ ContentType contentType("");
+ String mediaSrc;
+
+ mediaSrc = nextSourceChild(&contentType);
if (mediaSrc.isEmpty()) {
- ec = INVALID_STATE_ERR;
- goto end;
+ noneSupported();
+ return;
}
-
- // 7
- m_networkState = LOADING;
-
- // 8
- m_currentSrc = mediaSrc;
-
- // 9
- m_begun = true;
- dispatchProgressEvent(eventNames().loadstartEvent, false, 0, 0);
- if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel)
- goto end;
-
- // 10, 11, 12, 13
+
+ m_loadState = LoadingFromSourceElement;
+ loadResource(mediaSrc, contentType);
+}
+
+void HTMLMediaElement::loadResource(String url, ContentType& contentType)
+{
+ // The resource fetch algorithm
+
+ m_networkState = NETWORK_LOADING;
+
+ m_currentSrc = url;
+
+ if (m_sendProgressEvents)
+ startProgressEventTimer();
+
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
m_player.clear();
m_player.set(new MediaPlayer(this));
+#else
+ if (!m_player)
+ m_player.set(new MediaPlayer(this));
+#endif
+
updateVolume();
- m_player->load(m_currentSrc);
- if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel)
- goto end;
+
+ m_player->load(m_currentSrc, contentType);
if (renderer())
renderer()->updateFromElement();
-
- // 14
+}
+
+void HTMLMediaElement::startProgressEventTimer()
+{
+ if (m_progressEventTimer.isActive())
+ return;
+
m_previousProgressTime = WTF::currentTime();
m_previousProgress = 0;
- if (m_begun)
- // 350ms is not magic, it is in the spec!
- m_progressEventTimer.startRepeating(0.350);
-end:
- ASSERT(m_loadNestingLevel);
- m_loadNestingLevel--;
+ // 350ms is not magic, it is in the spec!
+ m_progressEventTimer.startRepeating(0.350);
+}
+
+void HTMLMediaElement::noneSupported()
+{
+ stopPeriodicTimers();
+ m_loadState = WaitingForSource;
+ m_currentSourceNode = 0;
+
+ // 3 - Reaching this step indicates that either the URL failed to resolve, or the media
+ // resource failed to load. Set the error attribute to a new MediaError object whose
+ // code attribute is set to MEDIA_ERR_NONE_SUPPORTED.
+ m_error = MediaError::create(MediaError::MEDIA_ERR_NONE_SUPPORTED);
+
+ // 4- Set the element's networkState attribute to the NETWORK_NO_SOURCE value.
+ m_networkState = NETWORK_NO_SOURCE;
+
+ // 5 - Queue a task to fire a progress event called error at the media element.
+ scheduleProgressEvent(eventNames().errorEvent);
+
+ // 6 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
+ m_delayingTheLoadEvent = false;
+
+ // Abort these steps. Until the load() method is invoked, the element won't attempt to load another resource.
+
+ if (isVideo())
+ static_cast<HTMLVideoElement*>(this)->updatePosterImage();
+ if (renderer())
+ renderer()->updateFromElement();
+}
+
+void HTMLMediaElement::mediaEngineError(PassRefPtr<MediaError> err)
+{
+ // 1 - The user agent should cancel the fetching process.
+ stopPeriodicTimers();
+ m_loadState = WaitingForSource;
+
+ // 2 - Set the error attribute to a new MediaError object whose code attribute is
+ // set to MEDIA_ERR_NETWORK/MEDIA_ERR_DECODE.
+ m_error = err;
+
+ // 3 - Queue a task to fire a progress event called error at the media element.
+ scheduleProgressEvent(eventNames().errorEvent);
+
+ // 3 - Set the element's networkState attribute to the NETWORK_EMPTY value and queue a
+ // task to fire a simple event called emptied at the element.
+ m_networkState = NETWORK_EMPTY;
+ scheduleEvent(eventNames().emptiedEvent);
+
+ // 4 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
+ m_delayingTheLoadEvent = false;
+
+ // 5 - Abort the overall resource selection algorithm.
+ m_currentSourceNode = 0;
+
}
void HTMLMediaElement::mediaPlayerNetworkStateChanged(MediaPlayer*)
{
- if (!m_begun || m_networkState == EMPTY)
+ beginProcessingMediaPlayerCallback();
+ setNetworkState(m_player->networkState());
+ endProcessingMediaPlayerCallback();
+}
+
+void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)
+{
+ if (state == MediaPlayer::Empty) {
+ // just update the cached state and leave, we can't do anything
+ m_networkState = NETWORK_EMPTY;
return;
-
- m_terminateLoadBelowNestingLevel = m_loadNestingLevel;
+ }
- MediaPlayer::NetworkState state = m_player->networkState();
-
- // 3.14.9.4. Loading the media resource
- // 14
- if (state == MediaPlayer::LoadFailed) {
- //delete m_player;
- //m_player = 0;
- // FIXME better error handling
- m_error = MediaError::create(MediaError::MEDIA_ERR_NETWORK);
- m_begun = false;
- m_progressEventTimer.stop();
- m_bufferingRate = 0;
-
- initAndDispatchProgressEvent(eventNames().errorEvent);
- if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel)
+ if (state == MediaPlayer::FormatError || state == MediaPlayer::NetworkError || state == MediaPlayer::DecodeError) {
+ stopPeriodicTimers();
+
+ // If we failed while trying to load a <source> element, the movie was never parsed, and there are more
+ // <source> children, schedule the next one without reporting an error
+ if (m_readyState < HAVE_METADATA && m_loadState == LoadingFromSourceElement && havePotentialSourceChild()) {
+ scheduleLoad();
return;
-
- m_networkState = EMPTY;
-
+ }
+
+ if (state == MediaPlayer::NetworkError)
+ mediaEngineError(MediaError::create(MediaError::MEDIA_ERR_NETWORK));
+ else if (state == MediaPlayer::DecodeError)
+ mediaEngineError(MediaError::create(MediaError::MEDIA_ERR_DECODE));
+ else if (state == MediaPlayer::FormatError)
+ noneSupported();
+
if (isVideo())
static_cast<HTMLVideoElement*>(this)->updatePosterImage();
- dispatchEventForType(eventNames().emptiedEvent, false, true);
return;
}
-
- if (state >= MediaPlayer::Loading && m_networkState < LOADING)
- m_networkState = LOADING;
-
- if (state >= MediaPlayer::LoadedMetaData && m_networkState < LOADED_METADATA) {
- m_player->seek(effectiveStart());
- m_networkState = LOADED_METADATA;
-
- dispatchEventForType(eventNames().durationchangeEvent, false, true);
- if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel)
- return;
-
- dispatchEventForType(eventNames().loadedmetadataEvent, false, true);
- if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel)
- return;
+
+ if (state == MediaPlayer::Idle && m_networkState > NETWORK_IDLE) {
+ ASSERT(static_cast<ReadyState>(m_player->readyState()) < HAVE_ENOUGH_DATA);
+ m_networkState = NETWORK_IDLE;
+ stopPeriodicTimers();
+ scheduleProgressEvent(eventNames().suspendEvent);
}
-
- if (state >= MediaPlayer::LoadedFirstFrame && m_networkState < LOADED_FIRST_FRAME) {
- m_networkState = LOADED_FIRST_FRAME;
-
- setReadyState(CAN_SHOW_CURRENT_FRAME);
-
- if (isVideo())
- static_cast<HTMLVideoElement*>(this)->updatePosterImage();
-
- if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel)
- return;
-
- m_loadedFirstFrame = true;
- if (renderer()) {
- ASSERT(!renderer()->isImage());
- static_cast<RenderVideo*>(renderer())->videoSizeChanged();
- }
-
- dispatchEventForType(eventNames().loadedfirstframeEvent, false, true);
- if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel)
- return;
-
- dispatchEventForType(eventNames().canshowcurrentframeEvent, false, true);
- if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel)
- return;
+
+ if (state == MediaPlayer::Loading && (m_networkState < NETWORK_LOADING || m_networkState == NETWORK_NO_SOURCE)) {
+ ASSERT(static_cast<ReadyState>(m_player->readyState()) < HAVE_ENOUGH_DATA);
+ m_networkState = NETWORK_LOADING;
+ startProgressEventTimer();
}
-
- // 15
- if (state == MediaPlayer::Loaded && m_networkState < LOADED) {
- m_begun = false;
- m_networkState = LOADED;
+
+ if (state == MediaPlayer::Loaded && (m_networkState < NETWORK_LOADED || m_networkState == NETWORK_NO_SOURCE)) {
+ m_networkState = NETWORK_LOADED;
m_progressEventTimer.stop();
- m_bufferingRate = 0;
- initAndDispatchProgressEvent(eventNames().loadEvent);
+
+ // Check to see if readyState changes need to be dealt with before sending the
+ // 'load' event so we report 'canplaythrough' first. This is necessary because a
+ // media engine reports readyState and networkState changes separately
+ MediaPlayer::ReadyState currentState = m_player->readyState();
+ if (static_cast<ReadyState>(currentState) != m_readyState)
+ setReadyState(currentState);
+
+ scheduleProgressEvent(eventNames().loadEvent);
}
}
void HTMLMediaElement::mediaPlayerReadyStateChanged(MediaPlayer*)
{
- MediaPlayer::ReadyState state = m_player->readyState();
- setReadyState((ReadyState)state);
+ beginProcessingMediaPlayerCallback();
+
+ setReadyState(m_player->readyState());
+
+ endProcessingMediaPlayerCallback();
}
-void HTMLMediaElement::setReadyState(ReadyState state)
+void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state)
{
- // 3.14.9.6. The ready states
- if (m_readyState == state)
+ // Set "wasPotentiallyPlaying" BEFORE updating m_readyState, potentiallyPlaying() uses it
+ bool wasPotentiallyPlaying = potentiallyPlaying();
+
+ ReadyState oldState = m_readyState;
+ m_readyState = static_cast<ReadyState>(state);
+
+ if (m_readyState == oldState)
return;
- bool wasActivelyPlaying = activelyPlaying();
- m_readyState = state;
-
- if (state >= CAN_PLAY)
+ if (m_readyState >= HAVE_CURRENT_DATA)
m_seeking = false;
- if (networkState() == EMPTY)
+ if (m_networkState == NETWORK_EMPTY)
return;
-
- if (state == DATA_UNAVAILABLE) {
- dispatchEventForType(eventNames().dataunavailableEvent, false, true);
- if (wasActivelyPlaying) {
- dispatchEventForType(eventNames().timeupdateEvent, false, true);
- dispatchEventForType(eventNames().waitingEvent, false, true);
- }
- } else if (state == CAN_SHOW_CURRENT_FRAME) {
- if (m_loadedFirstFrame)
- dispatchEventForType(eventNames().canshowcurrentframeEvent, false, true);
- if (wasActivelyPlaying) {
- dispatchEventForType(eventNames().timeupdateEvent, false, true);
- dispatchEventForType(eventNames().waitingEvent, false, true);
+
+ if (m_seeking && m_readyState < HAVE_CURRENT_DATA) {
+ // 4.8.10.10, step 9
+ scheduleEvent(eventNames().seekingEvent);
+ m_seeking = false;
+ }
+
+ if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA) {
+ // 4.8.10.9
+ scheduleTimeupdateEvent(false);
+ scheduleEvent(eventNames().waitingEvent);
+ }
+
+ if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) {
+ scheduleEvent(eventNames().durationchangeEvent);
+ scheduleEvent(eventNames().loadedmetadataEvent);
+
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ if (renderer() && !renderer()->isImage()) {
+ static_cast<RenderVideo*>(renderer())->videoSizeChanged();
}
- } else if (state == CAN_PLAY) {
- dispatchEventForType(eventNames().canplayEvent, false, true);
- } else if (state == CAN_PLAY_THROUGH) {
- dispatchEventForType(eventNames().canplaythroughEvent, false, true);
+#endif
+ m_delayingTheLoadEvent = false;
+ m_player->seek(0);
+ }
+
+ // 4.8.10.7 says loadeddata is sent only when the new state *is* HAVE_CURRENT_DATA: "If the
+ // previous ready state was HAVE_METADATA and the new ready state is HAVE_CURRENT_DATA",
+ // but the event table at the end of the spec says it is sent when: "readyState newly
+ // increased to HAVE_CURRENT_DATA or greater for the first time"
+ // We go with the later because it seems useful to count on getting this event
+ if (m_readyState >= HAVE_CURRENT_DATA && oldState < HAVE_CURRENT_DATA && !m_haveFiredLoadedData) {
+ m_haveFiredLoadedData = true;
+ scheduleEvent(eventNames().loadeddataEvent);
+ }
+
+ bool isPotentiallyPlaying = potentiallyPlaying();
+ if (m_readyState <= HAVE_CURRENT_DATA && oldState >= HAVE_FUTURE_DATA) {
+ if (isPotentiallyPlaying)
+ scheduleEvent(eventNames().waitingEvent);
+ }
+
+ if (m_readyState == HAVE_FUTURE_DATA && oldState <= HAVE_CURRENT_DATA) {
+ scheduleEvent(eventNames().canplayEvent);
+ if (isPotentiallyPlaying)
+ scheduleEvent(eventNames().playingEvent);
+
+ if (isVideo())
+ static_cast<HTMLVideoElement*>(this)->updatePosterImage();
+ }
+
+ if (m_readyState == HAVE_ENOUGH_DATA && oldState < HAVE_ENOUGH_DATA) {
+ if (oldState <= HAVE_CURRENT_DATA)
+ scheduleEvent(eventNames().canplayEvent);
+
+ scheduleEvent(eventNames().canplaythroughEvent);
+
+ if (isPotentiallyPlaying && oldState <= HAVE_CURRENT_DATA)
+ scheduleEvent(eventNames().playingEvent);
+
if (m_autoplaying && m_paused && autoplay()) {
m_paused = false;
- dispatchEventForType(eventNames().playEvent, false, true);
+ scheduleEvent(eventNames().playEvent);
+ scheduleEvent(eventNames().playingEvent);
}
+
+ if (isVideo())
+ static_cast<HTMLVideoElement*>(this)->updatePosterImage();
}
+
updatePlayState();
}
void HTMLMediaElement::progressEventTimerFired(Timer<HTMLMediaElement>*)
{
ASSERT(m_player);
+ if (m_networkState == NETWORK_EMPTY || m_networkState >= NETWORK_LOADED)
+ return;
+
unsigned progress = m_player->bytesLoaded();
double time = WTF::currentTime();
double timedelta = time - m_previousProgressTime;
- if (timedelta)
- m_bufferingRate = (float)(0.8 * m_bufferingRate + 0.2 * ((float)(progress - m_previousProgress)) / timedelta);
-
+
if (progress == m_previousProgress) {
if (timedelta > 3.0 && !m_sentStalledEvent) {
- m_bufferingRate = 0;
- initAndDispatchProgressEvent(eventNames().stalledEvent);
+ scheduleProgressEvent(eventNames().stalledEvent);
m_sentStalledEvent = true;
}
} else {
- initAndDispatchProgressEvent(eventNames().progressEvent);
+ scheduleProgressEvent(eventNames().progressEvent);
m_previousProgress = progress;
m_previousProgressTime = time;
m_sentStalledEvent = false;
@@ -514,52 +737,45 @@ void HTMLMediaElement::progressEventTimerFired(Timer<HTMLMediaElement>*)
void HTMLMediaElement::seek(float time, ExceptionCode& ec)
{
- // 3.14.9.8. Seeking
+ // 4.8.10.10. Seeking
// 1
- if (networkState() < LOADED_METADATA) {
+ if (m_readyState == HAVE_NOTHING || !m_player) {
ec = INVALID_STATE_ERR;
return;
}
-
+
// 2
- float minTime;
- if (currentLoop() == 0)
- minTime = effectiveStart();
- else
- minTime = effectiveLoopStart();
-
+ time = min(time, duration());
+
// 3
- float maxTime = currentLoop() == playCount() - 1 ? effectiveEnd() : effectiveLoopEnd();
-
+ time = max(time, 0.0f);
+
// 4
- time = min(time, maxTime);
-
- // 5
- time = max(time, minTime);
-
- // 6
RefPtr<TimeRanges> seekableRanges = seekable();
if (!seekableRanges->contain(time)) {
ec = INDEX_SIZE_ERR;
return;
}
- // 7
+ // avoid generating events when the time won't actually change
+ float now = currentTime();
+ if (time == now)
+ return;
+
+ // 5
m_currentTimeDuringSeek = time;
- // 8
+ // 6 - set the seeking flag, it will be cleared when the engine tells is the time has actually changed
m_seeking = true;
-
- // 9
- dispatchEventForType(eventNames().timeupdateEvent, false, true);
-
+
+ // 7
+ scheduleTimeupdateEvent(false);
+
+ // 8 - this is covered, if necessary, when the engine signals a readystate change
+
// 10
- // As soon as the user agent has established whether or not the media data for the new playback position is available,
- // and, if it is, decoded enough data to play back that position, the seeking DOM attribute must be set to false.
- if (m_player) {
- m_player->setEndTime(maxTime);
- m_player->seek(time);
- }
+ m_player->seek(time);
+ m_sentEndEvent = false;
}
HTMLMediaElement::ReadyState HTMLMediaElement::readyState() const
@@ -589,7 +805,10 @@ void HTMLMediaElement::setCurrentTime(float time, ExceptionCode& ec)
float HTMLMediaElement::duration() const
{
- return m_player ? m_player->duration() : 0;
+ if (m_readyState >= HAVE_METADATA)
+ return m_player->duration();
+
+ return numeric_limits<float>::quiet_NaN();
}
bool HTMLMediaElement::paused() const
@@ -602,15 +821,11 @@ float HTMLMediaElement::defaultPlaybackRate() const
return m_defaultPlaybackRate;
}
-void HTMLMediaElement::setDefaultPlaybackRate(float rate, ExceptionCode& ec)
+void HTMLMediaElement::setDefaultPlaybackRate(float rate)
{
- if (rate == 0.0f) {
- ec = NOT_SUPPORTED_ERR;
- return;
- }
if (m_defaultPlaybackRate != rate) {
m_defaultPlaybackRate = rate;
- dispatchEventAsync(eventNames().ratechangeEvent);
+ scheduleEvent(eventNames().ratechangeEvent);
}
}
@@ -619,16 +834,14 @@ float HTMLMediaElement::playbackRate() const
return m_player ? m_player->rate() : 0;
}
-void HTMLMediaElement::setPlaybackRate(float rate, ExceptionCode& ec)
+void HTMLMediaElement::setPlaybackRate(float rate)
{
- if (rate == 0.0f) {
- ec = NOT_SUPPORTED_ERR;
- return;
+ if (m_playbackRate != rate) {
+ m_playbackRate = rate;
+ scheduleEvent(eventNames().ratechangeEvent);
}
- if (m_player && m_player->rate() != rate) {
+ if (m_player && potentiallyPlaying() && m_player->rate() != rate)
m_player->setRate(rate);
- dispatchEventAsync(eventNames().ratechangeEvent);
- }
}
bool HTMLMediaElement::ended() const
@@ -646,126 +859,85 @@ void HTMLMediaElement::setAutoplay(bool b)
setBooleanAttribute(autoplayAttr, b);
}
-void HTMLMediaElement::play(ExceptionCode& ec)
+void HTMLMediaElement::play()
{
- // 3.14.9.7. Playing the media resource
- if (!m_player || networkState() == EMPTY) {
- ec = 0;
- load(ec);
- if (ec)
- return;
- }
- ExceptionCode unused;
- if (endedPlayback()) {
- m_currentLoop = 0;
- seek(effectiveStart(), unused);
- }
- setPlaybackRate(defaultPlaybackRate(), unused);
-
- if (m_paused) {
- m_paused = false;
- dispatchEventAsync(eventNames().playEvent);
- }
+ if (m_restrictions & RequireUserGestureForRateChangeRestriction && !processingUserGesture())
+ return;
- m_autoplaying = false;
-
- updatePlayState();
+ playInternal();
}
-void HTMLMediaElement::pause(ExceptionCode& ec)
+void HTMLMediaElement::playInternal()
{
- // 3.14.9.7. Playing the media resource
- if (!m_player || networkState() == EMPTY) {
- ec = 0;
- load(ec);
- if (ec)
- return;
- }
+ // 4.8.10.9. Playing the media resource
+ if (!m_player || m_networkState == NETWORK_EMPTY)
+ scheduleLoad();
- if (!m_paused) {
- m_paused = true;
- dispatchEventAsync(eventNames().timeupdateEvent);
- dispatchEventAsync(eventNames().pauseEvent);
+ if (endedPlayback()) {
+ ExceptionCode unused;
+ seek(0, unused);
}
+
+ setPlaybackRate(defaultPlaybackRate());
+
+ if (m_paused) {
+ m_paused = false;
+ scheduleEvent(eventNames().playEvent);
+ if (m_readyState <= HAVE_CURRENT_DATA)
+ scheduleEvent(eventNames().waitingEvent);
+ else if (m_readyState >= HAVE_FUTURE_DATA)
+ scheduleEvent(eventNames().playingEvent);
+ }
m_autoplaying = false;
-
- updatePlayState();
-}
-unsigned HTMLMediaElement::playCount() const
-{
- bool ok;
- unsigned count = getAttribute(playcountAttr).string().toUInt(&ok);
- return (count > 0 && ok) ? count : 1;
+ updatePlayState();
}
-void HTMLMediaElement::setPlayCount(unsigned count, ExceptionCode& ec)
+void HTMLMediaElement::pause()
{
- if (!count) {
- ec = INDEX_SIZE_ERR;
+ if (m_restrictions & RequireUserGestureForRateChangeRestriction && !processingUserGesture())
return;
- }
- setAttribute(playcountAttr, String::number(count));
- checkIfSeekNeeded();
-}
-float HTMLMediaElement::start() const
-{
- return getTimeOffsetAttribute(startAttr, 0);
+ pauseInternal();
}
-void HTMLMediaElement::setStart(float time)
-{
- setTimeOffsetAttribute(startAttr, time);
- checkIfSeekNeeded();
-}
-float HTMLMediaElement::end() const
-{
- return getTimeOffsetAttribute(endAttr, std::numeric_limits<float>::infinity());
-}
-
-void HTMLMediaElement::setEnd(float time)
-{
- setTimeOffsetAttribute(endAttr, time);
- checkIfSeekNeeded();
-}
-
-float HTMLMediaElement::loopStart() const
-{
- return getTimeOffsetAttribute(loopstartAttr, start());
-}
-
-void HTMLMediaElement::setLoopStart(float time)
+void HTMLMediaElement::pauseInternal()
{
- setTimeOffsetAttribute(loopstartAttr, time);
- checkIfSeekNeeded();
-}
+ // 4.8.10.9. Playing the media resource
+ if (!m_player || m_networkState == NETWORK_EMPTY)
+ scheduleLoad();
-float HTMLMediaElement::loopEnd() const
-{
- return getTimeOffsetAttribute(loopendAttr, end());
-}
+ m_autoplaying = false;
+
+ if (!m_paused) {
+ m_paused = true;
+ scheduleTimeupdateEvent(false);
+ scheduleEvent(eventNames().pauseEvent);
+ }
-void HTMLMediaElement::setLoopEnd(float time)
-{
- setTimeOffsetAttribute(loopendAttr, time);
- checkIfSeekNeeded();
+ updatePlayState();
}
-unsigned HTMLMediaElement::currentLoop() const
+bool HTMLMediaElement::loop() const
{
- return m_currentLoop;
+ return hasAttribute(loopAttr);
}
-void HTMLMediaElement::setCurrentLoop(unsigned currentLoop)
+void HTMLMediaElement::setLoop(bool b)
{
- m_currentLoop = currentLoop;
+ setBooleanAttribute(loopAttr, b);
}
bool HTMLMediaElement::controls() const
{
+ Frame* frame = document()->frame();
+
+ // always show controls when scripting is disabled
+ if (frame && !frame->script()->isEnabled())
+ return true;
+
return hasAttribute(controlsAttr);
}
@@ -789,7 +961,7 @@ void HTMLMediaElement::setVolume(float vol, ExceptionCode& ec)
if (m_volume != vol) {
m_volume = vol;
updateVolume();
- dispatchEventAsync(eventNames().volumechangeEvent);
+ scheduleEvent(eventNames().volumechangeEvent);
}
}
@@ -803,110 +975,224 @@ void HTMLMediaElement::setMuted(bool muted)
if (m_muted != muted) {
m_muted = muted;
updateVolume();
- dispatchEventAsync(eventNames().volumechangeEvent);
+ scheduleEvent(eventNames().volumechangeEvent);
}
}
-bool HTMLMediaElement::canPlay() const
+void HTMLMediaElement::togglePlayState()
{
- return paused() || ended() || networkState() < LOADED_METADATA;
+ // We can safely call the internal play/pause methods, which don't check restrictions, because
+ // this method is only called from the built-in media controller
+ if (canPlay())
+ playInternal();
+ else
+ pauseInternal();
}
-String HTMLMediaElement::pickMedia()
+void HTMLMediaElement::beginScrubbing()
{
- // 3.14.9.2. Location of the media resource
- String mediaSrc = getAttribute(srcAttr);
- if (mediaSrc.isEmpty()) {
- for (Node* n = firstChild(); n; n = n->nextSibling()) {
- if (n->hasTagName(sourceTag)) {
- HTMLSourceElement* source = static_cast<HTMLSourceElement*>(n);
- if (!source->hasAttribute(srcAttr))
- continue;
- if (source->hasAttribute(mediaAttr)) {
- MediaQueryEvaluator screenEval("screen", document()->frame(), renderer() ? renderer()->style() : 0);
- RefPtr<MediaList> media = MediaList::createAllowingDescriptionSyntax(source->media());
- if (!screenEval.eval(media.get()))
- continue;
- }
- if (source->hasAttribute(typeAttr)) {
- String type = source->type().stripWhiteSpace();
-
- // "type" can have parameters after a semi-colon, strip them before checking with the type registry
- int semi = type.find(';');
- if (semi != -1)
- type = type.left(semi).stripWhiteSpace();
-
- if (!MIMETypeRegistry::isSupportedMediaMIMEType(type))
- continue;
- }
- mediaSrc = source->src().string();
- break;
- }
+ if (!paused()) {
+ if (ended()) {
+ // Because a media element stays in non-paused state when it reaches end, playback resumes
+ // when the slider is dragged from the end to another position unless we pause first. Do
+ // a "hard pause" so an event is generated, since we want to stay paused after scrubbing finishes.
+ pause();
+ } else {
+ // Not at the end but we still want to pause playback so the media engine doesn't try to
+ // continue playing during scrubbing. Pause without generating an event as we will
+ // unpause after scrubbing finishes.
+ setPausedInternal(true);
}
}
- if (!mediaSrc.isEmpty())
- mediaSrc = document()->completeURL(mediaSrc).string();
- return mediaSrc;
}
-void HTMLMediaElement::checkIfSeekNeeded()
+void HTMLMediaElement::endScrubbing()
{
- // 3.14.9.5. Offsets into the media resource
- // 1
- if (playCount() <= m_currentLoop)
- m_currentLoop = playCount() - 1;
-
- // 2
- if (networkState() <= LOADING)
+ if (m_pausedInternal)
+ setPausedInternal(false);
+}
+
+// The spec says to fire periodic timeupdate events (those sent while playing) every
+// "15 to 250ms", we choose the slowest frequency
+static const double maxTimeupdateEventFrequency = 0.25;
+
+void HTMLMediaElement::startPlaybackProgressTimer()
+{
+ if (m_playbackProgressTimer.isActive())
+ return;
+
+ m_previousProgressTime = WTF::currentTime();
+ m_previousProgress = 0;
+ m_playbackProgressTimer.startRepeating(maxTimeupdateEventFrequency);
+}
+
+void HTMLMediaElement::playbackProgressTimerFired(Timer<HTMLMediaElement>*)
+{
+ ASSERT(m_player);
+ if (!m_playbackRate)
return;
+
+ scheduleTimeupdateEvent(true);
- // 3
- ExceptionCode ec;
- float time = currentTime();
- if (!m_currentLoop && time < effectiveStart())
- seek(effectiveStart(), ec);
+ // FIXME: deal with cue ranges here
+}
- // 4
- if (m_currentLoop && time < effectiveLoopStart())
- seek(effectiveLoopStart(), ec);
+void HTMLMediaElement::scheduleTimeupdateEvent(bool periodicEvent)
+{
+ double now = WTF::currentTime();
+ double timedelta = now - m_lastTimeUpdateEventWallTime;
+
+ // throttle the periodic events
+ if (periodicEvent && timedelta < maxTimeupdateEventFrequency)
+ return;
+
+ // Some media engines make multiple "time changed" callbacks at the same time, but we only want one
+ // event at a given time so filter here
+ float movieTime = m_player ? m_player->currentTime() : 0;
+ if (movieTime != m_lastTimeUpdateEventMovieTime) {
+ scheduleEvent(eventNames().timeupdateEvent);
+ m_lastTimeUpdateEventWallTime = now;
+ m_lastTimeUpdateEventMovieTime = movieTime;
+ }
+}
+
+bool HTMLMediaElement::canPlay() const
+{
+ return paused() || ended() || m_readyState < HAVE_METADATA;
+}
+
+bool HTMLMediaElement::havePotentialSourceChild()
+{
+ // Stash the current <source> node so we can restore it after checking
+ // to see there is another potential
+ Node* currentSourceNode = m_currentSourceNode;
+ String nextUrl = nextSourceChild();
+ m_currentSourceNode = currentSourceNode;
+
+ return !nextUrl.isEmpty();
+}
+
+String HTMLMediaElement::nextSourceChild(ContentType *contentType)
+{
+ String mediaSrc;
+ bool lookingForPreviousNode = m_currentSourceNode;
+
+ for (Node* node = firstChild(); node; node = node->nextSibling()) {
+ if (!node->hasTagName(sourceTag))
+ continue;
+
+ if (lookingForPreviousNode) {
+ if (m_currentSourceNode == node)
+ lookingForPreviousNode = false;
+ continue;
+ }
- // 5
- if (m_currentLoop < playCount() - 1 && time > effectiveLoopEnd()) {
- seek(effectiveLoopStart(), ec);
- m_currentLoop++;
+ HTMLSourceElement* source = static_cast<HTMLSourceElement*>(node);
+ if (!source->hasAttribute(srcAttr))
+ continue;
+ if (source->hasAttribute(mediaAttr)) {
+ MediaQueryEvaluator screenEval("screen", document()->frame(), renderer() ? renderer()->style() : 0);
+ RefPtr<MediaList> media = MediaList::createAllowingDescriptionSyntax(source->media());
+ if (!screenEval.eval(media.get()))
+ continue;
+ }
+ if (source->hasAttribute(typeAttr)) {
+ ContentType type(source->type());
+ if (!MediaPlayer::supportsType(type))
+ continue;
+
+ // return type with all parameters in place so the media engine can use them
+ if (contentType)
+ *contentType = type;
+ }
+ mediaSrc = source->src().string();
+ m_currentSourceNode = node;
+ break;
}
-
- // 6
- if (m_currentLoop == playCount() - 1 && time > effectiveEnd())
- seek(effectiveEnd(), ec);
- updatePlayState();
+ if (!mediaSrc.isEmpty())
+ mediaSrc = document()->completeURL(mediaSrc).string();
+
+ return mediaSrc;
}
void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*)
{
- if (readyState() >= CAN_PLAY)
+ beginProcessingMediaPlayerCallback();
+
+ if (m_readyState >= HAVE_CURRENT_DATA && m_seeking) {
+ scheduleEvent(eventNames().seekedEvent);
m_seeking = false;
-
- if (m_currentLoop < playCount() - 1 && currentTime() >= effectiveLoopEnd()) {
- ExceptionCode ec;
- seek(effectiveLoopStart(), ec);
- m_currentLoop++;
- dispatchEventForType(eventNames().timeupdateEvent, false, true);
}
- if (m_currentLoop == playCount() - 1 && currentTime() >= effectiveEnd()) {
- dispatchEventForType(eventNames().timeupdateEvent, false, true);
- dispatchEventForType(eventNames().endedEvent, false, true);
+ float now = currentTime();
+ float dur = duration();
+ if (now >= dur) {
+ if (loop()) {
+ ExceptionCode ignoredException;
+ m_sentEndEvent = false;
+ seek(0, ignoredException);
+ } else {
+ if (!m_sentEndEvent) {
+ m_sentEndEvent = true;
+ scheduleTimeupdateEvent(false);
+ scheduleEvent(eventNames().endedEvent);
+ }
+ }
}
+ else
+ m_sentEndEvent = false;
updatePlayState();
+ endProcessingMediaPlayerCallback();
}
void HTMLMediaElement::mediaPlayerRepaint(MediaPlayer*)
{
+ beginProcessingMediaPlayerCallback();
if (renderer())
renderer()->repaint();
+ endProcessingMediaPlayerCallback();
+}
+
+void HTMLMediaElement::mediaPlayerVolumeChanged(MediaPlayer*)
+{
+ beginProcessingMediaPlayerCallback();
+ updateVolume();
+ endProcessingMediaPlayerCallback();
+}
+
+void HTMLMediaElement::mediaPlayerDurationChanged(MediaPlayer*)
+{
+ beginProcessingMediaPlayerCallback();
+ scheduleEvent(eventNames().durationchangeEvent);
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ if (renderer()) {
+ renderer()->updateFromElement();
+ if (!renderer()->isImage())
+ static_cast<RenderVideo*>(renderer())->videoSizeChanged();
+ }
+#endif
+ endProcessingMediaPlayerCallback();
+}
+
+void HTMLMediaElement::mediaPlayerRateChanged(MediaPlayer*)
+{
+ beginProcessingMediaPlayerCallback();
+ // Stash the rate in case the one we tried to set isn't what the engine is
+ // using (eg. it can't handle the rate we set)
+ m_playbackRate = m_player->rate();
+ endProcessingMediaPlayerCallback();
+}
+
+void HTMLMediaElement::mediaPlayerSizeChanged(MediaPlayer*)
+{
+ beginProcessingMediaPlayerCallback();
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ if (renderer() && !renderer()->isImage())
+ static_cast<RenderVideo*>(renderer())->videoSizeChanged();
+#endif
+ endProcessingMediaPlayerCallback();
}
PassRefPtr<TimeRanges> HTMLMediaElement::buffered() const
@@ -931,53 +1217,45 @@ PassRefPtr<TimeRanges> HTMLMediaElement::seekable() const
return TimeRanges::create(0, m_player->maxTimeSeekable());
}
-float HTMLMediaElement::effectiveStart() const
+bool HTMLMediaElement::potentiallyPlaying() const
{
- if (!m_player)
- return 0;
- return min(start(), m_player->duration());
+ return !paused() && m_readyState >= HAVE_FUTURE_DATA && !endedPlayback() && !stoppedDueToErrors() && !pausedForUserInteraction();
}
-float HTMLMediaElement::effectiveEnd() const
-{
- if (!m_player)
- return 0;
- return min(max(end(), max(start(), loopStart())), m_player->duration());
-}
-
-float HTMLMediaElement::effectiveLoopStart() const
+bool HTMLMediaElement::endedPlayback() const
{
- if (!m_player)
- return 0;
- return min(loopStart(), m_player->duration());
+ return m_player && m_readyState >= HAVE_METADATA && currentTime() >= duration() && !loop();
}
-float HTMLMediaElement::effectiveLoopEnd() const
+bool HTMLMediaElement::stoppedDueToErrors() const
{
- if (!m_player)
- return 0;
- return min(max(start(), max(loopStart(), loopEnd())), m_player->duration());
+ if (m_readyState >= HAVE_METADATA && m_error) {
+ RefPtr<TimeRanges> seekableRanges = seekable();
+ if (!seekableRanges->contain(currentTime()))
+ return true;
+ }
+
+ return false;
}
-bool HTMLMediaElement::activelyPlaying() const
+bool HTMLMediaElement::pausedForUserInteraction() const
{
- return !paused() && readyState() >= CAN_PLAY && !endedPlayback(); // && !stoppedDueToErrors() && !pausedForUserInteraction();
+// return !paused() && m_readyState >= HAVE_FUTURE_DATA && [UA requires a decitions from the user]
+ return false;
}
-bool HTMLMediaElement::endedPlayback() const
-{
- return networkState() >= LOADED_METADATA && currentTime() >= effectiveEnd() && currentLoop() == playCount() - 1;
-}
-
void HTMLMediaElement::updateVolume()
{
if (!m_player)
return;
- Page* page = document()->page();
- float volumeMultiplier = page ? page->mediaVolume() : 1;
-
- m_player->setVolume(m_muted ? 0 : m_volume * volumeMultiplier);
+ // Avoid recursion when the player reports volume changes.
+ if (!processingMediaPlayerCallback()) {
+ Page* page = document()->page();
+ float volumeMultiplier = page ? page->mediaVolume() : 1;
+
+ m_player->setVolume(m_muted ? 0 : m_volume * volumeMultiplier);
+ }
if (renderer())
renderer()->updateFromElement();
@@ -987,20 +1265,26 @@ void HTMLMediaElement::updatePlayState()
{
if (!m_player)
return;
-
+
if (m_pausedInternal) {
if (!m_player->paused())
m_player->pause();
+ m_playbackProgressTimer.stop();
return;
}
- m_player->setEndTime(currentLoop() == playCount() - 1 ? effectiveEnd() : effectiveLoopEnd());
-
- bool shouldBePlaying = activelyPlaying() && currentTime() < effectiveEnd();
- if (shouldBePlaying && m_player->paused())
+ bool shouldBePlaying = potentiallyPlaying();
+ bool playerPaused = m_player->paused();
+ if (shouldBePlaying && playerPaused) {
+ // Set rate before calling play in case the rate was set before the media engine wasn't setup.
+ // The media engine should just stash the rate since it isn't already playing.
+ m_player->setRate(m_playbackRate);
m_player->play();
- else if (!shouldBePlaying && !m_player->paused())
+ startPlaybackProgressTimer();
+ } else if (!shouldBePlaying && !playerPaused) {
m_player->pause();
+ m_playbackProgressTimer.stop();
+ }
if (renderer())
renderer()->updateFromElement();
@@ -1012,25 +1296,50 @@ void HTMLMediaElement::setPausedInternal(bool b)
updatePlayState();
}
-void HTMLMediaElement::documentWillBecomeInactive()
+void HTMLMediaElement::stopPeriodicTimers()
+{
+ m_progressEventTimer.stop();
+ m_playbackProgressTimer.stop();
+}
+
+void HTMLMediaElement::userCancelledLoad()
{
- // 3.14.9.4. Loading the media resource
- // 14
- if (m_begun) {
- // For simplicity cancel the incomplete load by deleting the player
+ if (m_networkState != NETWORK_EMPTY) {
+
+ // If the media data fetching process is aborted by the user:
+
+ // 1 - The user agent should cancel the fetching process.
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
m_player.clear();
- m_progressEventTimer.stop();
+#endif
+ stopPeriodicTimers();
+ // 2 - Set the error attribute to a new MediaError object whose code attribute is set to MEDIA_ERR_ABORT.
m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED);
- m_begun = false;
- initAndDispatchProgressEvent(eventNames().abortEvent);
- if (m_networkState >= LOADING) {
- m_networkState = EMPTY;
- m_readyState = DATA_UNAVAILABLE;
- dispatchEventForType(eventNames().emptiedEvent, false, true);
+
+ // 3 - Queue a task to fire a progress event called abort at the media element.
+ scheduleProgressEvent(eventNames().abortEvent);
+
+ // 4 - If the media element's readyState attribute has a value equal to HAVE_NOTHING, set the
+ // element's networkState attribute to the NETWORK_EMPTY value and queue a task to fire a
+ // simple event called emptied at the element. Otherwise, set set the element's networkState
+ // attribute to the NETWORK_IDLE value.
+ if (m_networkState >= NETWORK_LOADING) {
+ m_networkState = NETWORK_EMPTY;
+ m_readyState = HAVE_NOTHING;
+ scheduleEvent(eventNames().emptiedEvent);
}
+
+ // 5 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
+ m_delayingTheLoadEvent = false;
}
+}
+
+void HTMLMediaElement::documentWillBecomeInactive()
+{
m_inActiveDocument = false;
+ userCancelledLoad();
+
// Stop the playback without generating events
setPausedInternal(true);
@@ -1045,6 +1354,8 @@ void HTMLMediaElement::documentDidBecomeActive()
if (m_error && m_error->code() == MediaError::MEDIA_ERR_ABORTED) {
// Restart the load if it was aborted in the middle by moving the document to the page cache.
+ // m_error is only left at MEDIA_ERR_ABORTED when the document becomes inactive (it is set to
+ // MEDIA_ERR_ABORTED while the abortEvent is being sent, but cleared immediately afterwards).
// This behavior is not specified but it seems like a sensible thing to do.
ExceptionCode ec;
load(ec);
@@ -1061,13 +1372,78 @@ void HTMLMediaElement::mediaVolumeDidChange()
void HTMLMediaElement::defaultEventHandler(Event* event)
{
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ RenderObject* r = renderer();
+ if (!r || !r->isWidget())
+ return;
+
+ Widget* widget = static_cast<RenderWidget*>(r)->widget();
+ if (widget)
+ widget->handleEvent(event);
+#else
if (renderer() && renderer()->isMedia())
static_cast<RenderMedia*>(renderer())->forwardEvent(event);
if (event->defaultHandled())
return;
HTMLElement::defaultEventHandler(event);
+#endif
}
+bool HTMLMediaElement::processingUserGesture() const
+{
+ Frame* frame = document()->frame();
+ FrameLoader* loader = frame ? frame->loader() : 0;
+
+ // return 'true' for safety if we don't know the answer
+ return loader ? loader->userGestureHint() : true;
+}
+
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+void HTMLMediaElement::deliverNotification(MediaPlayerProxyNotificationType notification)
+{
+ if (notification == MediaPlayerNotificationPlayPauseButtonPressed) {
+ ExceptionCode ec;
+ togglePlayState(ec);
+ return;
+ }
+
+ if (m_player)
+ m_player->deliverNotification(notification);
+}
+
+void HTMLMediaElement::setMediaPlayerProxy(WebMediaPlayerProxy* proxy)
+{
+ if (m_player)
+ m_player->setMediaPlayerProxy(proxy);
+}
+
+String HTMLMediaElement::initialURL()
+{
+ String initialSrc = mediaSrc = getAttribute(srcAttr);
+
+ if (initialSrc.isEmpty())
+ initialSrc = nextSourceChild();
+
+ if (!initialSrc.isEmpty())
+ initialSrc = document()->completeURL(initialSrc).string();
+
+ m_currentSrc = initialSrc;
+
+ return initialSrc;
+}
+
+void HTMLMediaElement::finishParsingChildren()
+{
+ HTMLElement::finishParsingChildren();
+ if (!m_player)
+ m_player.set(new MediaPlayer(this));
+
+ document()->updateRendering();
+ if (m_needWidgetUpdate && renderer())
+ static_cast<RenderPartObject*>(renderer())->updateWidget(true);
+}
+#endif
+
}
#endif
diff --git a/WebCore/html/HTMLMediaElement.h b/WebCore/html/HTMLMediaElement.h
index 6dd562c..ab0ab11 100644
--- a/WebCore/html/HTMLMediaElement.h
+++ b/WebCore/html/HTMLMediaElement.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,13 +31,17 @@
#include "HTMLElement.h"
#include "MediaPlayer.h"
#include "Timer.h"
-#include "VoidCallback.h"
+
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+#include "MediaPlayerProxy.h"
+#endif
namespace WebCore {
+class Event;
class MediaError;
-class TimeRanges;
class KURL;
+class TimeRanges;
class HTMLMediaElement : public HTMLElement, public MediaPlayerClient {
public:
@@ -58,6 +62,7 @@ public:
MediaPlayer* player() const { return m_player.get(); }
virtual bool isVideo() const { return false; }
+ virtual bool hasVideo() const { return false; }
void scheduleLoad();
@@ -76,15 +81,16 @@ public:
KURL src() const;
void setSrc(const String&);
String currentSrc() const;
-
- enum NetworkState { EMPTY, LOADING, LOADED_METADATA, LOADED_FIRST_FRAME, LOADED };
+
+ enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_LOADED, NETWORK_NO_SOURCE };
NetworkState networkState() const;
- float bufferingRate();
PassRefPtr<TimeRanges> buffered() const;
void load(ExceptionCode&);
+
+ String canPlayType(const String& mimeType) const;
// ready state
- enum ReadyState { DATA_UNAVAILABLE, CAN_SHOW_CURRENT_FRAME, CAN_PLAY, CAN_PLAY_THROUGH };
+ enum ReadyState { HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA };
ReadyState readyState() const;
bool seeking() const;
@@ -94,31 +100,19 @@ public:
float duration() const;
bool paused() const;
float defaultPlaybackRate() const;
- void setDefaultPlaybackRate(float, ExceptionCode&);
+ void setDefaultPlaybackRate(float);
float playbackRate() const;
- void setPlaybackRate(float, ExceptionCode&);
+ void setPlaybackRate(float);
PassRefPtr<TimeRanges> played() const;
PassRefPtr<TimeRanges> seekable() const;
bool ended() const;
bool autoplay() const;
void setAutoplay(bool b);
- void play(ExceptionCode&);
- void pause(ExceptionCode&);
-
-// looping
- float start() const;
- void setStart(float time);
- float end() const;
- void setEnd(float time);
- float loopStart() const;
- void setLoopStart(float time);
- float loopEnd() const;
- void setLoopEnd(float time);
- unsigned playCount() const;
- void setPlayCount(unsigned, ExceptionCode&);
- unsigned currentLoop() const;
- void setCurrentLoop(unsigned);
-
+ bool loop() const;
+ void setLoop(bool b);
+ void play();
+ void pause();
+
// controls
bool controls() const;
void setControls(bool);
@@ -126,9 +120,20 @@ public:
void setVolume(float, ExceptionCode&);
bool muted() const;
void setMuted(bool);
+ void togglePlayState();
+ void beginScrubbing();
+ void endScrubbing();
bool canPlay() const;
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; }
+ void deliverNotification(MediaPlayerProxyNotificationType notification);
+ void setMediaPlayerProxy(WebMediaPlayerProxy* proxy);
+ String initialURL();
+ virtual void finishParsingChildren();
+#endif
+
protected:
float getTimeOffsetAttribute(const QualifiedName&, float valueOnError) const;
void setTimeOffsetAttribute(const QualifiedName&, float value);
@@ -137,73 +142,136 @@ protected:
virtual void documentDidBecomeActive();
virtual void mediaVolumeDidChange();
- void initAndDispatchProgressEvent(const AtomicString& eventName);
- void dispatchEventAsync(const AtomicString& eventName);
-
- void setReadyState(ReadyState);
+ void setReadyState(MediaPlayer::ReadyState);
+ void setNetworkState(MediaPlayer::NetworkState);
private: // MediaPlayerObserver
virtual void mediaPlayerNetworkStateChanged(MediaPlayer*);
virtual void mediaPlayerReadyStateChanged(MediaPlayer*);
virtual void mediaPlayerTimeChanged(MediaPlayer*);
virtual void mediaPlayerRepaint(MediaPlayer*);
+ virtual void mediaPlayerVolumeChanged(MediaPlayer*);
+ virtual void mediaPlayerDurationChanged(MediaPlayer*);
+ virtual void mediaPlayerRateChanged(MediaPlayer*);
+ virtual void mediaPlayerSizeChanged(MediaPlayer*);
private:
void loadTimerFired(Timer<HTMLMediaElement>*);
void asyncEventTimerFired(Timer<HTMLMediaElement>*);
void progressEventTimerFired(Timer<HTMLMediaElement>*);
- void seek(float time, ExceptionCode& ec);
+ void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
+ void startPlaybackProgressTimer();
+ void startProgressEventTimer();
+ void stopPeriodicTimers();
+
+ void seek(float time, ExceptionCode&);
void checkIfSeekNeeded();
- String pickMedia();
+ void scheduleTimeupdateEvent(bool periodicEvent);
+ void scheduleProgressEvent(const AtomicString& eventName);
+ void scheduleEvent(const AtomicString& eventName);
+ void enqueueEvent(RefPtr<Event> event);
+
+ // loading
+ void selectMediaResource();
+ void loadResource(String url, ContentType& contentType);
+ void loadNextSourceChild();
+ void userCancelledLoad();
+ String nextSourceChild(ContentType* contentType = 0);
+ bool havePotentialSourceChild();
+ void noneSupported();
+ void mediaEngineError(PassRefPtr<MediaError> err);
+
+ // These "internal" functions do not check user gesture restrictions.
+ void loadInternal();
+ void playInternal();
+ void pauseInternal();
+
+ bool processingUserGesture() const;
+ bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; }
+ void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; }
+ void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; }
+
void updateVolume();
void updatePlayState();
- float effectiveStart() const;
- float effectiveEnd() const;
- float effectiveLoopStart() const;
- float effectiveLoopEnd() const;
- bool activelyPlaying() const;
+ bool potentiallyPlaying() const;
bool endedPlayback() const;
-
+ bool stoppedDueToErrors() const;
+ bool pausedForUserInteraction() const;
+
+ // Restrictions to change default behaviors. This is a effectively a compile time choice at the moment
+ // because there are no accessor methods.
+ enum BehaviorRestrictions
+ {
+ NoRestrictions = 0,
+ RequireUserGestureForLoadRestriction = 1 << 0,
+ RequireUserGestureForRateChangeRestriction = 1 << 1,
+ };
+
protected:
Timer<HTMLMediaElement> m_loadTimer;
Timer<HTMLMediaElement> m_asyncEventTimer;
Timer<HTMLMediaElement> m_progressEventTimer;
- Vector<AtomicString> m_asyncEventsToDispatch;
+ Timer<HTMLMediaElement> m_playbackProgressTimer;
+ Vector<RefPtr<Event> > m_pendingEvents;
+ float m_playbackRate;
float m_defaultPlaybackRate;
NetworkState m_networkState;
ReadyState m_readyState;
String m_currentSrc;
RefPtr<MediaError> m_error;
-
- bool m_begun;
- bool m_loadedFirstFrame;
- bool m_autoplaying;
-
- unsigned m_currentLoop;
+
float m_volume;
- bool m_muted;
-
- bool m_paused;
- bool m_seeking;
-
float m_currentTimeDuringSeek;
unsigned m_previousProgress;
double m_previousProgressTime;
- bool m_sentStalledEvent;
-
- float m_bufferingRate;
+
+ // the last time a timeupdate event was sent (wall clock)
+ double m_lastTimeUpdateEventWallTime;
+
+ // the last time a timeupdate event was sent in movie time
+ float m_lastTimeUpdateEventMovieTime;
- unsigned m_loadNestingLevel;
- unsigned m_terminateLoadBelowNestingLevel;
+ // loading state
+ enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
+ LoadState m_loadState;
+ Node *m_currentSourceNode;
- bool m_pausedInternal;
- bool m_inActiveDocument;
-
OwnPtr<MediaPlayer> m_player;
+
+ BehaviorRestrictions m_restrictions;
+
+ // counter incremented while processing a callback from the media player, so we can avoid
+ // calling the media engine recursively
+ int m_processingMediaPlayerCallback;
+
+ bool m_processingLoad : 1;
+ bool m_delayingTheLoadEvent : 1;
+ bool m_haveFiredLoadedData : 1;
+ bool m_inActiveDocument : 1;
+ bool m_autoplaying : 1;
+ bool m_muted : 1;
+ bool m_paused : 1;
+ bool m_seeking : 1;
+
+ // data has not been loaded since sending a "stalled" event
+ bool m_sentStalledEvent : 1;
+
+ // time has not changed since sending an "ended" event
+ bool m_sentEndEvent : 1;
+
+ bool m_pausedInternal : 1;
+
+ // Not all media engines provide enough information about a file to be able to
+ // support progress events so setting m_sendProgressEvents disables them
+ bool m_sendProgressEvents : 1;
+
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ bool m_needWidgetUpdate : 1;
+#endif
};
} //namespace
diff --git a/WebCore/html/HTMLMediaElement.idl b/WebCore/html/HTMLMediaElement.idl
index 1e3eb90..931980b 100644
--- a/WebCore/html/HTMLMediaElement.idl
+++ b/WebCore/html/HTMLMediaElement.idl
@@ -33,22 +33,24 @@ interface [GenerateConstructor, Conditional=VIDEO] HTMLMediaElement : HTMLElemen
attribute DOMString src;
readonly attribute DOMString currentSrc;
- const unsigned short EMPTY = 0;
- const unsigned short LOADING = 1;
- const unsigned short LOADED_METADATA = 2;
- const unsigned short LOADED_FIRST_FRAME = 3;
- const unsigned short LOADED = 4;
+ const unsigned short NETWORK_EMPTY = 0;
+ const unsigned short NETWORK_IDLE = 1;
+ const unsigned short NETWORK_LOADING = 2;
+ const unsigned short NETWORK_LOADED = 3;
+ const unsigned short NETWORK_NO_SOURCE = 4;
readonly attribute unsigned short networkState;
- readonly attribute float bufferingRate;
+
readonly attribute TimeRanges buffered;
void load()
raises (DOMException);
+ DOMString canPlayType(in DOMString type);
// ready state
- const unsigned short DATA_UNAVAILABLE = 0;
- const unsigned short CAN_SHOW_CURRENT_FRAME = 1;
- const unsigned short CAN_PLAY = 2;
- const unsigned short CAN_PLAY_THROUGH = 3;
+ const unsigned short HAVE_NOTHING = 0;
+ const unsigned short HAVE_METADATA = 1;
+ const unsigned short HAVE_CURRENT_DATA = 2;
+ const unsigned short HAVE_FUTURE_DATA = 3;
+ const unsigned short HAVE_ENOUGH_DATA = 4;
readonly attribute unsigned short readyState;
readonly attribute boolean seeking;
@@ -57,27 +59,15 @@ interface [GenerateConstructor, Conditional=VIDEO] HTMLMediaElement : HTMLElemen
setter raises (DOMException);
readonly attribute float duration;
readonly attribute boolean paused;
- attribute float defaultPlaybackRate
- setter raises (DOMException);
- attribute float playbackRate
- setter raises (DOMException);
+ attribute float defaultPlaybackRate;
+ attribute float playbackRate;
readonly attribute TimeRanges played;
readonly attribute TimeRanges seekable;
readonly attribute boolean ended;
attribute boolean autoplay;
- void play()
- raises (DOMException);
- void pause()
- raises (DOMException);
-
- // looping
- attribute float start;
- attribute float end;
- attribute float loopStart;
- attribute float loopEnd;
- attribute unsigned long playCount
- setter raises (DOMException);
- attribute unsigned long currentLoop;
+ attribute boolean loop;
+ void play();
+ void pause();
// controls
attribute boolean controls;
diff --git a/WebCore/html/HTMLObjectElement.cpp b/WebCore/html/HTMLObjectElement.cpp
index 6f85d18..a41e037 100644
--- a/WebCore/html/HTMLObjectElement.cpp
+++ b/WebCore/html/HTMLObjectElement.cpp
@@ -119,14 +119,15 @@ void HTMLObjectElement::parseMappedAttribute(MappedAttribute *attr)
bool HTMLObjectElement::rendererIsNeeded(RenderStyle* style)
{
- if (m_useFallbackContent || isImageType())
- return HTMLPlugInElement::rendererIsNeeded(style);
-
Frame* frame = document()->frame();
if (!frame)
return false;
- return true;
+ // Temporary Workaround for Gears plugin - see bug 24215 for details and bug 24346 to track removal.
+ // Gears expects the plugin to be instantiated even if display:none is set
+ // for the object element.
+ bool isGearsPlugin = equalIgnoringCase(getAttribute(typeAttr), "application/x-googlegears");
+ return isGearsPlugin || HTMLPlugInElement::rendererIsNeeded(style);
}
RenderObject *HTMLObjectElement::createRenderer(RenderArena* arena, RenderStyle* style)
@@ -156,7 +157,7 @@ void HTMLObjectElement::attach()
return;
if (renderer())
- static_cast<RenderImage*>(renderer())->setCachedImage(m_imageLoader->image());
+ toRenderImage(renderer())->setCachedImage(m_imageLoader->image());
}
}
diff --git a/WebCore/html/HTMLOptGroupElement.cpp b/WebCore/html/HTMLOptGroupElement.cpp
index 294472b..5c79e74 100644
--- a/WebCore/html/HTMLOptGroupElement.cpp
+++ b/WebCore/html/HTMLOptGroupElement.cpp
@@ -58,40 +58,30 @@ const AtomicString& HTMLOptGroupElement::type() const
bool HTMLOptGroupElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach)
{
bool result = HTMLFormControlElement::insertBefore(newChild, refChild, ec, shouldLazyAttach);
- if (result)
- recalcSelectOptions();
return result;
}
bool HTMLOptGroupElement::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach)
{
bool result = HTMLFormControlElement::replaceChild(newChild, oldChild, ec, shouldLazyAttach);
- if (result)
- recalcSelectOptions();
return result;
}
bool HTMLOptGroupElement::removeChild(Node* oldChild, ExceptionCode& ec)
{
bool result = HTMLFormControlElement::removeChild(oldChild, ec);
- if (result)
- recalcSelectOptions();
return result;
}
bool HTMLOptGroupElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach)
{
bool result = HTMLFormControlElement::appendChild(newChild, ec, shouldLazyAttach);
- if (result)
- recalcSelectOptions();
return result;
}
bool HTMLOptGroupElement::removeChildren()
{
bool result = HTMLFormControlElement::removeChildren();
- if (result)
- recalcSelectOptions();
return result;
}
diff --git a/WebCore/html/HTMLOptionElement.cpp b/WebCore/html/HTMLOptionElement.cpp
index 085019f..982f578 100644
--- a/WebCore/html/HTMLOptionElement.cpp
+++ b/WebCore/html/HTMLOptionElement.cpp
@@ -225,13 +225,16 @@ bool HTMLOptionElement::disabled() const
return HTMLFormControlElement::disabled() || (parentNode() && static_cast<HTMLFormControlElement*>(parentNode())->disabled());
}
-void HTMLOptionElement::insertedIntoDocument()
+void HTMLOptionElement::insertedIntoTree(bool deep)
{
- HTMLSelectElement* select;
- if (selected() && (select = ownerSelectElement()))
+ if (HTMLSelectElement* select = ownerSelectElement()) {
+ select->setRecalcListItems();
+ if (selected())
+ select->setSelectedIndex(index(), false);
select->scrollToSelection();
+ }
- HTMLFormControlElement::insertedIntoDocument();
+ HTMLFormControlElement::insertedIntoTree(deep);
}
} // namespace
diff --git a/WebCore/html/HTMLOptionElement.h b/WebCore/html/HTMLOptionElement.h
index 39b857c..8c0f260 100644
--- a/WebCore/html/HTMLOptionElement.h
+++ b/WebCore/html/HTMLOptionElement.h
@@ -77,7 +77,7 @@ public:
virtual bool disabled() const;
- virtual void insertedIntoDocument();
+ virtual void insertedIntoTree(bool);
virtual void accessKeyAction(bool);
private:
diff --git a/WebCore/html/HTMLParser.cpp b/WebCore/html/HTMLParser.cpp
index 0403dad..a4d4671 100644
--- a/WebCore/html/HTMLParser.cpp
+++ b/WebCore/html/HTMLParser.cpp
@@ -61,6 +61,13 @@ using namespace HTMLNames;
static const unsigned cMaxRedundantTagDepth = 20;
static const unsigned cResidualStyleMaxDepth = 200;
+static const int minBlockLevelTagPriority = 3;
+
+// A cap on the number of tags with priority minBlockLevelTagPriority or higher
+// allowed in m_blockStack. The cap is enforced by adding such new elements as
+// siblings instead of children once it is reached.
+static const size_t cMaxBlockDepth = 4096;
+
struct HTMLStackElem : Noncopyable {
HTMLStackElem(const AtomicString& t, int lvl, Node* n, bool r, HTMLStackElem* nx)
: tagName(t)
@@ -113,36 +120,38 @@ struct HTMLStackElem : Noncopyable {
*/
HTMLParser::HTMLParser(HTMLDocument* doc, bool reportErrors)
- : document(doc)
- , current(doc)
- , didRefCurrent(false)
- , blockStack(0)
+ : m_document(doc)
+ , m_current(doc)
+ , m_didRefCurrent(false)
+ , m_blockStack(0)
+ , m_blocksInStack(0)
, m_hasPElementInScope(NotInScope)
- , head(0)
- , inBody(false)
- , haveContent(false)
- , haveFrameSet(false)
+ , m_head(0)
+ , m_inBody(false)
+ , m_haveContent(false)
+ , m_haveFrameSet(false)
, m_isParsingFragment(false)
, m_reportErrors(reportErrors)
, m_handlingResidualStyleAcrossBlocks(false)
- , inStrayTableContent(0)
+ , m_inStrayTableContent(0)
{
}
HTMLParser::HTMLParser(DocumentFragment* frag)
- : document(frag->document())
- , current(frag)
- , didRefCurrent(true)
- , blockStack(0)
+ : m_document(frag->document())
+ , m_current(frag)
+ , m_didRefCurrent(true)
+ , m_blockStack(0)
+ , m_blocksInStack(0)
, m_hasPElementInScope(NotInScope)
- , head(0)
- , inBody(true)
- , haveContent(false)
- , haveFrameSet(false)
+ , m_head(0)
+ , m_inBody(true)
+ , m_haveContent(false)
+ , m_haveFrameSet(false)
, m_isParsingFragment(true)
, m_reportErrors(false)
, m_handlingResidualStyleAcrossBlocks(false)
- , inStrayTableContent(0)
+ , m_inStrayTableContent(0)
{
if (frag)
frag->ref();
@@ -151,26 +160,26 @@ HTMLParser::HTMLParser(DocumentFragment* frag)
HTMLParser::~HTMLParser()
{
freeBlock();
- if (didRefCurrent)
- current->deref();
+ if (m_didRefCurrent)
+ m_current->deref();
}
void HTMLParser::reset()
{
ASSERT(!m_isParsingFragment);
- setCurrent(document);
+ setCurrent(m_document);
freeBlock();
- inBody = false;
- haveFrameSet = false;
- haveContent = false;
- inStrayTableContent = 0;
+ m_inBody = false;
+ m_haveFrameSet = false;
+ m_haveContent = false;
+ m_inStrayTableContent = 0;
m_currentFormElement = 0;
m_currentMapElement = 0;
- head = 0;
+ m_head = 0;
m_isindexElement = 0;
m_skipModeTag = nullAtom;
@@ -178,13 +187,13 @@ void HTMLParser::reset()
void HTMLParser::setCurrent(Node* newCurrent)
{
- bool didRefNewCurrent = newCurrent && newCurrent != document;
+ bool didRefNewCurrent = newCurrent && newCurrent != m_document;
if (didRefNewCurrent)
newCurrent->ref();
- if (didRefCurrent)
- current->deref();
- current = newCurrent;
- didRefCurrent = didRefNewCurrent;
+ if (m_didRefCurrent)
+ m_current->deref();
+ m_current = newCurrent;
+ m_didRefCurrent = didRefNewCurrent;
}
PassRefPtr<Node> HTMLParser::parseToken(Token* t)
@@ -193,7 +202,7 @@ PassRefPtr<Node> HTMLParser::parseToken(Token* t)
if (!t->beginTag && t->tagName == m_skipModeTag)
// Found the end tag for the current skip mode, so we're done skipping.
m_skipModeTag = nullAtom;
- else if (current->localName() == t->tagName)
+ else if (m_current->localName() == t->tagName)
// Do not skip </iframe>.
// FIXME: What does that comment mean? How can it be right to parse a token without clearing m_skipModeTag?
;
@@ -202,7 +211,7 @@ PassRefPtr<Node> HTMLParser::parseToken(Token* t)
}
// Apparently some sites use </br> instead of <br>. Be compatible with IE and Firefox and treat this like <br>.
- if (t->isCloseTag(brTag) && document->inCompatMode()) {
+ if (t->isCloseTag(brTag) && m_document->inCompatMode()) {
reportError(MalformedBRError);
t->beginTag = true;
}
@@ -214,17 +223,17 @@ PassRefPtr<Node> HTMLParser::parseToken(Token* t)
// Ignore spaces, if we're not inside a paragraph or other inline code.
// Do not alter the text if it is part of a scriptTag.
- if (t->tagName == textAtom && t->text && current->localName() != scriptTag) {
- if (inBody && !skipMode() && current->localName() != styleTag &&
- current->localName() != titleTag && !t->text->containsOnlyWhitespace())
- haveContent = true;
+ if (t->tagName == textAtom && t->text && m_current->localName() != scriptTag) {
+ if (m_inBody && !skipMode() && m_current->localName() != styleTag &&
+ m_current->localName() != titleTag && !t->text->containsOnlyWhitespace())
+ m_haveContent = true;
RefPtr<Node> n;
String text = t->text.get();
unsigned charsLeft = text.length();
while (charsLeft) {
// split large blocks of text to nodes of manageable size
- n = Text::createWithLengthLimit(document, text, charsLeft);
+ n = Text::createWithLengthLimit(m_document, text, charsLeft);
if (!insertNode(n.get(), t->selfClosingTag))
return 0;
}
@@ -269,8 +278,8 @@ PassRefPtr<Node> HTMLParser::parseToken(Token* t)
if (m_currentFormElement == n)
m_currentFormElement = 0;
- if (head == n)
- head = 0;
+ if (m_head == n)
+ m_head = 0;
return 0;
}
@@ -280,25 +289,25 @@ PassRefPtr<Node> HTMLParser::parseToken(Token* t)
void HTMLParser::parseDoctypeToken(DoctypeToken* t)
{
// Ignore any doctype after the first. Ignore doctypes in fragments.
- if (document->doctype() || m_isParsingFragment || current != document)
+ if (m_document->doctype() || m_isParsingFragment || m_current != m_document)
return;
// Make a new doctype node and set it as our doctype.
- document->addChild(DocumentType::create(document, String::adopt(t->m_name), String::adopt(t->m_publicID), String::adopt(t->m_systemID)));
+ m_document->addChild(DocumentType::create(m_document, String::adopt(t->m_name), String::adopt(t->m_publicID), String::adopt(t->m_systemID)));
}
-static bool isTableSection(Node* n)
+static bool isTableSection(const Node* n)
{
return n->hasTagName(tbodyTag) || n->hasTagName(tfootTag) || n->hasTagName(theadTag);
}
-static bool isTablePart(Node* n)
+static bool isTablePart(const Node* n)
{
return n->hasTagName(trTag) || n->hasTagName(tdTag) || n->hasTagName(thTag) ||
isTableSection(n);
}
-static bool isTableRelated(Node* n)
+static bool isTableRelated(const Node* n)
{
return n->hasTagName(tableTag) || isTablePart(n);
}
@@ -317,33 +326,38 @@ bool HTMLParser::insertNode(Node* n, bool flat)
// <table> is never allowed inside stray table content. Always pop out of the stray table content
// and close up the first table, and then start the second table as a sibling.
- if (inStrayTableContent && localName == tableTag)
+ if (m_inStrayTableContent && localName == tableTag)
popBlock(tableTag);
-
+
+ if (tagPriority >= minBlockLevelTagPriority) {
+ while (m_blocksInStack >= cMaxBlockDepth)
+ popBlock(m_blockStack->tagName);
+ }
+
// let's be stupid and just try to insert it.
// this should work if the document is well-formed
- Node* newNode = current->addChild(n);
+ Node* newNode = m_current->addChild(n);
if (!newNode)
return handleError(n, flat, localName, tagPriority); // Try to handle the error.
// don't push elements without end tags (e.g., <img>) on the stack
- bool parentAttached = current->attached();
+ bool parentAttached = m_current->attached();
if (tagPriority > 0 && !flat) {
- if (newNode == current) {
+ if (newNode == m_current) {
// This case should only be hit when a demoted <form> is placed inside a table.
ASSERT(localName == formTag);
- reportError(FormInsideTablePartError, &current->localName());
+ reportError(FormInsideTablePartError, &m_current->localName());
} else {
// The pushBlock function transfers ownership of current to the block stack
- // so we're guaranteed that didRefCurrent is false. The code below is an
+ // so we're guaranteed that m_didRefCurrent is false. The code below is an
// optimized version of setCurrent that takes advantage of that fact and also
// assumes that newNode is neither 0 nor a pointer to the document.
pushBlock(localName, tagPriority);
newNode->beginParsingChildren();
- ASSERT(!didRefCurrent);
+ ASSERT(!m_didRefCurrent);
newNode->ref();
- current = newNode;
- didRefCurrent = true;
+ m_current = newNode;
+ m_didRefCurrent = true;
}
if (parentAttached && !n->attached() && !m_isParsingFragment)
n->attach();
@@ -353,6 +367,9 @@ bool HTMLParser::insertNode(Node* n, bool flat)
n->finishParsingChildren();
}
+ if (localName == htmlTag && m_document->frame())
+ m_document->frame()->loader()->dispatchDocumentElementAvailable();
+
return true;
}
@@ -366,28 +383,28 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
if (n->isHTMLElement()) {
HTMLElement* h = static_cast<HTMLElement*>(n);
if (h->hasLocalName(trTag) || h->hasLocalName(thTag) || h->hasLocalName(tdTag)) {
- if (inStrayTableContent && !isTableRelated(current)) {
- reportError(MisplacedTablePartError, &localName, &current->localName());
+ if (m_inStrayTableContent && !isTableRelated(m_current)) {
+ reportError(MisplacedTablePartError, &localName, &m_current->localName());
// pop out to the nearest enclosing table-related tag.
- while (blockStack && !isTableRelated(current))
+ while (m_blockStack && !isTableRelated(m_current))
popOneBlock();
return insertNode(n);
}
} else if (h->hasLocalName(headTag)) {
- if (!current->isDocumentNode() && !current->hasTagName(htmlTag)) {
+ if (!m_current->isDocumentNode() && !m_current->hasTagName(htmlTag)) {
reportError(MisplacedHeadError);
return false;
}
} else if (h->hasLocalName(metaTag) || h->hasLocalName(linkTag) || h->hasLocalName(baseTag)) {
bool createdHead = false;
- if (!head) {
+ if (!m_head) {
createHead();
createdHead = true;
}
- if (head) {
+ if (m_head) {
if (!createdHead)
- reportError(MisplacedHeadContentError, &localName, &current->localName());
- if (head->addChild(n)) {
+ reportError(MisplacedHeadContentError, &localName, &m_current->localName());
+ if (m_head->addChild(n)) {
if (!n->attached() && !m_isParsingFragment)
n->attach();
return true;
@@ -395,13 +412,13 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
return false;
}
} else if (h->hasLocalName(htmlTag)) {
- if (!current->isDocumentNode() ) {
- if (document->documentElement() && document->documentElement()->hasTagName(htmlTag)) {
+ if (!m_current->isDocumentNode() ) {
+ if (m_document->documentElement() && m_document->documentElement()->hasTagName(htmlTag)) {
reportError(RedundantHTMLBodyError, &localName);
// we have another <HTML> element.... apply attributes to existing one
// make sure we don't overwrite already existing attributes
NamedAttrMap* map = static_cast<Element*>(n)->attributes(true);
- Element* existingHTML = static_cast<Element*>(document->documentElement());
+ Element* existingHTML = static_cast<Element*>(m_document->documentElement());
NamedAttrMap* bmap = existingHTML->attributes(false);
for (unsigned l = 0; map && l < map->length(); ++l) {
Attribute* it = map->attributeItem(l);
@@ -413,19 +430,19 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
}
} else if (h->hasLocalName(titleTag) || h->hasLocalName(styleTag)) {
bool createdHead = false;
- if (!head) {
+ if (!m_head) {
createHead();
createdHead = true;
}
- if (head) {
- Node* newNode = head->addChild(n);
+ if (m_head) {
+ Node* newNode = m_head->addChild(n);
if (!newNode) {
setSkipMode(h->tagQName());
return false;
}
if (!createdHead)
- reportError(MisplacedHeadContentError, &localName, &current->localName());
+ reportError(MisplacedHeadContentError, &localName, &m_current->localName());
pushBlock(localName, tagPriority);
newNode->beginParsingChildren();
@@ -434,18 +451,18 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
n->attach();
return true;
}
- if (inBody) {
+ if (m_inBody) {
setSkipMode(h->tagQName());
return false;
}
} else if (h->hasLocalName(bodyTag)) {
- if (inBody && document->body()) {
+ if (m_inBody && m_document->body()) {
// we have another <BODY> element.... apply attributes to existing one
// make sure we don't overwrite already existing attributes
// some sites use <body bgcolor=rightcolor>...<body bgcolor=wrongcolor>
reportError(RedundantHTMLBodyError, &localName);
NamedAttrMap* map = static_cast<Element*>(n)->attributes(true);
- Element* existingBody = document->body();
+ Element* existingBody = m_document->body();
NamedAttrMap* bmap = existingBody->attributes(false);
for (unsigned l = 0; map && l < map->length(); ++l) {
Attribute* it = map->attributeItem(l);
@@ -454,11 +471,11 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
}
return false;
}
- else if (!current->isDocumentNode())
+ else if (!m_current->isDocumentNode())
return false;
} else if (h->hasLocalName(areaTag)) {
if (m_currentMapElement) {
- reportError(MisplacedAreaError, &current->localName());
+ reportError(MisplacedAreaError, &m_current->localName());
m_currentMapElement->addChild(n);
if (!n->attached() && !m_isParsingFragment)
n->attach();
@@ -467,18 +484,18 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
}
return false;
} else if (h->hasLocalName(colgroupTag) || h->hasLocalName(captionTag)) {
- if (isTableRelated(current)) {
- while (blockStack && isTablePart(current))
+ if (isTableRelated(m_current)) {
+ while (m_blockStack && isTablePart(m_current))
popOneBlock();
return insertNode(n);
}
}
- } else if (n->isCommentNode() && !head)
+ } else if (n->isCommentNode() && !m_head)
return false;
// 2. Next we examine our currently active element to do some further error handling.
- if (current->isHTMLElement()) {
- HTMLElement* h = static_cast<HTMLElement*>(current);
+ if (m_current->isHTMLElement()) {
+ HTMLElement* h = static_cast<HTMLElement*>(m_current);
const AtomicString& currentTagName = h->localName();
if (h->hasLocalName(htmlTag)) {
HTMLElement* elt = n->isHTMLElement() ? static_cast<HTMLElement*>(n) : 0;
@@ -487,9 +504,9 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
elt->hasLocalName(objectTag) || elt->hasLocalName(embedTag) ||
elt->hasLocalName(titleTag) || elt->hasLocalName(isindexTag) ||
elt->hasLocalName(baseTag))) {
- if (!head) {
- head = new HTMLHeadElement(headTag, document);
- e = head;
+ if (!m_head) {
+ m_head = new HTMLHeadElement(headTag, m_document);
+ e = m_head;
insertNode(e);
handled = true;
}
@@ -499,8 +516,8 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
if (t->containsOnlyWhitespace())
return false;
}
- if (!haveFrameSet) {
- e = new HTMLBodyElement(bodyTag, document);
+ if (!m_haveFrameSet) {
+ e = new HTMLBodyElement(bodyTag, m_document);
startBody();
insertNode(e);
handled = true;
@@ -512,9 +529,9 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
return false;
else {
// This means the body starts here...
- if (!haveFrameSet) {
+ if (!m_haveFrameSet) {
popBlock(currentTagName);
- e = new HTMLBodyElement(bodyTag, document);
+ e = new HTMLBodyElement(bodyTag, m_document);
startBody();
insertNode(e);
handled = true;
@@ -542,7 +559,7 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
handled = true; // ...and start a new one
} else {
ExceptionCode ec = 0;
- Node* node = current;
+ Node* node = m_current;
Node* parent = node->parentNode();
// A script may have removed the current node's parent from the DOM
// http://bugs.webkit.org/show_bug.cgi?id=7137
@@ -574,24 +591,24 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
pushBlock(localName, tagPriority);
n->beginParsingChildren();
setCurrent(n);
- inStrayTableContent++;
- blockStack->strayTableContent = true;
+ m_inStrayTableContent++;
+ m_blockStack->strayTableContent = true;
}
return true;
}
}
if (!ec) {
- if (current->hasTagName(trTag)) {
+ if (m_current->hasTagName(trTag)) {
reportError(TablePartRequiredError, &localName, &tdTag.localName());
- e = new HTMLTableCellElement(tdTag, document);
- } else if (current->hasTagName(tableTag)) {
+ e = new HTMLTableCellElement(tdTag, m_document);
+ } else if (m_current->hasTagName(tableTag)) {
// Don't report an error in this case, since making a <tbody> happens all the time when you have <table><tr>,
// and it isn't really a parse error per se.
- e = new HTMLTableSectionElement(tbodyTag, document);
+ e = new HTMLTableSectionElement(tbodyTag, m_document);
} else {
reportError(TablePartRequiredError, &localName, &trTag.localName());
- e = new HTMLTableRowElement(trTag, document);
+ e = new HTMLTableRowElement(trTag, m_document);
}
insertNode(e);
@@ -625,20 +642,20 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
popBlock(currentTagName);
handled = true;
} else if (!h->hasLocalName(bodyTag)) {
- if (isInline(current)) {
+ if (isInline(m_current)) {
popInlineBlocks();
handled = true;
}
}
- } else if (current->isDocumentNode()) {
+ } else if (m_current->isDocumentNode()) {
if (n->isTextNode()) {
Text* t = static_cast<Text*>(n);
if (t->containsOnlyWhitespace())
return false;
}
- if (!document->documentElement()) {
- e = new HTMLHtmlElement(htmlTag, document);
+ if (!m_document->documentElement()) {
+ e = new HTMLHtmlElement(htmlTag, m_document);
insertNode(e);
handled = true;
}
@@ -646,7 +663,7 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName,
// 3. If we couldn't handle the error, just return false and attempt to error-correct again.
if (!handled) {
- reportError(IgnoredContentError, &localName, &current->localName());
+ reportError(IgnoredContentError, &localName, &m_current->localName());
return false;
}
return insertNode(n);
@@ -657,21 +674,21 @@ typedef HashMap<AtomicStringImpl*, CreateErrorCheckFunc> FunctionMap;
bool HTMLParser::textCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
- result = new Text(document, t->text.get());
+ result = new Text(m_document, t->text.get());
return false;
}
bool HTMLParser::commentCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
- result = new Comment(document, t->text.get());
+ result = new Comment(m_document, t->text.get());
return false;
}
bool HTMLParser::headCreateErrorCheck(Token*, RefPtr<Node>& result)
{
- if (!head || current->localName() == htmlTag) {
- head = new HTMLHeadElement(headTag, document);
- result = head;
+ if (!m_head || m_current->localName() == htmlTag) {
+ m_head = new HTMLHeadElement(headTag, m_document);
+ result = m_head;
} else
reportError(MisplacedHeadError);
return false;
@@ -680,7 +697,7 @@ bool HTMLParser::headCreateErrorCheck(Token*, RefPtr<Node>& result)
bool HTMLParser::bodyCreateErrorCheck(Token*, RefPtr<Node>&)
{
// body no longer allowed if we have a frameset
- if (haveFrameSet)
+ if (m_haveFrameSet)
return false;
popBlock(headTag);
startBody();
@@ -690,19 +707,19 @@ bool HTMLParser::bodyCreateErrorCheck(Token*, RefPtr<Node>&)
bool HTMLParser::framesetCreateErrorCheck(Token*, RefPtr<Node>&)
{
popBlock(headTag);
- if (inBody && !haveFrameSet && !haveContent) {
+ if (m_inBody && !m_haveFrameSet && !m_haveContent) {
popBlock(bodyTag);
// ### actually for IE document.body returns the now hidden "body" element
// we can't implement that behaviour now because it could cause too many
// regressions and the headaches are not worth the work as long as there is
// no site actually relying on that detail (Dirk)
- if (document->body())
- document->body()->setAttribute(styleAttr, "display:none");
- inBody = false;
+ if (m_document->body())
+ m_document->body()->setAttribute(styleAttr, "display:none");
+ m_inBody = false;
}
- if ((haveContent || haveFrameSet) && current->localName() == htmlTag)
+ if ((m_haveContent || m_haveFrameSet) && m_current->localName() == htmlTag)
return false;
- haveFrameSet = true;
+ m_haveFrameSet = true;
startBody();
return true;
}
@@ -712,7 +729,7 @@ bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result)
// Only create a new form if we're not already inside one.
// This is consistent with other browsers' behavior.
if (!m_currentFormElement) {
- m_currentFormElement = new HTMLFormElement(formTag, document);
+ m_currentFormElement = new HTMLFormElement(formTag, m_document);
result = m_currentFormElement;
pCloserCreateErrorCheck(t, result);
}
@@ -722,7 +739,7 @@ bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result)
bool HTMLParser::isindexCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
RefPtr<Node> n = handleIsindex(t);
- if (!inBody)
+ if (!m_inBody)
m_isindexElement = n.release();
else {
t->selfClosingTag = true;
@@ -800,7 +817,7 @@ bool HTMLParser::noframesCreateErrorCheck(Token*, RefPtr<Node>&)
bool HTMLParser::noscriptCreateErrorCheck(Token*, RefPtr<Node>&)
{
if (!m_isParsingFragment) {
- Settings* settings = document->settings();
+ Settings* settings = m_document->settings();
if (settings && settings->isJavaScriptEnabled())
setSkipMode(noscriptTag);
}
@@ -816,7 +833,7 @@ bool HTMLParser::pCloserCreateErrorCheck(Token*, RefPtr<Node>&)
bool HTMLParser::pCloserStrictCreateErrorCheck(Token*, RefPtr<Node>&)
{
- if (document->inCompatMode())
+ if (m_document->inCompatMode())
return true;
if (hasPElementInScope())
popBlock(pTag);
@@ -825,7 +842,7 @@ bool HTMLParser::pCloserStrictCreateErrorCheck(Token*, RefPtr<Node>&)
bool HTMLParser::mapCreateErrorCheck(Token*, RefPtr<Node>& result)
{
- m_currentMapElement = new HTMLMapElement(mapTag, document);
+ m_currentMapElement = new HTMLMapElement(mapTag, m_document);
result = m_currentMapElement;
return false;
}
@@ -896,7 +913,7 @@ PassRefPtr<Node> HTMLParser::getNode(Token* t)
if (CreateErrorCheckFunc errorCheckFunc = gFunctionMap.get(t->tagName.impl()))
proceed = (this->*errorCheckFunc)(t, result);
if (proceed)
- result = HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, t->tagName, xhtmlNamespaceURI), document, m_currentFormElement.get());
+ result = HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, t->tagName, xhtmlNamespaceURI), m_document, m_currentFormElement.get());
return result.release();
}
@@ -906,7 +923,7 @@ bool HTMLParser::allowNestedRedundantTag(const AtomicString& tagName)
// about 1500 tags, all from a bunch of <b>s. We will only allow at most 20
// nested tags of the same type before just ignoring them all together.
unsigned i = 0;
- for (HTMLStackElem* curr = blockStack;
+ for (HTMLStackElem* curr = m_blockStack;
i < cMaxRedundantTagDepth && curr && curr->tagName == tagName;
curr = curr->next, i++) { }
return i != cMaxRedundantTagDepth;
@@ -929,9 +946,9 @@ void HTMLParser::processCloseTag(Token* t)
else if (t->tagName == pTag)
checkForCloseTagErrors = false;
- HTMLStackElem* oldElem = blockStack;
+ HTMLStackElem* oldElem = m_blockStack;
popBlock(t->tagName, checkForCloseTagErrors);
- if (oldElem == blockStack && t->tagName == pTag) {
+ if (oldElem == m_blockStack && t->tagName == pTag) {
// We encountered a stray </p>. Amazingly Gecko, WinIE, and MacIE all treat
// this as a valid break, i.e., <p></p>. So go ahead and make the empty
// paragraph.
@@ -976,7 +993,7 @@ bool HTMLParser::isInline(Node* node) const
e->hasLocalName(noembedTag))
return true;
if (e->hasLocalName(noscriptTag) && !m_isParsingFragment) {
- Settings* settings = document->settings();
+ Settings* settings = m_document->settings();
if (settings && settings->isJavaScriptEnabled())
return true;
}
@@ -1047,7 +1064,7 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem)
// Find the outermost element that crosses over to a higher level. If there exists another higher-level
// element, we will do another pass, until we have corrected the innermost one.
ExceptionCode ec = 0;
- HTMLStackElem* curr = blockStack;
+ HTMLStackElem* curr = m_blockStack;
HTMLStackElem* prev = 0;
HTMLStackElem* prevMaxElem = 0;
maxElem = 0;
@@ -1071,7 +1088,7 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem)
return;
Node* residualElem = prev->node;
- Node* blockElem = prevMaxElem ? prevMaxElem->node : current;
+ Node* blockElem = prevMaxElem ? prevMaxElem->node : m_current;
Node* parentElem = elem->node;
// Check to see if the reparenting that is going to occur is allowed according to the DOM.
@@ -1220,13 +1237,13 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem)
// <table><b><i><form></b></form></i></table>
// Then this check will be too simplistic. Right now the <i><form> chain will end up inside the <tbody>, which is pretty crazy.
if (strayTableContent)
- inStrayTableContent--;
+ m_inStrayTableContent--;
// Step 7: Reopen intermediate inlines, e.g., <b><p><i>Foo</b>Goo</p>.
// In the above example, Goo should stay italic.
// We cap the number of tags we're willing to reopen based off cResidualStyleMaxDepth.
- HTMLStackElem* curr = blockStack;
+ HTMLStackElem* curr = m_blockStack;
HTMLStackElem* residualStyleStack = 0;
unsigned stackDepth = 1;
unsigned redundantStyleCount = 0;
@@ -1254,7 +1271,7 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem)
} else
popOneBlock();
- curr = blockStack;
+ curr = m_blockStack;
}
reopenResidualStyleTags(residualStyleStack, 0); // Stray table content can't be an issue here, since some element above will always become the root of new stray table content.
@@ -1276,7 +1293,7 @@ void HTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTab
if (malformedTableParent)
malformedTableParent->insertBefore(newNode, malformedTableParent->lastChild(), ec);
else
- current->appendChild(newNode, ec);
+ m_current->appendChild(newNode, ec);
// FIXME: Is it really OK to ignore the exceptions here?
// Now push a new stack element for this node we just created.
@@ -1285,9 +1302,9 @@ void HTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTab
// Set our strayTableContent boolean if needed, so that the reopened tag also knows
// that it is inside a malformed table.
- blockStack->strayTableContent = malformedTableParent != 0;
- if (blockStack->strayTableContent)
- inStrayTableContent++;
+ m_blockStack->strayTableContent = malformedTableParent != 0;
+ if (m_blockStack->strayTableContent)
+ m_inStrayTableContent++;
// Clear our malformed table parent variable.
malformedTableParent = 0;
@@ -1305,8 +1322,10 @@ void HTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTab
void HTMLParser::pushBlock(const AtomicString& tagName, int level)
{
- blockStack = new HTMLStackElem(tagName, level, current, didRefCurrent, blockStack);
- didRefCurrent = false;
+ m_blockStack = new HTMLStackElem(tagName, level, m_current, m_didRefCurrent, m_blockStack);
+ if (level >= minBlockLevelTagPriority)
+ m_blocksInStack++;
+ m_didRefCurrent = false;
if (tagName == pTag)
m_hasPElementInScope = InScope;
else if (isScopingTag(tagName))
@@ -1315,7 +1334,7 @@ void HTMLParser::pushBlock(const AtomicString& tagName, int level)
void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors)
{
- HTMLStackElem* elem = blockStack;
+ HTMLStackElem* elem = m_blockStack;
int maxLevel = 0;
@@ -1343,12 +1362,12 @@ void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors)
HTMLStackElem* residualStyleStack = 0;
Node* malformedTableParent = 0;
- elem = blockStack;
+ elem = m_blockStack;
unsigned stackDepth = 1;
unsigned redundantStyleCount = 0;
while (elem) {
if (elem->tagName == tagName) {
- int strayTable = inStrayTableContent;
+ int strayTable = m_inStrayTableContent;
popOneBlock();
elem = 0;
@@ -1356,8 +1375,8 @@ void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors)
// explicit <tbody> or <tr>.
// If we end up needing to reopen residual style tags, the root of the reopened chain
// must also know that it is the root of malformed content inside a <tbody>/<tr>.
- if (strayTable && (inStrayTableContent < strayTable) && residualStyleStack) {
- Node* curr = current;
+ if (strayTable && (m_inStrayTableContent < strayTable) && residualStyleStack) {
+ Node* curr = m_current;
while (curr && !curr->hasTagName(tableTag))
curr = curr->parentNode();
malformedTableParent = curr ? curr->parentNode() : 0;
@@ -1392,7 +1411,7 @@ void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors)
popOneBlock();
} else
popOneBlock();
- elem = blockStack;
+ elem = m_blockStack;
}
}
@@ -1401,19 +1420,23 @@ void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors)
inline HTMLStackElem* HTMLParser::popOneBlockCommon()
{
- HTMLStackElem* elem = blockStack;
+ HTMLStackElem* elem = m_blockStack;
// Form elements restore their state during the parsing process.
// Also, a few elements (<applet>, <object>) need to know when all child elements (<param>s) are available.
- if (current && elem->node != current)
- current->finishParsingChildren();
+ if (m_current && elem->node != m_current)
+ m_current->finishParsingChildren();
- blockStack = elem->next;
- current = elem->node;
- didRefCurrent = elem->didRefNode;
+ if (m_blockStack->level >= minBlockLevelTagPriority) {
+ ASSERT(m_blocksInStack > 0);
+ m_blocksInStack--;
+ }
+ m_blockStack = elem->next;
+ m_current = elem->node;
+ m_didRefCurrent = elem->didRefNode;
if (elem->strayTableContent)
- inStrayTableContent--;
+ m_inStrayTableContent--;
if (elem->tagName == pTag)
m_hasPElementInScope = NotInScope;
@@ -1426,8 +1449,8 @@ inline HTMLStackElem* HTMLParser::popOneBlockCommon()
void HTMLParser::popOneBlock()
{
// Store the current node before popOneBlockCommon overwrites it.
- Node* lastCurrent = current;
- bool didRefLastCurrent = didRefCurrent;
+ Node* lastCurrent = m_current;
+ bool didRefLastCurrent = m_didRefCurrent;
delete popOneBlockCommon();
@@ -1441,8 +1464,8 @@ void HTMLParser::moveOneBlockToStack(HTMLStackElem*& head)
// See the two callers for details.
// Store the current node before popOneBlockCommon overwrites it.
- Node* lastCurrent = current;
- bool didRefLastCurrent = didRefCurrent;
+ Node* lastCurrent = m_current;
+ bool didRefLastCurrent = m_didRefCurrent;
// Pop the block, but don't deref the current node as popOneBlock does because
// we'll be using the pointer in the new stack element.
@@ -1450,7 +1473,7 @@ void HTMLParser::moveOneBlockToStack(HTMLStackElem*& head)
// Transfer the current node into the stack element.
// No need to deref the old elem->node because popOneBlockCommon transferred
- // it into the current/didRefCurrent fields.
+ // it into the m_current/m_didRefCurrent fields.
elem->node = lastCurrent;
elem->didRefNode = didRefLastCurrent;
elem->next = head;
@@ -1460,7 +1483,7 @@ void HTMLParser::moveOneBlockToStack(HTMLStackElem*& head)
void HTMLParser::checkIfHasPElementInScope()
{
m_hasPElementInScope = NotInScope;
- HTMLStackElem* elem = blockStack;
+ HTMLStackElem* elem = m_blockStack;
while (elem) {
const AtomicString& tagName = elem->tagName;
if (tagName == pTag) {
@@ -1474,42 +1497,43 @@ void HTMLParser::checkIfHasPElementInScope()
void HTMLParser::popInlineBlocks()
{
- while (blockStack && isInline(current))
+ while (m_blockStack && isInline(m_current))
popOneBlock();
}
void HTMLParser::freeBlock()
{
- while (blockStack)
+ while (m_blockStack)
popOneBlock();
+ ASSERT(!m_blocksInStack);
}
void HTMLParser::createHead()
{
- if (head || !document->documentElement())
+ if (m_head || !m_document->documentElement())
return;
- head = new HTMLHeadElement(headTag, document);
- HTMLElement* body = document->body();
+ m_head = new HTMLHeadElement(headTag, m_document);
+ HTMLElement* body = m_document->body();
ExceptionCode ec = 0;
- document->documentElement()->insertBefore(head, body, ec);
+ m_document->documentElement()->insertBefore(m_head, body, ec);
if (ec)
- head = 0;
+ m_head = 0;
// If the body does not exist yet, then the <head> should be pushed as the current block.
- if (head && !body) {
- pushBlock(head->localName(), head->tagPriority());
- setCurrent(head);
+ if (m_head && !body) {
+ pushBlock(m_head->localName(), m_head->tagPriority());
+ setCurrent(m_head);
}
}
PassRefPtr<Node> HTMLParser::handleIsindex(Token* t)
{
- RefPtr<Node> n = new HTMLDivElement(divTag, document);
+ RefPtr<Node> n = new HTMLDivElement(divTag, m_document);
NamedMappedAttrMap* attrs = t->attrs.get();
- RefPtr<HTMLIsIndexElement> isIndex = new HTMLIsIndexElement(isindexTag, document, m_currentFormElement.get());
+ RefPtr<HTMLIsIndexElement> isIndex = new HTMLIsIndexElement(isindexTag, m_document, m_currentFormElement.get());
isIndex->setAttributeMap(attrs);
isIndex->setAttribute(typeAttr, "khtml_isindex");
@@ -1520,20 +1544,20 @@ PassRefPtr<Node> HTMLParser::handleIsindex(Token* t)
t->attrs = 0;
}
- n->addChild(new HTMLHRElement(hrTag, document));
- n->addChild(new Text(document, text));
+ n->addChild(new HTMLHRElement(hrTag, m_document));
+ n->addChild(new Text(m_document, text));
n->addChild(isIndex.release());
- n->addChild(new HTMLHRElement(hrTag, document));
+ n->addChild(new HTMLHRElement(hrTag, m_document));
return n.release();
}
void HTMLParser::startBody()
{
- if (inBody)
+ if (m_inBody)
return;
- inBody = true;
+ m_inBody = true;
if (m_isindexElement) {
insertNode(m_isindexElement.get(), true /* don't descend into this node */);
@@ -1544,8 +1568,8 @@ void HTMLParser::startBody()
void HTMLParser::finished()
{
// In the case of a completely empty document, here's the place to create the HTML element.
- if (current && current->isDocumentNode() && !document->documentElement())
- insertNode(new HTMLHtmlElement(htmlTag, document));
+ if (m_current && m_current->isDocumentNode() && !m_document->documentElement())
+ insertNode(new HTMLHtmlElement(htmlTag, m_document));
// This ensures that "current" is not left pointing to a node when the document is destroyed.
freeBlock();
@@ -1553,16 +1577,16 @@ void HTMLParser::finished()
// Warning, this may delete the tokenizer and parser, so don't try to do anything else after this.
if (!m_isParsingFragment)
- document->finishedParsing();
+ m_document->finishedParsing();
}
void HTMLParser::reportErrorToConsole(HTMLParserErrorCode errorCode, const AtomicString* tagName1, const AtomicString* tagName2, bool closeTags)
{
- Frame* frame = document->frame();
+ Frame* frame = m_document->frame();
if (!frame)
return;
- HTMLTokenizer* htmlTokenizer = static_cast<HTMLTokenizer*>(document->tokenizer());
+ HTMLTokenizer* htmlTokenizer = static_cast<HTMLTokenizer*>(m_document->tokenizer());
int lineNumber = htmlTokenizer->lineNumber() + 1;
AtomicString tag1;
@@ -1597,7 +1621,7 @@ void HTMLParser::reportErrorToConsole(HTMLParserErrorCode errorCode, const Atomi
frame->domWindow()->console()->addMessage(HTMLMessageSource,
isWarning(errorCode) ? WarningMessageLevel : ErrorMessageLevel,
- message, lineNumber, document->url().string());
+ message, lineNumber, m_document->url().string());
}
}
diff --git a/WebCore/html/HTMLParser.h b/WebCore/html/HTMLParser.h
index 866835f..23fb980 100644
--- a/WebCore/html/HTMLParser.h
+++ b/WebCore/html/HTMLParser.h
@@ -150,33 +150,38 @@ private:
void reportErrorToConsole(HTMLParserErrorCode, const AtomicString* tagName1, const AtomicString* tagName2, bool closeTags);
- Document* document;
+ Document* m_document;
// The currently active element (the one new elements will be added to). Can be a document fragment, a document or an element.
- Node* current;
+ Node* m_current;
// We can't ref a document, but we don't want to constantly check if a node is a document just to decide whether to deref.
- bool didRefCurrent;
+ bool m_didRefCurrent;
- HTMLStackElem* blockStack;
+ HTMLStackElem* m_blockStack;
+
+ // The number of tags with priority minBlockLevelTagPriority or higher
+ // currently in m_blockStack. The parser enforces a cap on this value by
+ // adding such new elements as siblings instead of children once it is reached.
+ size_t m_blocksInStack;
enum ElementInScopeState { NotInScope, InScope, Unknown };
ElementInScopeState m_hasPElementInScope;
RefPtr<HTMLFormElement> m_currentFormElement; // currently active form
RefPtr<HTMLMapElement> m_currentMapElement; // current map
- HTMLHeadElement* head; // head element; needed for HTML which defines <base> after </head>
+ HTMLHeadElement* m_head; // head element; needed for HTML which defines <base> after </head>
RefPtr<Node> m_isindexElement; // a possible <isindex> element in the head
- bool inBody;
- bool haveContent;
- bool haveFrameSet;
+ bool m_inBody;
+ bool m_haveContent;
+ bool m_haveFrameSet;
AtomicString m_skipModeTag; // tells the parser to discard all tags until it reaches the one specified
bool m_isParsingFragment;
bool m_reportErrors;
bool m_handlingResidualStyleAcrossBlocks;
- int inStrayTableContent;
+ int m_inStrayTableContent;
};
}
diff --git a/WebCore/html/HTMLQuoteElement.cpp b/WebCore/html/HTMLQuoteElement.cpp
index 19164e2..e548215 100644
--- a/WebCore/html/HTMLQuoteElement.cpp
+++ b/WebCore/html/HTMLQuoteElement.cpp
@@ -22,6 +22,7 @@
#include "config.h"
#include "HTMLQuoteElement.h"
+#include "Document.h"
#include "HTMLNames.h"
namespace WebCore {
@@ -34,6 +35,13 @@ HTMLQuoteElement::HTMLQuoteElement(const QualifiedName& tagName, Document* doc)
ASSERT(hasTagName(qTag));
}
+void HTMLQuoteElement::insertedIntoDocument()
+{
+ document()->setUsesBeforeAfterRules(true);
+
+ HTMLElement::insertedIntoDocument();
+}
+
String HTMLQuoteElement::cite() const
{
return getAttribute(citeAttr);
diff --git a/WebCore/html/HTMLQuoteElement.h b/WebCore/html/HTMLQuoteElement.h
index 1e35431..623c28f 100644
--- a/WebCore/html/HTMLQuoteElement.h
+++ b/WebCore/html/HTMLQuoteElement.h
@@ -36,6 +36,8 @@ public:
virtual HTMLTagStatus endTagRequirement() const { return TagStatusRequired; }
virtual int tagPriority() const { return 1; }
+ virtual void insertedIntoDocument();
+
String cite() const;
void setCite(const String&);
};
diff --git a/WebCore/html/HTMLSelectElement.cpp b/WebCore/html/HTMLSelectElement.cpp
index 7a0ee29..107fbd0 100644
--- a/WebCore/html/HTMLSelectElement.cpp
+++ b/WebCore/html/HTMLSelectElement.cpp
@@ -2,7 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
* (C) 2006 Alexey Proskuryakov (ap@nypop.com)
*
* This library is free software; you can redistribute it and/or
@@ -67,6 +67,9 @@ using namespace HTMLNames;
static const DOMTimeStamp typeAheadTimeout = 1000;
+// Upper limit agreed upon with representatives of Opera and Mozilla.
+static const unsigned maxSelectItems = 10000;
+
HTMLSelectElement::HTMLSelectElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
: HTMLFormControlElementWithState(tagName, doc, f)
, m_minwidth(0)
@@ -218,10 +221,7 @@ void HTMLSelectElement::add(HTMLElement *element, HTMLElement *before, Exception
if (!element || !(element->hasLocalName(optionTag) || element->hasLocalName(hrTag)))
return;
- ec = 0;
insertBefore(element, before, ec);
- if (!ec)
- setRecalcListItems();
}
void HTMLSelectElement::remove(int index)
@@ -236,8 +236,6 @@ void HTMLSelectElement::remove(int index)
Element *item = items[listIndex];
ASSERT(item->parentNode());
item->parentNode()->removeChild(item, ec);
- if (!ec)
- setRecalcListItems();
}
String HTMLSelectElement::value()
@@ -296,46 +294,6 @@ void HTMLSelectElement::restoreState(const String& state)
setChanged();
}
-bool HTMLSelectElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach)
-{
- bool result = HTMLFormControlElementWithState::insertBefore(newChild, refChild, ec, shouldLazyAttach);
- if (result)
- setRecalcListItems();
- return result;
-}
-
-bool HTMLSelectElement::replaceChild(PassRefPtr<Node> newChild, Node *oldChild, ExceptionCode& ec, bool shouldLazyAttach)
-{
- bool result = HTMLFormControlElementWithState::replaceChild(newChild, oldChild, ec, shouldLazyAttach);
- if (result)
- setRecalcListItems();
- return result;
-}
-
-bool HTMLSelectElement::removeChild(Node* oldChild, ExceptionCode& ec)
-{
- bool result = HTMLFormControlElementWithState::removeChild(oldChild, ec);
- if (result)
- setRecalcListItems();
- return result;
-}
-
-bool HTMLSelectElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach)
-{
- bool result = HTMLFormControlElementWithState::appendChild(newChild, ec, shouldLazyAttach);
- if (result)
- setRecalcListItems();
- return result;
-}
-
-bool HTMLSelectElement::removeChildren()
-{
- bool result = HTMLFormControlElementWithState::removeChildren();
- if (result)
- setRecalcListItems();
- return result;
-}
-
void HTMLSelectElement::parseMappedAttribute(MappedAttribute *attr)
{
bool oldUsesMenuList = usesMenuList();
@@ -349,7 +307,7 @@ void HTMLSelectElement::parseMappedAttribute(MappedAttribute *attr)
attr->setValue(attrSize);
m_size = max(size, 1);
- if ((oldUsesMenuList != usesMenuList() || !oldUsesMenuList && m_size != oldSize) && attached()) {
+ if ((oldUsesMenuList != usesMenuList() || (!oldUsesMenuList && m_size != oldSize)) && attached()) {
detach();
attach();
setRecalcListItems();
@@ -422,6 +380,9 @@ RenderObject* HTMLSelectElement::createRenderer(RenderArena* arena, RenderStyle*
bool HTMLSelectElement::appendFormData(FormDataList& list, bool)
{
+ if (name().isEmpty())
+ return false;
+
bool successful = false;
const Vector<HTMLElement*>& items = listItems();
@@ -536,6 +497,7 @@ void HTMLSelectElement::childrenChanged(bool changedByParser, Node* beforeChange
void HTMLSelectElement::setRecalcListItems()
{
m_recalcListItems = true;
+ m_activeSelectionAnchorIndex = -1; // Manual selection anchor is reset when manipulating the select programmatically.
if (renderer()) {
if (usesMenuList())
static_cast<RenderMenuList*>(renderer())->setOptionsChanged(true);
@@ -617,8 +579,6 @@ void HTMLSelectElement::defaultEventHandler(Event* evt)
void HTMLSelectElement::menuListDefaultEventHandler(Event* evt)
{
- RenderMenuList* menuList = static_cast<RenderMenuList*>(renderer());
-
if (evt->type() == eventNames().keydownEvent) {
if (!renderer() || !evt->isKeyboardEvent())
return;
@@ -630,7 +590,8 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* evt)
// Save the selection so it can be compared to the new selection when we call onChange during setSelectedIndex,
// which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
saveLastSelection();
- menuList->showPopup();
+ if (RenderMenuList* menuList = static_cast<RenderMenuList*>(renderer()))
+ menuList->showPopup();
handled = true;
}
#elif defined ANDROID_KEYBOARD_NAVIGATION
@@ -677,7 +638,8 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* evt)
// Save the selection so it can be compared to the new selection when we call onChange during setSelectedIndex,
// which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
saveLastSelection();
- menuList->showPopup();
+ if (RenderMenuList* menuList = static_cast<RenderMenuList*>(renderer()))
+ menuList->showPopup();
handled = true;
}
if (keyCode == '\r') {
@@ -700,13 +662,15 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* evt)
if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
focus();
- if (menuList->popupIsVisible())
- menuList->hidePopup();
- else {
- // Save the selection so it can be compared to the new selection when we call onChange during setSelectedIndex,
- // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
- saveLastSelection();
- menuList->showPopup();
+ if (RenderMenuList* menuList = static_cast<RenderMenuList*>(renderer())) {
+ if (menuList->popupIsVisible())
+ menuList->hidePopup();
+ else {
+ // Save the selection so it can be compared to the new selection when we call onChange during setSelectedIndex,
+ // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
+ saveLastSelection();
+ menuList->showPopup();
+ }
}
evt->setDefaultHandled();
}
@@ -716,9 +680,11 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* evt)
{
if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
focus();
-
- MouseEvent* mEvt = static_cast<MouseEvent*>(evt);
- int listIndex = static_cast<RenderListBox*>(renderer())->listIndexAtOffset(mEvt->offsetX(), mEvt->offsetY());
+
+ // Convert to coords relative to the list box if needed.
+ MouseEvent* mouseEvent = static_cast<MouseEvent*>(evt);
+ IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouseEvent->absoluteLocation(), false, true));
+ int listIndex = static_cast<RenderListBox*>(renderer())->listIndexAtOffset(localOffset.x(), localOffset.y());
if (listIndex >= 0) {
// Save the selection so it can be compared to the new selection when we call onChange during mouseup, or after autoscroll finishes.
saveLastSelection();
@@ -727,13 +693,13 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* evt)
bool multiSelectKeyPressed = false;
#if PLATFORM(MAC)
- multiSelectKeyPressed = mEvt->metaKey();
+ multiSelectKeyPressed = mouseEvent->metaKey();
#else
- multiSelectKeyPressed = mEvt->ctrlKey();
+ multiSelectKeyPressed = mouseEvent->ctrlKey();
#endif
- bool shiftSelect = multiple() && mEvt->shiftKey();
- bool multiSelect = multiple() && multiSelectKeyPressed && !mEvt->shiftKey();
+ bool shiftSelect = multiple() && mouseEvent->shiftKey();
+ bool multiSelect = multiple() && multiSelectKeyPressed && !mouseEvent->shiftKey();
HTMLElement* clickedElement = listItems()[listIndex];
HTMLOptionElement* option = 0;
@@ -1068,8 +1034,8 @@ Node* HTMLSelectElement::item(unsigned index)
void HTMLSelectElement::setOption(unsigned index, HTMLOptionElement* option, ExceptionCode& ec)
{
ec = 0;
- if (index > INT_MAX)
- index = INT_MAX;
+ if (index > maxSelectItems - 1)
+ index = maxSelectItems - 1;
int diff = index - length();
HTMLElement* before = 0;
// out of array bounds ? first insert empty dummies
@@ -1091,15 +1057,14 @@ void HTMLSelectElement::setOption(unsigned index, HTMLOptionElement* option, Exc
void HTMLSelectElement::setLength(unsigned newLen, ExceptionCode& ec)
{
ec = 0;
- if (newLen > INT_MAX)
- newLen = INT_MAX;
+ if (newLen > maxSelectItems)
+ newLen = maxSelectItems;
int diff = length() - newLen;
if (diff < 0) { // add dummy elements
do {
- RefPtr<Element> option = document()->createElement("option", ec);
- if (!option)
- break;
+ RefPtr<Element> option = document()->createElement(optionTag, false);
+ ASSERT(option);
add(static_cast<HTMLElement*>(option.get()), 0, ec);
if (ec)
break;
diff --git a/WebCore/html/HTMLSelectElement.h b/WebCore/html/HTMLSelectElement.h
index ec49a82..59e4a4b 100644
--- a/WebCore/html/HTMLSelectElement.h
+++ b/WebCore/html/HTMLSelectElement.h
@@ -81,11 +81,6 @@ public:
virtual bool saveState(String& value) const;
virtual void restoreState(const String&);
- virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&, bool shouldLazyAttach = false);
- virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&, bool shouldLazyAttach = false);
- virtual bool removeChild(Node* child, ExceptionCode&);
- virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&, bool shouldLazyAttach = false);
- virtual bool removeChildren();
virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
virtual void parseMappedAttribute(MappedAttribute*);
diff --git a/WebCore/html/HTMLSourceElement.cpp b/WebCore/html/HTMLSourceElement.cpp
index c8f814f..609bcbf 100644
--- a/WebCore/html/HTMLSourceElement.cpp
+++ b/WebCore/html/HTMLSourceElement.cpp
@@ -53,7 +53,7 @@ void HTMLSourceElement::insertedIntoDocument()
HTMLElement::insertedIntoDocument();
if (parentNode() && (parentNode()->hasTagName(audioTag) || parentNode()->hasTagName(videoTag))) {
HTMLMediaElement* media = static_cast<HTMLMediaElement*>(parentNode());
- if (media->networkState() == HTMLMediaElement::EMPTY)
+ if (media->networkState() == HTMLMediaElement::NETWORK_EMPTY)
media->scheduleLoad();
}
}
diff --git a/WebCore/html/HTMLTagNames.in b/WebCore/html/HTMLTagNames.in
index 1697ebe..8b1fa2b 100644
--- a/WebCore/html/HTMLTagNames.in
+++ b/WebCore/html/HTMLTagNames.in
@@ -52,7 +52,7 @@ hr interfaceName=HTMLHRElement
html
i interfaceName=HTMLElement
iframe interfaceName=HTMLIFrameElement, constructorNeedsCreatedByParser
-image
+image mapToTagName=img
img interfaceName=HTMLImageElement, constructorNeedsFormElement
input constructorNeedsFormElement
ins interfaceName=HTMLModElement
diff --git a/WebCore/html/HTMLTextAreaElement.cpp b/WebCore/html/HTMLTextAreaElement.cpp
index 091718b..4eec088 100644
--- a/WebCore/html/HTMLTextAreaElement.cpp
+++ b/WebCore/html/HTMLTextAreaElement.cpp
@@ -37,7 +37,7 @@
#include "Page.h"
#include "RenderStyle.h"
#include "RenderTextControlMultiLine.h"
-#include "Selection.h"
+#include "VisibleSelection.h"
#include "Text.h"
#include <wtf/StdLibExtras.h>
@@ -96,7 +96,7 @@ int HTMLTextAreaElement::selectionStart()
return 0;
if (document()->focusedNode() != this && m_cachedSelectionStart >= 0)
return m_cachedSelectionStart;
- return static_cast<RenderTextControl*>(renderer())->selectionStart();
+ return toRenderTextControl(renderer())->selectionStart();
}
int HTMLTextAreaElement::selectionEnd()
@@ -105,35 +105,35 @@ int HTMLTextAreaElement::selectionEnd()
return 0;
if (document()->focusedNode() != this && m_cachedSelectionEnd >= 0)
return m_cachedSelectionEnd;
- return static_cast<RenderTextControl*>(renderer())->selectionEnd();
+ return toRenderTextControl(renderer())->selectionEnd();
}
void HTMLTextAreaElement::setSelectionStart(int start)
{
if (!renderer())
return;
- static_cast<RenderTextControl*>(renderer())->setSelectionStart(start);
+ toRenderTextControl(renderer())->setSelectionStart(start);
}
void HTMLTextAreaElement::setSelectionEnd(int end)
{
if (!renderer())
return;
- static_cast<RenderTextControl*>(renderer())->setSelectionEnd(end);
+ toRenderTextControl(renderer())->setSelectionEnd(end);
}
void HTMLTextAreaElement::select()
{
if (!renderer())
return;
- static_cast<RenderTextControl*>(renderer())->select();
+ toRenderTextControl(renderer())->select();
}
void HTMLTextAreaElement::setSelectionRange(int start, int end)
{
if (!renderer())
return;
- static_cast<RenderTextControl*>(renderer())->setSelectionRange(start, end);
+ toRenderTextControl(renderer())->setSelectionRange(start, end);
}
void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
@@ -206,7 +206,7 @@ bool HTMLTextAreaElement::appendFormData(FormDataList& encoding, bool)
// FIXME: It's not acceptable to ignore the HardWrap setting when there is no renderer.
// While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
- RenderTextControl* control = static_cast<RenderTextControl*>(renderer());
+ RenderTextControl* control = toRenderTextControl(renderer());
const String& text = (m_wrap == HardWrap && control) ? control->textWithHardLineBreaks() : value();
encoding.appendData(name(), text);
return true;
@@ -233,10 +233,17 @@ void HTMLTextAreaElement::updateFocusAppearance(bool restorePreviousSelection)
ASSERT(renderer());
if (!restorePreviousSelection || m_cachedSelectionStart < 0) {
+#if ENABLE(ON_FIRST_TEXTAREA_FOCUS_SELECT_ALL)
+ // Devices with trackballs or d-pads may focus on a textarea in route
+ // to another focusable node. By selecting all text, the next movement
+ // can more readily be interpreted as moving to the next node.
+ select();
+#else
// If this is the first focus, set a caret at the beginning of the text.
// This matches some browsers' behavior; see bug 11746 Comment #15.
// http://bugs.webkit.org/show_bug.cgi?id=11746#c15
setSelectionRange(0, 0);
+#endif
} else {
// Restore the cached selection. This matches other browsers' behavior.
setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd);
@@ -265,7 +272,7 @@ void HTMLTextAreaElement::updateValue() const
return;
ASSERT(renderer());
- m_value = static_cast<RenderTextControl*>(renderer())->text();
+ m_value = toRenderTextControl(renderer())->text();
const_cast<HTMLTextAreaElement*>(this)->setValueMatchesRenderer();
notifyFormStateChanged(this);
}
@@ -382,11 +389,11 @@ void HTMLTextAreaElement::setRows(int rows)
setAttribute(rowsAttr, String::number(rows));
}
-Selection HTMLTextAreaElement::selection() const
+VisibleSelection HTMLTextAreaElement::selection() const
{
if (!renderer() || m_cachedSelectionStart < 0 || m_cachedSelectionEnd < 0)
- return Selection();
- return static_cast<RenderTextControl*>(renderer())->selection(m_cachedSelectionStart, m_cachedSelectionEnd);
+ return VisibleSelection();
+ return toRenderTextControl(renderer())->selection(m_cachedSelectionStart, m_cachedSelectionEnd);
}
bool HTMLTextAreaElement::shouldUseInputMethod() const
diff --git a/WebCore/html/HTMLTextAreaElement.h b/WebCore/html/HTMLTextAreaElement.h
index f02ad65..f78386c 100644
--- a/WebCore/html/HTMLTextAreaElement.h
+++ b/WebCore/html/HTMLTextAreaElement.h
@@ -28,7 +28,7 @@
namespace WebCore {
-class Selection;
+class VisibleSelection;
class HTMLTextAreaElement : public HTMLFormControlElementWithState {
public:
@@ -87,7 +87,7 @@ public:
void setRows(int);
void cacheSelection(int s, int e) { m_cachedSelectionStart = s; m_cachedSelectionEnd = e; };
- Selection selection() const;
+ VisibleSelection selection() const;
virtual bool shouldUseInputMethod() const;
diff --git a/WebCore/html/HTMLTokenizer.cpp b/WebCore/html/HTMLTokenizer.cpp
index b01d4e4..e4952f7 100644
--- a/WebCore/html/HTMLTokenizer.cpp
+++ b/WebCore/html/HTMLTokenizer.cpp
@@ -143,7 +143,7 @@ inline void Token::addAttribute(AtomicString& attrName, const AtomicString& attr
RefPtr<MappedAttribute> a = MappedAttribute::create(attrName, attributeValue);
if (!attrs) {
attrs = NamedMappedAttrMap::create();
- attrs->reserveCapacity(10);
+ attrs->reserveInitialCapacity(10);
}
attrs->insertAttribute(a.release(), viewSourceMode);
}
@@ -448,15 +448,6 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state)
m_scriptTagSrcAttrValue = String();
} else {
// Parse m_scriptCode containing <script> info
-#if USE(LOW_BANDWIDTH_DISPLAY)
- if (m_doc->inLowBandwidthDisplay()) {
- // ideal solution is only skipping internal JavaScript if there is external JavaScript.
- // but internal JavaScript can use document.write() to create an external JavaScript,
- // so we have to skip internal JavaScript all the time.
- m_doc->frame()->loader()->needToSwitchOutLowBandwidthDisplay();
- doScriptExec = false;
- } else
-#endif
doScriptExec = m_scriptNode->shouldExecuteAsJavaScript();
m_scriptNode = 0;
}
@@ -1600,13 +1591,13 @@ inline bool HTMLTokenizer::continueProcessing(int& processedCount, double startT
return true;
}
-bool HTMLTokenizer::write(const SegmentedString& str, bool appendData)
+void HTMLTokenizer::write(const SegmentedString& str, bool appendData)
{
if (!m_buffer)
- return false;
+ return;
if (m_parserStopped)
- return false;
+ return;
SegmentedString source(str);
if (m_executingScript)
@@ -1623,7 +1614,7 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData)
m_preloadScanner->write(source);
#endif
}
- return false;
+ return;
}
@@ -1639,7 +1630,7 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData)
// Once a timer is set, it has control of when the tokenizer continues.
if (m_timer.isActive())
- return false;
+ return;
bool wasInWrite = m_inWrite;
m_inWrite = true;
@@ -1784,11 +1775,8 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData)
android::TimeCounter::record(android::TimeCounter::ParsingTimeCounter, __FUNCTION__);
#endif
- if (m_noMoreData && !m_inWrite && !state.loadingExtScript() && !m_executingScript && !m_timer.isActive()) {
+ if (m_noMoreData && !m_inWrite && !state.loadingExtScript() && !m_executingScript && !m_timer.isActive())
end(); // this actually causes us to be deleted
- return true;
- }
- return false;
}
void HTMLTokenizer::stopParsing()
@@ -2004,11 +1992,11 @@ void HTMLTokenizer::notifyFinished(CachedResource*)
#endif
if (errorOccurred)
- EventTargetNodeCast(n.get())->dispatchEventForType(eventNames().errorEvent, true, false);
+ n->dispatchEventForType(eventNames().errorEvent, true, false);
else {
if (static_cast<HTMLScriptElement*>(n.get())->shouldExecuteAsJavaScript())
m_state = scriptExecution(sourceCode, m_state);
- EventTargetNodeCast(n.get())->dispatchEventForType(eventNames().loadEvent, false, false);
+ n->dispatchEventForType(eventNames().loadEvent, false, false);
}
// The state of m_pendingScripts.isEmpty() can change inside the scriptExecution()
diff --git a/WebCore/html/HTMLTokenizer.h b/WebCore/html/HTMLTokenizer.h
index b4453af..2896974 100644
--- a/WebCore/html/HTMLTokenizer.h
+++ b/WebCore/html/HTMLTokenizer.h
@@ -138,7 +138,7 @@ public:
HTMLTokenizer(DocumentFragment*);
virtual ~HTMLTokenizer();
- virtual bool write(const SegmentedString&, bool appendData);
+ virtual void write(const SegmentedString&, bool appendData);
virtual void finish();
virtual void setForceSynchronous(bool force);
virtual bool isWaitingForScripts() const;
diff --git a/WebCore/html/HTMLVideoElement.cpp b/WebCore/html/HTMLVideoElement.cpp
index a67db71..b0aac3c 100644
--- a/WebCore/html/HTMLVideoElement.cpp
+++ b/WebCore/html/HTMLVideoElement.cpp
@@ -52,27 +52,30 @@ bool HTMLVideoElement::rendererIsNeeded(RenderStyle* style)
return HTMLElement::rendererIsNeeded(style);
}
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
RenderObject* HTMLVideoElement::createRenderer(RenderArena* arena, RenderStyle*)
{
if (m_shouldShowPosterImage)
return new (arena) RenderImage(this);
return new (arena) RenderVideo(this);
}
+#endif
void HTMLVideoElement::attach()
{
HTMLMediaElement::attach();
-
+
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
if (m_shouldShowPosterImage) {
if (!m_imageLoader)
m_imageLoader.set(new HTMLImageLoader(this));
m_imageLoader->updateFromElement();
if (renderer() && renderer()->isImage()) {
- RenderImage* imageRenderer = static_cast<RenderImage*>(renderer());
+ RenderImage* imageRenderer = toRenderImage(renderer());
imageRenderer->setCachedImage(m_imageLoader->image());
}
}
-
+#endif
}
void HTMLVideoElement::detach()
@@ -91,9 +94,14 @@ void HTMLVideoElement::parseMappedAttribute(MappedAttribute* attr)
if (attrName == posterAttr) {
updatePosterImage();
if (m_shouldShowPosterImage) {
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
if (!m_imageLoader)
m_imageLoader.set(new HTMLImageLoader(this));
m_imageLoader->updateFromElementIgnoringPreviousError();
+#else
+ if (m_player)
+ m_player->setPoster(poster());
+#endif
}
} else if (attrName == widthAttr)
addCSSLength(attr, CSSPropertyWidth, attr->value());
@@ -163,12 +171,18 @@ const QualifiedName& HTMLVideoElement::imageSourceAttributeName() const
void HTMLVideoElement::updatePosterImage()
{
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
bool oldShouldShowPosterImage = m_shouldShowPosterImage;
- m_shouldShowPosterImage = !poster().isEmpty() && m_networkState < LOADED_FIRST_FRAME;
+#endif
+
+ m_shouldShowPosterImage = !poster().isEmpty() && readyState() < HAVE_CURRENT_DATA;
+
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
if (attached() && oldShouldShowPosterImage != m_shouldShowPosterImage) {
detach();
attach();
}
+#endif
}
}
diff --git a/WebCore/html/HTMLVideoElement.h b/WebCore/html/HTMLVideoElement.h
index 8779c85..d35f3f8 100644
--- a/WebCore/html/HTMLVideoElement.h
+++ b/WebCore/html/HTMLVideoElement.h
@@ -42,11 +42,14 @@ public:
virtual int tagPriority() const { return 5; }
virtual bool rendererIsNeeded(RenderStyle*);
+#if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
+#endif
virtual void attach();
virtual void detach();
virtual void parseMappedAttribute(MappedAttribute* attr);
virtual bool isVideo() const { return true; }
+ virtual bool hasVideo() const { return player() && player()->hasVideo(); }
virtual bool isURLAttribute(Attribute*) const;
virtual const QualifiedName& imageSourceAttributeName() const;
diff --git a/WebCore/html/HTMLViewSourceDocument.cpp b/WebCore/html/HTMLViewSourceDocument.cpp
index 163ee72..596f16e 100644
--- a/WebCore/html/HTMLViewSourceDocument.cpp
+++ b/WebCore/html/HTMLViewSourceDocument.cpp
@@ -73,7 +73,7 @@ void HTMLViewSourceDocument::createContainingTable()
// document.
RefPtr<Element> div = new HTMLDivElement(divTag, this);
RefPtr<NamedMappedAttrMap> attrs = NamedMappedAttrMap::create();
- attrs->insertAttribute(MappedAttribute::create(classAttr, "webkit-line-gutter-backdrop"), true);
+ attrs->addAttribute(MappedAttribute::create(classAttr, "webkit-line-gutter-backdrop"));
div->setAttributeMap(attrs.release());
body->addChild(div);
div->attach();
@@ -195,7 +195,7 @@ Element* HTMLViewSourceDocument::addSpanWithClassName(const String& className)
Element* span = new HTMLElement(spanTag, this);
RefPtr<NamedMappedAttrMap> attrs = NamedMappedAttrMap::create();
- attrs->insertAttribute(MappedAttribute::create(classAttr, className), true);
+ attrs->addAttribute(MappedAttribute::create(classAttr, className));
span->setAttributeMap(attrs.release());
m_current->addChild(span);
span->attach();
@@ -212,7 +212,7 @@ void HTMLViewSourceDocument::addLine(const String& className)
// Create a cell that will hold the line number (it is generated in the stylesheet using counters).
Element* td = new HTMLTableCellElement(tdTag, this);
RefPtr<NamedMappedAttrMap> attrs = NamedMappedAttrMap::create();
- attrs->insertAttribute(MappedAttribute::create(classAttr, "webkit-line-number"), true);
+ attrs->addAttribute(MappedAttribute::create(classAttr, "webkit-line-number"));
td->setAttributeMap(attrs.release());
trow->addChild(td);
td->attach();
@@ -220,7 +220,7 @@ void HTMLViewSourceDocument::addLine(const String& className)
// Create a second cell for the line contents
td = new HTMLTableCellElement(tdTag, this);
attrs = NamedMappedAttrMap::create();
- attrs->insertAttribute(MappedAttribute::create(classAttr, "webkit-line-content"), true);
+ attrs->addAttribute(MappedAttribute::create(classAttr, "webkit-line-content"));
td->setAttributeMap(attrs.release());
trow->addChild(td);
td->attach();
@@ -283,9 +283,9 @@ Element* HTMLViewSourceDocument::addLink(const String& url, bool isAnchor)
classValue = "webkit-html-attribute-value webkit-html-external-link";
else
classValue = "webkit-html-attribute-value webkit-html-resource-link";
- attrs->insertAttribute(MappedAttribute::create(classAttr, classValue), true);
- attrs->insertAttribute(MappedAttribute::create(targetAttr, "_blank"), true);
- attrs->insertAttribute(MappedAttribute::create(hrefAttr, url), true);
+ attrs->addAttribute(MappedAttribute::create(classAttr, classValue));
+ attrs->addAttribute(MappedAttribute::create(targetAttr, "_blank"));
+ attrs->addAttribute(MappedAttribute::create(hrefAttr, url));
anchor->setAttributeMap(attrs.release());
m_current->addChild(anchor);
anchor->attach();
diff --git a/WebCore/html/MediaError.h b/WebCore/html/MediaError.h
index fbf375f..7dcf72a 100644
--- a/WebCore/html/MediaError.h
+++ b/WebCore/html/MediaError.h
@@ -34,7 +34,7 @@ namespace WebCore {
class MediaError : public RefCounted<MediaError> {
public:
- enum Code { MEDIA_ERR_ABORTED = 1, MEDIA_ERR_NETWORK, MEDIA_ERR_DECODE };
+ enum Code { MEDIA_ERR_ABORTED = 1, MEDIA_ERR_NETWORK, MEDIA_ERR_DECODE, MEDIA_ERR_NONE_SUPPORTED };
static PassRefPtr<MediaError> create(Code code) { return adoptRef(new MediaError(code)); }
diff --git a/WebCore/html/MediaError.idl b/WebCore/html/MediaError.idl
index 5b4f0a2..162170f 100644
--- a/WebCore/html/MediaError.idl
+++ b/WebCore/html/MediaError.idl
@@ -28,6 +28,7 @@ module html {
const unsigned short MEDIA_ERR_ABORTED = 1;
const unsigned short MEDIA_ERR_NETWORK = 2;
const unsigned short MEDIA_ERR_DECODE = 3;
+ const unsigned short MEDIA_ERR_NONE_SUPPORTED = 4;
readonly attribute unsigned short code;
};
}
diff --git a/WebCore/html/PreloadScanner.cpp b/WebCore/html/PreloadScanner.cpp
index 7e95c65..782e9bd 100644
--- a/WebCore/html/PreloadScanner.cpp
+++ b/WebCore/html/PreloadScanner.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -43,7 +44,7 @@
#include <wtf/CurrentTime.h>
#include <wtf/unicode/Unicode.h>
-#ifdef __GNUC__
+#if COMPILER(GCC)
// The main tokenizer includes this too so we are getting two copies of the data. However, this way the code gets inlined.
#include "HTMLEntityNames.c"
#else
@@ -128,9 +129,13 @@ bool PreloadScanner::scanningBody() const
void PreloadScanner::write(const SegmentedString& source)
{
+#if PRELOAD_DEBUG
double startTime = currentTime();
+#endif
tokenize(source);
+#if PRELOAD_DEBUG
m_timeUsed += currentTime() - startTime;
+#endif
}
static inline bool isWhitespace(UChar c)