diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:15 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:15 -0800 |
commit | 1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch) | |
tree | 4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/html | |
parent | 9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff) | |
download | external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2 |
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'WebCore/html')
161 files changed, 4995 insertions, 4391 deletions
diff --git a/WebCore/html/CanvasGradient.cpp b/WebCore/html/CanvasGradient.cpp index e3e3726..693d8f7 100644 --- a/WebCore/html/CanvasGradient.cpp +++ b/WebCore/html/CanvasGradient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2007 Alp Toker <alp@atoker.com> * * Redistribution and use in source and binary forms, with or without @@ -28,269 +28,34 @@ #include "CanvasGradient.h" #include "CSSParser.h" - -#if PLATFORM(CG) -#include <ApplicationServices/ApplicationServices.h> -#elif PLATFORM(QT) -#include <QGradient> -#elif PLATFORM(CAIRO) -#include <cairo.h> -#endif - -#ifdef ANDROID_CANVAS_IMPL -#include "GraphicsContext.h" -#include "SkColorShader.h" -#endif +#include "ExceptionCode.h" namespace WebCore { CanvasGradient::CanvasGradient(const FloatPoint& p0, const FloatPoint& p1) - : m_radial(false), m_p0(p0), m_p1(p1), m_stopsSorted(false), m_lastStop(0) -#if PLATFORM(CG) - , m_shading(0) -#elif PLATFORM(QT) - , m_shading(0) -#elif PLATFORM(CAIRO) - , m_shading(0) -#endif -#ifdef ANDROID_CANVAS_IMPL - , m_platformGradient(NULL) -#endif + : m_gradient(Gradient::create(p0, p1)) { } CanvasGradient::CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1) - : m_radial(true), m_p0(p0), m_p1(p1), m_r0(r0), m_r1(r1), m_stopsSorted(false), m_lastStop(0) -#if PLATFORM(CG) - , m_shading(0) -#elif PLATFORM(QT) - , m_shading(0) -#elif PLATFORM(CAIRO) - , m_shading(0) -#endif -#ifdef ANDROID_CANVAS_IMPL - , m_platformGradient(NULL) -#endif -{ -} - -CanvasGradient::~CanvasGradient() -{ -#if PLATFORM(CG) - CGShadingRelease(m_shading); -#elif PLATFORM(QT) - delete m_shading; -#elif PLATFORM(CAIRO) - cairo_pattern_destroy(m_shading); -#endif -#ifdef ANDROID_CANVAS_IMPL - if (m_platformGradient) - GraphicsContext::freePlatformGradient(m_platformGradient); -#endif -} - -void CanvasGradient::addColorStop(float value, const String& color) + : m_gradient(Gradient::create(p0, r0, p1, r1)) { - RGBA32 rgba = 0; // default is transparant black - CSSParser::parseColor(rgba, color); - m_stops.append(ColorStop(value, - ((rgba >> 16) & 0xFF) / 255.0f, - ((rgba >> 8) & 0xFF) / 255.0f, - (rgba & 0xFF) / 255.0f, - ((rgba >> 24) & 0xFF) / 255.0f)); - - m_stopsSorted = false; - -#if PLATFORM(CG) - CGShadingRelease(m_shading); - m_shading = 0; -#elif PLATFORM(QT) - delete m_shading; - m_shading = 0; -#elif PLATFORM(CAIRO) - cairo_pattern_destroy(m_shading); - m_shading = 0; -#endif -} - -#if PLATFORM(CG) - -static void gradientCallback(void* info, const CGFloat* in, CGFloat* out) -{ - float r, g, b, a; - static_cast<CanvasGradient*>(info)->getColor(*in, &r, &g, &b, &a); - out[0] = r; - out[1] = g; - out[2] = b; - out[3] = a; } -CGShadingRef CanvasGradient::platformShading() -{ - if (m_shading) - return m_shading; - - const CGFloat intervalRanges[2] = { 0, 1 }; - const CGFloat colorComponentRanges[4 * 2] = { 0, 1, 0, 1, 0, 1, 0, 1 }; - const CGFunctionCallbacks gradientCallbacks = { 0, gradientCallback, 0 }; - CGFunctionRef colorFunction = CGFunctionCreate(this, 1, intervalRanges, 4, colorComponentRanges, &gradientCallbacks); - - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - - if (m_radial) - m_shading = CGShadingCreateRadial(colorSpace, m_p0, m_r0, m_p1, m_r1, colorFunction, true, true); - else - m_shading = CGShadingCreateAxial(colorSpace, m_p0, m_p1, colorFunction, true, true); - - CGColorSpaceRelease(colorSpace); - CGFunctionRelease(colorFunction); - - return m_shading; -} - -#elif PLATFORM(QT) - -QGradient* CanvasGradient::platformShading() -{ - if (m_shading) - return m_shading; - - if (m_radial) - m_shading = new QRadialGradient(m_p0.x(), m_p0.y(), m_r0, m_p1.x(), m_p1.y()); - else m_shading = new QLinearGradient(m_p0.x(), m_p0.y(), m_p1.x(), m_p1.y()); - - QColor stopColor; - Vector<ColorStop>::iterator stopIterator = m_stops.begin();; - while (stopIterator != m_stops.end()) { - stopColor.setRgbF(stopIterator->red, stopIterator->green, stopIterator->blue, stopIterator->alpha); - m_shading->setColorAt(stopIterator->stop, stopColor); - ++stopIterator; - } - - return m_shading; -} - -#elif PLATFORM(CAIRO) - -cairo_pattern_t* CanvasGradient::platformShading() +void CanvasGradient::addColorStop(float value, const String& color, ExceptionCode& ec) { - if (m_shading) - return m_shading; - - if (m_radial) - m_shading = cairo_pattern_create_radial(m_p0.x(), m_p0.y(), m_r0, m_p1.x(), m_p1.y(), m_r1); - else - m_shading = cairo_pattern_create_linear(m_p0.x(), m_p0.y(), m_p1.x(), m_p1.y()); - - Vector<ColorStop>::iterator stopIterator = m_stops.begin(); - while (stopIterator != m_stops.end()) { - cairo_pattern_add_color_stop_rgba(m_shading, stopIterator->stop, stopIterator->red, stopIterator->green, stopIterator->blue, stopIterator->alpha); - ++stopIterator; - } - - return m_shading; -} - -#endif - -static inline bool compareStops(const CanvasGradient::ColorStop &a, const CanvasGradient::ColorStop &b) -{ - return a.stop < b.stop; -} - -void CanvasGradient::getColor(float value, float* r, float* g, float* b, float* a) -{ - ASSERT(value >= 0); - ASSERT(value <= 1); - - if (m_stops.isEmpty()) { - *r = 0; - *g = 0; - *b = 0; - *a = 0; - return; - } - if (!m_stopsSorted) { - if (m_stops.size()) - std::stable_sort(m_stops.begin(), m_stops.end(), compareStops); - m_stopsSorted = true; - } - if (value <= 0 || value <= m_stops.first().stop) { - *r = m_stops.first().red; - *g = m_stops.first().green; - *b = m_stops.first().blue; - *a = m_stops.first().alpha; + if (!(value >= 0 && value <= 1.0f)) { + ec = INDEX_SIZE_ERR; return; } - if (value >= 1 || value >= m_stops.last().stop) { - *r = m_stops.last().red; - *g = m_stops.last().green; - *b = m_stops.last().blue; - *a = m_stops.last().alpha; + + RGBA32 rgba = 0; + if (!CSSParser::parseColor(rgba, color)) { + ec = SYNTAX_ERR; return; } - // Find stop before and stop after and interpolate. - int stop = findStop(value); - const ColorStop& lastStop = m_stops[stop]; - const ColorStop& nextStop = m_stops[stop + 1]; - float stopFraction = (value - lastStop.stop) / (nextStop.stop - lastStop.stop); - *r = lastStop.red + (nextStop.red - lastStop.red) * stopFraction; - *g = lastStop.green + (nextStop.green - lastStop.green) * stopFraction; - *b = lastStop.blue + (nextStop.blue - lastStop.blue) * stopFraction; - *a = lastStop.alpha + (nextStop.alpha - lastStop.alpha) * stopFraction; -} - -int CanvasGradient::findStop(float value) const -{ - ASSERT(value >= 0); - ASSERT(value <= 1); - ASSERT(m_stopsSorted); - - int numStops = m_stops.size(); - ASSERT(numStops >= 2); - ASSERT(m_lastStop < numStops - 1); - - int i = m_lastStop; - if (value < m_stops[i].stop) - i = 1; - else - i = m_lastStop + 1; - - for (; i < numStops - 1; ++i) - if (value < m_stops[i].stop) - break; - - m_lastStop = i - 1; - return m_lastStop; -} - -#ifdef ANDROID_CANVAS_IMPL -PlatformGradient* CanvasGradient::platformGradient() -{ - PlatformGradient* pg = m_platformGradient; - int count = m_stops.size(); - - if (NULL == pg) { - // it seems the spec says a zero-size gradient draws transparent - if (0 == count) { - pg = new SkColorShader(0); - } else { - // call this to ensure that data[] is sorted - float r, g, b, a; - (void)getColor(0, &r, &g, &b, &a); - - const float* data = (const float*)m_stops.data(); - - if (m_radial) - pg = GraphicsContext::newPlatformRadialGradient(m_p0, m_r0, m_p1, m_r1, data, count); - else - pg = GraphicsContext::newPlatformLinearGradient(m_p0, m_p1, data, count); - } - m_platformGradient = pg; - } - return pg; + m_gradient->addColorStop(value, Color(rgba)); } -#endif -} //namespace +} // namespace diff --git a/WebCore/html/CanvasGradient.h b/WebCore/html/CanvasGradient.h index 2648599..3b81dbd 100644 --- a/WebCore/html/CanvasGradient.h +++ b/WebCore/html/CanvasGradient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved. * Copyright (C) 2007 Alp Toker <alp@atoker.com> * * Redistribution and use in source and binary forms, with or without @@ -27,80 +27,38 @@ #ifndef CanvasGradient_h #define CanvasGradient_h -#include "FloatPoint.h" +#include "Gradient.h" +#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#include <wtf/Vector.h> - -#ifdef ANDROID_CANVAS_IMPL - #include "PlatformGraphics.h" -#endif - -#if PLATFORM(CG) -typedef struct CGShading* CGShadingRef; -#elif PLATFORM(QT) -class QGradient; -#elif PLATFORM(CAIRO) -typedef struct _cairo_pattern cairo_pattern_t; -#endif namespace WebCore { class String; + typedef int ExceptionCode; + class CanvasGradient : public RefCounted<CanvasGradient> { public: - CanvasGradient(const FloatPoint& p0, const FloatPoint& p1); - CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1); - ~CanvasGradient(); + static PassRefPtr<CanvasGradient> create(const FloatPoint& p0, const FloatPoint& p1) + { + return adoptRef(new CanvasGradient(p0, p1)); + } + static PassRefPtr<CanvasGradient> create(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1) + { + return adoptRef(new CanvasGradient(p0, r0, p1, r1)); + } + + Gradient* gradient() const { return m_gradient.get(); } - void addColorStop(float, const String& color); + void addColorStop(float value, const String& color, ExceptionCode&); - void getColor(float value, float* r, float* g, float* b, float* a); - -#ifdef ANDROID_CANVAS_IMPL - PlatformGradient* platformGradient(); -#endif - -#if PLATFORM(CG) - CGShadingRef platformShading(); -#elif PLATFORM(QT) - QGradient *platformShading(); -#elif PLATFORM(CAIRO) - cairo_pattern_t* platformShading(); -#endif - - struct ColorStop { - float stop; - float red; - float green; - float blue; - float alpha; - - ColorStop() : stop(0), red(0), green(0), blue(0), alpha(0) { } - ColorStop(float s, float r, float g, float b, float a) : stop(s), red(r), green(g), blue(b), alpha(a) { } - }; + void getColor(float value, float* r, float* g, float* b, float* a) const { m_gradient->getColor(value, r, g, b, a); } private: - int findStop(float value) const; - - bool m_radial; - FloatPoint m_p0, m_p1; - float m_r0, m_r1; - mutable Vector<ColorStop> m_stops; - mutable bool m_stopsSorted; - mutable int m_lastStop; - -#if PLATFORM(CG) - CGShadingRef m_shading; -#elif PLATFORM(QT) - QGradient *m_shading; -#elif PLATFORM(CAIRO) - cairo_pattern_t* m_shading; -#endif - -#ifdef ANDROID_CANVAS_IMPL - PlatformGradient* m_platformGradient; -#endif + CanvasGradient(const FloatPoint& p0, const FloatPoint& p1); + CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1); + + RefPtr<Gradient> m_gradient; }; } //namespace diff --git a/WebCore/html/CanvasGradient.idl b/WebCore/html/CanvasGradient.idl index 578be2b..a925a26 100644 --- a/WebCore/html/CanvasGradient.idl +++ b/WebCore/html/CanvasGradient.idl @@ -30,7 +30,8 @@ module html { ImplementationUUID=a2942ae6-2731-4286-98cc-9d5e79e20de1 ] CanvasGradient { - void addColorStop(in float offset, in DOMString color); + void addColorStop(in float offset, in DOMString color) + raises (DOMException); }; diff --git a/WebCore/html/CanvasPattern.cpp b/WebCore/html/CanvasPattern.cpp index 585fc62..62a4620 100644 --- a/WebCore/html/CanvasPattern.cpp +++ b/WebCore/html/CanvasPattern.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,216 +26,41 @@ #include "config.h" #include "CanvasPattern.h" -#include "CachedImage.h" #include "ExceptionCode.h" -#include "FloatRect.h" -#include "GraphicsContext.h" -#include "Image.h" +#include "PlatformString.h" namespace WebCore { void CanvasPattern::parseRepetitionType(const String& type, bool& repeatX, bool& repeatY, ExceptionCode& ec) { + ec = 0; if (type.isEmpty() || type == "repeat") { repeatX = true; repeatY = true; - ec = 0; return; } if (type == "no-repeat") { repeatX = false; repeatY = false; - ec = 0; return; } if (type == "repeat-x") { repeatX = true; repeatY = false; - ec = 0; return; } if (type == "repeat-y") { repeatX = false; repeatY = true; - ec = 0; return; } ec = SYNTAX_ERR; } -#if PLATFORM(CG) - -CanvasPattern::CanvasPattern(CGImageRef image, bool repeatX, bool repeatY) - : m_platformImage(image) - , m_cachedImage(0) - , m_repeatX(repeatX) - , m_repeatY(repeatY) -{ -} - -#elif PLATFORM(CAIRO) - -CanvasPattern::CanvasPattern(cairo_surface_t* surface, bool repeatX, bool repeatY) - : m_platformImage(cairo_surface_reference(surface)) - , m_cachedImage(0) - , m_repeatX(repeatX) - , m_repeatY(repeatY) -{ -} - -#endif - -CanvasPattern::CanvasPattern(CachedImage* cachedImage, bool repeatX, bool repeatY) - : -#if PLATFORM(CG) || PLATFORM(CAIRO) - m_platformImage(0) - , -#endif - m_cachedImage(cachedImage) - , m_repeatX(repeatX) - , m_repeatY(repeatY) -#ifdef ANDROID_CANVAS_IMPL - , m_platformPattern(NULL) -#endif -{ - if (cachedImage) - cachedImage->ref(this); -} - -CanvasPattern::~CanvasPattern() -{ -#ifdef ANDROID_CANVAS_IMPL - if (m_platformPattern) - GraphicsContext::freePlatformPattern(m_platformPattern); -#endif -#if PLATFORM(CAIRO) - if (m_platformImage) - cairo_surface_destroy(m_platformImage); -#endif - if (m_cachedImage) - m_cachedImage->deref(this); -} - -#if PLATFORM(CG) - -static void patternCallback(void* info, CGContextRef context) -{ - CGImageRef platformImage = static_cast<CanvasPattern*>(info)->platformImage(); - if (platformImage) { - CGRect rect = GraphicsContext(context).roundToDevicePixels( - FloatRect(0, 0, CGImageGetWidth(platformImage), CGImageGetHeight(platformImage))); - CGContextDrawImage(context, rect, platformImage); - return; - } - - CachedImage* cachedImage = static_cast<CanvasPattern*>(info)->cachedImage(); - if (!cachedImage) - return; - Image* image = cachedImage->image(); - if (!image) - return; - - FloatRect rect = GraphicsContext(context).roundToDevicePixels(image->rect()); - - if (image->getCGImageRef()) { - CGContextDrawImage(context, rect, image->getCGImageRef()); - // FIXME: We should refactor this code to use the platform-independent - // drawing API in all cases. Then, this didDraw call will happen - // automatically, and we can remove it. - cachedImage->didDraw(image); - return; - } - - GraphicsContext(context).drawImage(image, rect); -} - -static void patternReleaseCallback(void* info) -{ - static_cast<CanvasPattern*>(info)->deref(); -} - -CGPatternRef CanvasPattern::createPattern(const CGAffineTransform& transform) -{ - CGRect rect; - rect.origin.x = 0; - rect.origin.y = 0; - if (m_platformImage) { - rect.size.width = CGImageGetWidth(m_platformImage.get()); - rect.size.height = CGImageGetHeight(m_platformImage.get()); - } else { - if (!m_cachedImage) - return 0; - Image* image = m_cachedImage->image(); - if (!image) - return 0; - rect.size.width = image->width(); - rect.size.height = image->height(); - } - - CGAffineTransform patternTransform = - CGAffineTransformTranslate(CGAffineTransformScale(transform, 1, -1), 0, -rect.size.height); - - float xStep = m_repeatX ? rect.size.width : FLT_MAX; - // If FLT_MAX should also be used for yStep, nothing is rendered. Using fractions of FLT_MAX also - // result in nothing being rendered. This is not a problem with xStep. - // INT_MAX is almost correct, but there seems to be some number wrapping occuring making the fill - // pattern is not filled correctly. - // So, just pick a really large number that works. - float yStep = m_repeatY ? rect.size.height : (100000000.0f); - - const CGPatternCallbacks patternCallbacks = { 0, patternCallback, patternReleaseCallback }; - ref(); - return CGPatternCreate(this, rect, patternTransform, xStep, yStep, - kCGPatternTilingConstantSpacing, TRUE, &patternCallbacks); -} - -#elif PLATFORM(CAIRO) - -cairo_pattern_t* CanvasPattern::createPattern(const cairo_matrix_t& m) -{ - cairo_surface_t* surface = 0; - if (m_platformImage) { - surface = m_platformImage; - } else { - if (!m_cachedImage) - return 0; - Image* image = m_cachedImage->image(); - if (!image) - return 0; - surface = image->nativeImageForCurrentFrame(); - } - - if (!surface) - return 0; - - cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface); - cairo_pattern_set_matrix(pattern, &m); - if (m_repeatX || m_repeatY) - cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); - return pattern; -} - -#endif - -#ifdef ANDROID_CANVAS_IMPL -/* TODO - 1) pass in graphics context or something in case Apple needs to see the current matrix. If so, - we may need to pass the current (if any) platformPatter to it, so it can free it in and build - a new one, if that is required (not needed by our platform). - 2) Need a RepeatTile mode for Decal, so we can represent <canvas> notion of "no-repeat" -*/ -PlatformPattern* CanvasPattern::platformPattern() +CanvasPattern::CanvasPattern(Image* image, bool repeatX, bool repeatY, bool originClean) + : m_pattern(Pattern::create(image, repeatX, repeatY)) + , m_originClean(originClean) { - if (NULL == m_platformPattern && m_cachedImage) - { - Image* image = m_cachedImage->image(); - if (image) - m_platformPattern = GraphicsContext::newPlatformPattern(image, - m_repeatX ? Image::RepeatTile : Image::StretchTile, - m_repeatY ? Image::RepeatTile : Image::StretchTile); - } - return m_platformPattern; } -#endif } diff --git a/WebCore/html/CanvasPattern.h b/WebCore/html/CanvasPattern.h index d74dc8a..6c012d1 100644 --- a/WebCore/html/CanvasPattern.h +++ b/WebCore/html/CanvasPattern.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,69 +26,37 @@ #ifndef CanvasPattern_h #define CanvasPattern_h -#include "CachedResourceClient.h" +#include "Pattern.h" +#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#ifdef ANDROID_CANVAS_IMPL - #include "PlatformGraphics.h" -#endif -#if PLATFORM(CG) -#include <wtf/RetainPtr.h> -#include <ApplicationServices/ApplicationServices.h> -#elif PLATFORM(CAIRO) -#include <cairo.h> -#endif - namespace WebCore { - class CachedImage; + class Image; class String; typedef int ExceptionCode; - class CanvasPattern : public RefCounted<CanvasPattern>, CachedResourceClient { + class CanvasPattern : public RefCounted<CanvasPattern> { public: static void parseRepetitionType(const String&, bool& repeatX, bool& repeatY, ExceptionCode&); -#if PLATFORM(CG) - CanvasPattern(CGImageRef, bool repeatX, bool repeatY); -#elif PLATFORM(CAIRO) - CanvasPattern(cairo_surface_t*, bool repeatX, bool repeatY); -#endif - CanvasPattern(CachedImage*, bool repeatX, bool repeatY); - ~CanvasPattern(); + static PassRefPtr<CanvasPattern> create(Image* image, bool repeatX, bool repeatY, bool originClean) + { + return adoptRef(new CanvasPattern(image, repeatX, repeatY, originClean)); + } -#if PLATFORM(CG) - CGImageRef platformImage() const { return m_platformImage.get(); } -#elif PLATFORM(CAIRO) - cairo_surface_t* platformImage() const { return m_platformImage; } -#endif - CachedImage* cachedImage() const { return m_cachedImage; } + Pattern* pattern() const { return m_pattern.get(); } -#if PLATFORM(CG) - CGPatternRef createPattern(const CGAffineTransform&); -#elif PLATFORM(CAIRO) - cairo_pattern_t* createPattern(const cairo_matrix_t&); -#endif - -#ifdef ANDROID_CANVAS_IMPL - PlatformPattern* platformPattern(); -#endif + bool originClean() const { return m_originClean; } private: -#if PLATFORM(CG) - const RetainPtr<CGImageRef> m_platformImage; -#elif PLATFORM(CAIRO) - cairo_surface_t* const m_platformImage; -#endif - CachedImage* const m_cachedImage; - const bool m_repeatX; - const bool m_repeatY; + CanvasPattern(Image*, bool repeatX, bool repeatY, bool originClean); -#ifdef ANDROID_CANVAS_IMPL - PlatformPattern* m_platformPattern; -#endif + RefPtr<Pattern> m_pattern; + bool m_originClean; }; + } // namespace WebCore #endif diff --git a/WebCore/html/CanvasPixelArray.cpp b/WebCore/html/CanvasPixelArray.cpp new file mode 100644 index 0000000..82bc27b --- /dev/null +++ b/WebCore/html/CanvasPixelArray.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CanvasPixelArray.h" + +namespace WebCore { + +PassRefPtr<CanvasPixelArray> CanvasPixelArray::create(unsigned size) +{ + return adoptRef(new CanvasPixelArray(size)); +} + +CanvasPixelArray::CanvasPixelArray(unsigned size) + : m_data(size) +{ + ASSERT((reinterpret_cast<size_t>(m_data.data()) & 3) == 0); +} + +} diff --git a/WebCore/html/CanvasPixelArray.h b/WebCore/html/CanvasPixelArray.h new file mode 100644 index 0000000..5560538 --- /dev/null +++ b/WebCore/html/CanvasPixelArray.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CanvasPixelArray_h +#define CanvasPixelArray_h + +#include <wtf/MathExtras.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> + +namespace WebCore { + + class CanvasPixelArray : public RefCounted<CanvasPixelArray> { + public: + static PassRefPtr<CanvasPixelArray> create(unsigned size); + + Vector<unsigned char>& data() { return m_data; } + unsigned length() const { return m_data.size(); } + + void set(unsigned index, double value) + { + if (index >= m_data.size()) + return; + if (!(value > 0)) // Clamp NaN to 0 + value = 0; + else if (value > 255) + value = 255; + m_data[index] = static_cast<unsigned char>(value + 0.5); + } + + bool get(unsigned index, unsigned char& result) const + { + if (index >= m_data.size()) + return false; + result = m_data[index]; + return true; + } + + private: + CanvasPixelArray(unsigned size); + Vector<unsigned char> m_data; + }; + +} // namespace WebCore + +#endif // CanvasPixelArray_h diff --git a/WebCore/html/CanvasPixelArray.idl b/WebCore/html/CanvasPixelArray.idl new file mode 100644 index 0000000..d4dcecb --- /dev/null +++ b/WebCore/html/CanvasPixelArray.idl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module html { + + interface [ + CustomHeader, + HasCustomIndexGetter, + HasCustomIndexSetter + ] CanvasPixelArray { + readonly attribute long length; + }; + +} diff --git a/WebCore/html/CanvasRenderingContext2D.cpp b/WebCore/html/CanvasRenderingContext2D.cpp index 04cd1b5..5e3f36c 100644 --- a/WebCore/html/CanvasRenderingContext2D.cpp +++ b/WebCore/html/CanvasRenderingContext2D.cpp @@ -1,7 +1,8 @@ /* * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2007 Trolltech ASA + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,49 +34,53 @@ #include "CachedImage.h" #include "CanvasGradient.h" #include "CanvasPattern.h" +#include "CanvasPixelArray.h" #include "CanvasStyle.h" +#include "CSSPropertyNames.h" +#include "CSSStyleSelector.h" #include "Document.h" #include "ExceptionCode.h" +#include "FloatConversion.h" #include "Frame.h" #include "GraphicsContext.h" #include "HTMLCanvasElement.h" #include "HTMLImageElement.h" #include "HTMLNames.h" +#include "ImageBuffer.h" +#include "ImageData.h" +#include "KURL.h" #include "NotImplemented.h" +#include "Page.h" #include "RenderHTMLCanvas.h" +#include "SecurityOrigin.h" #include "Settings.h" +#include "TextMetrics.h" +#include <kjs/interpreter.h> +#include <stdio.h> #include <wtf/MathExtras.h> -#if PLATFORM(QT) -#include <QPainter> -#include <QPixmap> -#include <QPainterPath> -#elif PLATFORM(CAIRO) -#include "CairoPath.h" -#include <cairo.h> -#endif +using namespace std; namespace WebCore { using namespace HTMLNames; -#ifdef ANDROID_CANVAS_IMPL -static PlatformGradient* extractGradient(CanvasStyle* style) +const char* defaultFont = "10px sans-serif"; + +CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas) + : m_canvas(canvas) + , m_stateStack(1) { - CanvasGradient* grad = style->gradient(); - return grad ? grad->platformGradient() : NULL; } -static PlatformPattern* extractPattern(CanvasStyle* style) + +void CanvasRenderingContext2D::ref() { - CanvasPattern* pat = style->pattern(); - return pat ? pat->platformPattern() : NULL; + m_canvas->ref(); } -#endif -CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas) - : m_canvas(canvas) - , m_stateStack(1) +void CanvasRenderingContext2D::deref() { + m_canvas->deref(); } void CanvasRenderingContext2D::reset() @@ -85,8 +90,8 @@ void CanvasRenderingContext2D::reset() } CanvasRenderingContext2D::State::State() - : m_strokeStyle(new CanvasStyle("black")) - , m_fillStyle(new CanvasStyle("black")) + : m_strokeStyle(CanvasStyle::create("black")) + , m_fillStyle(CanvasStyle::create("black")) , m_lineWidth(1) , m_lineCap(ButtCap) , m_lineJoin(MiterJoin) @@ -95,8 +100,10 @@ CanvasRenderingContext2D::State::State() , m_shadowColor("black") , m_globalAlpha(1) , m_globalComposite(CompositeSourceOver) - , m_appliedStrokePattern(false) - , m_appliedFillPattern(false) + , m_textAlign(StartTextAlign) + , m_textBaseline(AlphabeticTextBaseline) + , m_unparsedFont(defaultFont) + , m_realizedFont(false) { } @@ -115,7 +122,9 @@ void CanvasRenderingContext2D::restore() ASSERT(m_stateStack.size() >= 1); if (m_stateStack.size() <= 1) return; + m_path.transform(state().m_transform); m_stateStack.removeLast(); + m_path.transform(state().m_transform.inverse()); GraphicsContext* c = drawingContext(); if (!c) return; @@ -131,12 +140,19 @@ void CanvasRenderingContext2D::setStrokeStyle(PassRefPtr<CanvasStyle> style) { if (!style) return; + + if (m_canvas->originClean()) { + if (CanvasPattern* pattern = style->canvasPattern()) { + if (!pattern->originClean()) + m_canvas->setOriginTainted(); + } + } + state().m_strokeStyle = style; GraphicsContext* c = drawingContext(); if (!c) return; state().m_strokeStyle->applyStrokeColor(c); - state().m_appliedStrokePattern = false; } CanvasStyle* CanvasRenderingContext2D::fillStyle() const @@ -148,17 +164,19 @@ void CanvasRenderingContext2D::setFillStyle(PassRefPtr<CanvasStyle> style) { if (!style) return; + + if (m_canvas->originClean()) { + if (CanvasPattern* pattern = style->canvasPattern()) { + if (!pattern->originClean()) + m_canvas->setOriginTainted(); + } + } + state().m_fillStyle = style; GraphicsContext* c = drawingContext(); if (!c) return; -#if PLATFORM(CAIRO) - // FIXME: hack to reduce code duplication in CanvasStyle.cpp - state().m_fillStyle->applyStrokeColor(c); -#else state().m_fillStyle->applyFillColor(c); -#endif - state().m_appliedFillPattern = false; } float CanvasRenderingContext2D::lineWidth() const @@ -311,7 +329,8 @@ void CanvasRenderingContext2D::scale(float sx, float sy) if (!c) return; c->scale(FloatSize(sx, sy)); - state().m_path.transform(AffineTransform().scale(1.0/sx, 1.0/sy)); + state().m_transform.scale(sx, sy); + m_path.transform(AffineTransform().scale(1.0/sx, 1.0/sy)); } void CanvasRenderingContext2D::rotate(float angleInRadians) @@ -320,7 +339,8 @@ void CanvasRenderingContext2D::rotate(float angleInRadians) if (!c) return; c->rotate(angleInRadians); - state().m_path.transform(AffineTransform().rotate(-angleInRadians / piDouble * 180.0)); + state().m_transform.rotate(angleInRadians / piDouble * 180.0); + m_path.transform(AffineTransform().rotate(-angleInRadians / piDouble * 180.0)); } void CanvasRenderingContext2D::translate(float tx, float ty) @@ -329,7 +349,8 @@ void CanvasRenderingContext2D::translate(float tx, float ty) if (!c) return; c->translate(tx, ty); - state().m_path.transform(AffineTransform().translate(-tx, -ty)); + state().m_transform.translate(tx, ty); + m_path.transform(AffineTransform().translate(-tx, -ty)); } void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float m22, float dx, float dy) @@ -339,208 +360,192 @@ void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float return; // HTML5 3.14.11.1 -- ignore any calls that pass non-finite numbers - if (!isfinite(m11) || !isfinite(m21) || !isfinite(dx) || - !isfinite(m12) || !isfinite(m22) || !isfinite(dy)) + if (!isfinite(m11) | !isfinite(m21) | !isfinite(dx) | + !isfinite(m12) | !isfinite(m22) | !isfinite(dy)) return; AffineTransform transform(m11, m12, m21, m22, dx, dy); c->concatCTM(transform); - state().m_path.transform(transform.inverse()); + state().m_transform.multiply(transform); + m_path.transform(transform.inverse()); } void CanvasRenderingContext2D::setStrokeColor(const String& color) { - setStrokeStyle(new CanvasStyle(color)); + setStrokeStyle(CanvasStyle::create(color)); } void CanvasRenderingContext2D::setStrokeColor(float grayLevel) { - setStrokeStyle(new CanvasStyle(grayLevel, 1)); + setStrokeStyle(CanvasStyle::create(grayLevel, 1)); } void CanvasRenderingContext2D::setStrokeColor(const String& color, float alpha) { - setStrokeStyle(new CanvasStyle(color, alpha)); + setStrokeStyle(CanvasStyle::create(color, alpha)); } void CanvasRenderingContext2D::setStrokeColor(float grayLevel, float alpha) { - setStrokeStyle(new CanvasStyle(grayLevel, alpha)); + setStrokeStyle(CanvasStyle::create(grayLevel, alpha)); } void CanvasRenderingContext2D::setStrokeColor(float r, float g, float b, float a) { - setStrokeStyle(new CanvasStyle(r, g, b, a)); + setStrokeStyle(CanvasStyle::create(r, g, b, a)); } void CanvasRenderingContext2D::setStrokeColor(float c, float m, float y, float k, float a) { - setStrokeStyle(new CanvasStyle(c, m, y, k, a)); + setStrokeStyle(CanvasStyle::create(c, m, y, k, a)); } void CanvasRenderingContext2D::setFillColor(const String& color) { - setFillStyle(new CanvasStyle(color)); + setFillStyle(CanvasStyle::create(color)); } void CanvasRenderingContext2D::setFillColor(float grayLevel) { - setFillStyle(new CanvasStyle(grayLevel, 1)); + setFillStyle(CanvasStyle::create(grayLevel, 1)); } void CanvasRenderingContext2D::setFillColor(const String& color, float alpha) { - setFillStyle(new CanvasStyle(color, 1)); + setFillStyle(CanvasStyle::create(color, 1)); } void CanvasRenderingContext2D::setFillColor(float grayLevel, float alpha) { - setFillStyle(new CanvasStyle(grayLevel, alpha)); + setFillStyle(CanvasStyle::create(grayLevel, alpha)); } void CanvasRenderingContext2D::setFillColor(float r, float g, float b, float a) { - setFillStyle(new CanvasStyle(r, g, b, a)); + setFillStyle(CanvasStyle::create(r, g, b, a)); } void CanvasRenderingContext2D::setFillColor(float c, float m, float y, float k, float a) { - setFillStyle(new CanvasStyle(c, m, y, k, a)); + setFillStyle(CanvasStyle::create(c, m, y, k, a)); } void CanvasRenderingContext2D::beginPath() { - state().m_path.clear(); + m_path.clear(); } void CanvasRenderingContext2D::closePath() { - state().m_path.closeSubpath(); + m_path.closeSubpath(); } void CanvasRenderingContext2D::moveTo(float x, float y) { - state().m_path.moveTo(FloatPoint(x, y)); + if (!isfinite(x) | !isfinite(y)) + return; + m_path.moveTo(FloatPoint(x, y)); } void CanvasRenderingContext2D::lineTo(float x, float y) { - state().m_path.addLineTo(FloatPoint(x, y)); + if (!isfinite(x) | !isfinite(y)) + return; + m_path.addLineTo(FloatPoint(x, y)); } void CanvasRenderingContext2D::quadraticCurveTo(float cpx, float cpy, float x, float y) { - state().m_path.addQuadCurveTo(FloatPoint(cpx, cpy), FloatPoint(x, y)); + if (!isfinite(cpx) | !isfinite(cpy) | !isfinite(x) | !isfinite(y)) + return; + m_path.addQuadCurveTo(FloatPoint(cpx, cpy), FloatPoint(x, y)); } void CanvasRenderingContext2D::bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y) { - state().m_path.addBezierCurveTo(FloatPoint(cp1x, cp1y), FloatPoint(cp2x, cp2y), FloatPoint(x, y)); + if (!isfinite(cp1x) | !isfinite(cp1y) | !isfinite(cp2x) | !isfinite(cp2y) | !isfinite(x) | !isfinite(y)) + return; + m_path.addBezierCurveTo(FloatPoint(cp1x, cp1y), FloatPoint(cp2x, cp2y), FloatPoint(x, y)); } void CanvasRenderingContext2D::arcTo(float x0, float y0, float x1, float y1, float r, ExceptionCode& ec) { ec = 0; - if (!(r > 0)) { + if (!isfinite(x0) | !isfinite(y0) | !isfinite(x1) | !isfinite(y1) | !isfinite(r)) + return; + + if (r < 0) { ec = INDEX_SIZE_ERR; return; } -// SkDebugf("------ arcTo %g %g %g %g %g\n", x0, y0, x1, y1, r); - state().m_path.addArcTo(FloatPoint(x0, y0), FloatPoint(x1, y1), r); + + m_path.addArcTo(FloatPoint(x0, y0), FloatPoint(x1, y1), r); } void CanvasRenderingContext2D::arc(float x, float y, float r, float sa, float ea, bool anticlockwise, ExceptionCode& ec) { ec = 0; - if (!(r > 0)) { + if (!isfinite(x) | !isfinite(y) | !isfinite(r) | !isfinite(sa) | !isfinite(ea)) + return; + + if (r < 0) { ec = INDEX_SIZE_ERR; return; } - state().m_path.addArc(FloatPoint(x, y), r, sa, ea, anticlockwise); + + m_path.addArc(FloatPoint(x, y), r, sa, ea, anticlockwise); +} + +static bool validateRectForCanvas(float& x, float& y, float& width, float& height) +{ + if (!isfinite(x) | !isfinite(y) | !isfinite(width) | !isfinite(height)) + return false; + + if (width < 0) { + width = -width; + x -= width; + } + + if (height < 0) { + height = -height; + y -= height; + } + + return true; } -void CanvasRenderingContext2D::rect(float x, float y, float width, float height, ExceptionCode& ec) +void CanvasRenderingContext2D::rect(float x, float y, float width, float height) { - ec = 0; - if (!(width >= 0 && height >= 0)) { - ec = INDEX_SIZE_ERR; + if (!validateRectForCanvas(x, y, width, height)) return; - } - state().m_path.addRect(FloatRect(x, y, width, height)); + + m_path.addRect(FloatRect(x, y, width, height)); } +#if ENABLE(DASHBOARD_SUPPORT) void CanvasRenderingContext2D::clearPathForDashboardBackwardCompatibilityMode() { - if (m_canvas) - if (Settings* settings = m_canvas->document()->settings()) - if (settings->usesDashboardBackwardCompatibilityMode()) - state().m_path.clear(); + if (Settings* settings = m_canvas->document()->settings()) + if (settings->usesDashboardBackwardCompatibilityMode()) + m_path.clear(); } +#endif void CanvasRenderingContext2D::fill() { GraphicsContext* c = drawingContext(); if (!c) return; - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGContextBeginPath(c->platformContext()); - CGContextAddPath(c->platformContext(), state().m_path.platformPath()); - if (!state().m_path.isEmpty()) - willDraw(CGContextGetPathBoundingBox(c->platformContext())); + c->beginPath(); + c->addPath(m_path); + if (!m_path.isEmpty()) + willDraw(m_path.boundingRect()); - if (state().m_fillStyle->gradient()) { - // Shading works on the entire clip region, so convert the current path to a clip. - c->save(); - CGContextClip(c->platformContext()); - CGContextDrawShading(c->platformContext(), state().m_fillStyle->gradient()->platformShading()); - c->restore(); - } else { - if (state().m_fillStyle->pattern()) - applyFillPattern(); - CGContextFillPath(c->platformContext()); - } -#elif defined(ANDROID_CANVAS_IMPL) - CanvasStyle* s = state().m_fillStyle.get(); - const Path& path = state().m_path; - if (path.isEmpty()) { // <canvas> treats empty path filling as the entire visible area - FloatRect rect = c->getClipLocalBounds(); - willDraw(rect); - c->fillRect(rect, extractGradient(s), extractPattern(s)); - } - else { - willDraw(path.boundingRect()); - c->fillPath(path, extractGradient(s), extractPattern(s)); - } -#elif PLATFORM(QT) - QPainterPath* path = state().m_path.platformPath(); - QPainter* p = static_cast<QPainter*>(c->platformContext()); - willDraw(path->controlPointRect()); - if (state().m_fillStyle->gradient()) { - p->fillPath(*path, QBrush(*(state().m_fillStyle->gradient()->platformShading()))); - } else { - if (state().m_fillStyle->pattern()) - applyFillPattern(); - p->fillPath(*path, p->brush()); - } -#elif PLATFORM(CAIRO) - cairo_t* cr = c->platformContext(); - cairo_save(cr); - willDraw(state().m_path.boundingRect()); - if (state().m_fillStyle->gradient()) { - cairo_set_source(cr, state().m_fillStyle->gradient()->platformShading()); - c->addPath(state().m_path); - cairo_fill(cr); - } else { - if (state().m_fillStyle->pattern()) - applyFillPattern(); - c->addPath(state().m_path); - cairo_fill(cr); - } - cairo_restore(cr); -#endif + c->fillPath(); +#if ENABLE(DASHBOARD_SUPPORT) clearPathForDashboardBackwardCompatibilityMode(); +#endif } void CanvasRenderingContext2D::stroke() @@ -548,70 +553,23 @@ void CanvasRenderingContext2D::stroke() GraphicsContext* c = drawingContext(); if (!c) return; - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGContextBeginPath(c->platformContext()); - CGContextAddPath(c->platformContext(), state().m_path.platformPath()); + c->beginPath(); + c->addPath(m_path); - if (!state().m_path.isEmpty()) { + if (!m_path.isEmpty()) { + // FIXME: This is insufficient, need to use CGContextReplacePathWithStrokedPath to expand to required bounds float lineWidth = state().m_lineWidth; - float inset = -lineWidth / 2; - CGRect boundingRect = CGRectInset(CGContextGetPathBoundingBox(c->platformContext()), inset, inset); + float inset = lineWidth / 2; + FloatRect boundingRect = m_path.boundingRect(); + boundingRect.inflate(inset); willDraw(boundingRect); } - if (state().m_strokeStyle->gradient()) { - // Shading works on the entire clip region, so convert the current path to a clip. - c->save(); - CGContextReplacePathWithStrokedPath(c->platformContext()); - CGContextClip(c->platformContext()); - CGContextDrawShading(c->platformContext(), state().m_strokeStyle->gradient()->platformShading()); - c->restore(); - } else { - if (state().m_strokeStyle->pattern()) - applyStrokePattern(); - CGContextStrokePath(c->platformContext()); - } -#elif defined(ANDROID_CANVAS_IMPL) - CanvasStyle* s = state().m_strokeStyle.get(); - const Path& path = state().m_path; - FloatRect bounds = path.boundingRect(); - bounds.inflate(state().m_lineWidth * 0.5f); - willDraw(bounds); - c->strokePath(path, extractGradient(s), extractPattern(s)); -#elif PLATFORM(QT) - QPainterPath* path = state().m_path.platformPath(); - QPainter* p = static_cast<QPainter*>(c->platformContext()); - willDraw(path->controlPointRect()); - if (state().m_strokeStyle->gradient()) { - p->save(); - p->setBrush(*(state().m_strokeStyle->gradient()->platformShading())); - p->strokePath(*path, p->pen()); - p->restore(); - } else { - if (state().m_strokeStyle->pattern()) - applyStrokePattern(); - p->strokePath(*path, p->pen()); - } -#elif PLATFORM(CAIRO) - cairo_t* cr = c->platformContext(); - cairo_save(cr); - // FIXME: consider inset, as in CG - willDraw(state().m_path.boundingRect()); - if (state().m_strokeStyle->gradient()) { - cairo_set_source(cr, state().m_strokeStyle->gradient()->platformShading()); - c->addPath(state().m_path); - cairo_stroke(cr); - } else { - if (state().m_strokeStyle->pattern()) - applyStrokePattern(); - c->addPath(state().m_path); - cairo_stroke(cr); - } - cairo_restore(cr); -#endif + c->strokePath(); +#if ENABLE(DASHBOARD_SUPPORT) clearPathForDashboardBackwardCompatibilityMode(); +#endif } void CanvasRenderingContext2D::clip() @@ -619,8 +577,10 @@ void CanvasRenderingContext2D::clip() GraphicsContext* c = drawingContext(); if (!c) return; - c->clip(state().m_path); + c->clip(m_path); +#if ENABLE(DASHBOARD_SUPPORT) clearPathForDashboardBackwardCompatibilityMode(); +#endif } bool CanvasRenderingContext2D::isPointInPath(const float x, const float y) @@ -631,20 +591,17 @@ bool CanvasRenderingContext2D::isPointInPath(const float x, const float y) FloatPoint point(x, y); // We have to invert the current transform to ensure we correctly handle the // transforms applied to the current path. - AffineTransform ctm = c->getCTM(); + AffineTransform ctm = state().m_transform; if (!ctm.isInvertible()) return false; FloatPoint transformedPoint = ctm.inverse().mapPoint(point); - return state().m_path.contains(transformedPoint); + return m_path.contains(transformedPoint); } -void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height, ExceptionCode& ec) +void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height) { - ec = 0; - if (!(width >= 0 && height >= 0)) { - ec = INDEX_SIZE_ERR; + if (!validateRectForCanvas(x, y, width, height)) return; - } GraphicsContext* c = drawingContext(); if (!c) return; @@ -653,81 +610,37 @@ void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he c->clearRect(rect); } -void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height, ExceptionCode& ec) +void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height) { - ec = 0; - - if (!(width >= 0 && height >= 0)) { - ec = INDEX_SIZE_ERR; + if (!validateRectForCanvas(x, y, width, height)) return; - } GraphicsContext* c = drawingContext(); if (!c) return; - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGRect rect = CGRectMake(x, y, width, height); - willDraw(rect); - - if (state().m_fillStyle->gradient()) { - // Shading works on the entire clip region, so convert the rect to a clip. - c->save(); - CGContextClipToRect(c->platformContext(), rect); - CGContextDrawShading(c->platformContext(), state().m_fillStyle->gradient()->platformShading()); - c->restore(); - } else { - if (state().m_fillStyle->pattern()) - applyFillPattern(); - CGContextFillRect(c->platformContext(), rect); - } -#elif defined(ANDROID_CANVAS_IMPL) - CanvasStyle* s = state().m_fillStyle.get(); - FloatRect rect = FloatRect(x, y, width, height); - willDraw(rect); - c->fillRect(rect, extractGradient(s), extractPattern(s)); -#elif PLATFORM(QT) - QRectF rect(x, y, width, height); - willDraw(rect); - QPainter* p = static_cast<QPainter*>(c->platformContext()); - if (state().m_fillStyle->gradient()) { - p->fillRect(rect, QBrush(*(state().m_fillStyle->gradient()->platformShading()))); - } else { - if (state().m_fillStyle->pattern()) - applyFillPattern(); - p->fillRect(rect, p->brush()); - } -#elif PLATFORM(CAIRO) FloatRect rect(x, y, width, height); willDraw(rect); - cairo_t* cr = c->platformContext(); - cairo_save(cr); - if (state().m_fillStyle->gradient()) { - cairo_set_source(cr, state().m_fillStyle->gradient()->platformShading()); - } else { - if (state().m_fillStyle->pattern()) - applyFillPattern(); - } - cairo_rectangle(cr, x, y, width, height); - cairo_fill(cr); - cairo_restore(cr); -#endif + + c->save(); + c->fillRect(rect); + c->restore(); } -void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height, ExceptionCode& ec) +void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height) { - strokeRect(x, y, width, height, state().m_lineWidth, ec); + if (!validateRectForCanvas(x, y, width, height)) + return; + strokeRect(x, y, width, height, state().m_lineWidth); } -void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height, float lineWidth, ExceptionCode& ec) +void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height, float lineWidth) { - ec = 0; - - if (!(width >= 0 && height >= 0 && lineWidth >= 0)) { - ec = INDEX_SIZE_ERR; + if (!validateRectForCanvas(x, y, width, height)) + return; + + if (!(lineWidth >= 0)) return; - } GraphicsContext* c = drawingContext(); if (!c) @@ -739,18 +652,29 @@ void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h boundingRect.inflate(lineWidth / 2); willDraw(boundingRect); -#ifndef ANDROID_CANVAS_IMPL - // FIXME: No support for gradients! - if (state().m_strokeStyle->pattern()) - applyStrokePattern(); - c->strokeRect(rect, lineWidth); -#else - CanvasStyle* s = state().m_strokeStyle.get(); - c->strokeRect(rect, lineWidth, extractGradient(s), extractPattern(s)); -#endif } +#if PLATFORM(CG) +static inline CGSize adjustedShadowSize(CGFloat width, CGFloat height) +{ + // Work around <rdar://problem/5539388> by ensuring that shadow offsets will get truncated + // to the desired integer. + static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128); + if (width > 0) + width += extraShadowOffset; + else if (width < 0) + width -= extraShadowOffset; + + if (height > 0) + height += extraShadowOffset; + else if (height < 0) + height -= extraShadowOffset; + + return CGSizeMake(width, height); +} +#endif + void CanvasRenderingContext2D::setShadow(float width, float height, float blur) { state().m_shadowOffset = FloatSize(width, height); @@ -782,7 +706,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur, CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); CGColorRef color = CGColorCreate(colorSpace, components); CGColorSpaceRelease(colorSpace); - CGContextSetShadowWithColor(c->platformContext(), CGSizeMake(width, height), blur, color); + CGContextSetShadowWithColor(c->platformContext(), adjustedShadowSize(width, -height), blur, color); CGColorRelease(color); #endif } @@ -809,7 +733,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur, CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGColorRef shadowColor = CGColorCreate(colorSpace, components); CGColorSpaceRelease(colorSpace); - CGContextSetShadowWithColor(c->platformContext(), CGSizeMake(width, height), blur, shadowColor); + CGContextSetShadowWithColor(c->platformContext(), adjustedShadowSize(width, -height), blur, shadowColor); CGColorRelease(shadowColor); #endif } @@ -829,7 +753,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur, CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); CGColorRef color = CGColorCreate(colorSpace, components); CGColorSpaceRelease(colorSpace); - CGContextSetShadowWithColor(c->platformContext(), CGSizeMake(width, height), blur, color); + CGContextSetShadowWithColor(c->platformContext(), adjustedShadowSize(width, -height), blur, color); CGColorRelease(color); #endif } @@ -849,7 +773,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur, CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGColorRef shadowColor = CGColorCreate(colorSpace, components); CGColorSpaceRelease(colorSpace); - CGContextSetShadowWithColor(c->platformContext(), CGSizeMake(width, height), blur, shadowColor); + CGContextSetShadowWithColor(c->platformContext(), adjustedShadowSize(width, -height), blur, shadowColor); CGColorRelease(shadowColor); #endif } @@ -869,7 +793,7 @@ void CanvasRenderingContext2D::setShadow(float width, float height, float blur, CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceCMYK(); CGColorRef shadowColor = CGColorCreate(colorSpace, components); CGColorSpaceRelease(colorSpace); - CGContextSetShadowWithColor(dc->platformContext(), CGSizeMake(width, height), blur, shadowColor); + CGContextSetShadowWithColor(dc->platformContext(), adjustedShadowSize(width, -height), blur, shadowColor); CGColorRelease(shadowColor); #endif } @@ -901,7 +825,8 @@ void CanvasRenderingContext2D::applyShadow() CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGColorRef color = CGColorCreate(colorSpace, components); CGColorSpaceRelease(colorSpace); - CGContextSetShadowWithColor(c->platformContext(), state().m_shadowOffset, state().m_shadowBlur, color); + + CGContextSetShadowWithColor(c->platformContext(), adjustedShadowSize(state().m_shadowOffset.width(), -state().m_shadowOffset.height()), state().m_shadowBlur, color); CGColorRelease(color); #endif } @@ -909,10 +834,18 @@ void CanvasRenderingContext2D::applyShadow() static IntSize size(HTMLImageElement* image) { if (CachedImage* cachedImage = image->cachedImage()) - return cachedImage->imageSize(); + return cachedImage->imageSize(1.0f); // FIXME: Not sure about this. return IntSize(); } +static inline FloatRect normalizeRect(const FloatRect& rect) +{ + return FloatRect(min(rect.x(), rect.right()), + min(rect.y(), rect.bottom()), + max(rect.width(), -rect.width()), + max(rect.height(), -rect.height())); +} + void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y) { ASSERT(image); @@ -929,12 +862,12 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, drawImage(image, FloatRect(0, 0, s.width(), s.height()), FloatRect(x, y, width, height), ec); } -#if defined(ANDROID_CANVAS_IMPL) -static void dumprect(const char label[], const FloatRect& r) +void CanvasRenderingContext2D::checkOrigin(const KURL& url) { - printf("----- %s [%g %g %g %g]\n", label, r.x(), r.y(), r.width(), r.height()); + RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url); + if (!m_canvas->document()->securityOrigin()->canAccess(origin.get())) + m_canvas->setOriginTainted(); } -#endif void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode& ec) @@ -944,13 +877,12 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec ec = 0; FloatRect imageRect = FloatRect(FloatPoint(), size(image)); - if (!(imageRect.contains(srcRect) && srcRect.width() >= 0 && srcRect.height() >= 0 - && dstRect.width() >= 0 && dstRect.height() >= 0)) { + if (!imageRect.contains(normalizeRect(srcRect)) || srcRect.width() == 0 || srcRect.height() == 0) { ec = INDEX_SIZE_ERR; return; } - if (srcRect.isEmpty() || dstRect.isEmpty()) + if (!dstRect.width() || !dstRect.height()) return; GraphicsContext* c = drawingContext(); @@ -961,10 +893,16 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec if (!cachedImage) return; + if (m_canvas->originClean()) + checkOrigin(cachedImage->response().url()); + + if (m_canvas->originClean() && !cachedImage->image()->hasSingleSecurityOrigin()) + m_canvas->setOriginTainted(); + FloatRect sourceRect = c->roundToDevicePixels(srcRect); FloatRect destRect = c->roundToDevicePixels(dstRect); willDraw(destRect); -#if defined(ANDROID_CANVAS_IMPL) +#if PLATFORM(SGL) // this seems like a bug fix as well. // can't see how the std code can use destRect/sourceRect, since they are scaled by matrix c->drawImage(cachedImage->image(), dstRect, srcRect, state().m_globalComposite); @@ -995,13 +933,12 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, const FloatR ec = 0; FloatRect srcCanvasRect = FloatRect(FloatPoint(), canvas->size()); - if (!(srcCanvasRect.contains(srcRect) && srcRect.width() >= 0 && srcRect.height() >= 0 - && dstRect.width() >= 0 && dstRect.height() >= 0)) { + if (!srcCanvasRect.contains(normalizeRect(srcRect)) || srcRect.width() == 0 || srcRect.height() == 0) { ec = INDEX_SIZE_ERR; return; } - if (srcRect.isEmpty() || dstRect.isEmpty()) + if (!dstRect.width() || !dstRect.height()) return; GraphicsContext* c = drawingContext(); @@ -1012,68 +949,16 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, const FloatR FloatRect destRect = c->roundToDevicePixels(dstRect); // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGImageRef platformImage = canvas->createPlatformImage(); - if (!platformImage) + ImageBuffer* buffer = canvas->buffer(); + if (!buffer) return; - willDraw(destRect); + if (!canvas->originClean()) + m_canvas->setOriginTainted(); - float iw = CGImageGetWidth(platformImage); - float ih = CGImageGetHeight(platformImage); - if (sourceRect.x() == 0 && sourceRect.y() == 0 && iw == sourceRect.width() && ih == sourceRect.height()) { - // Fast path, yay! - CGContextDrawImage(c->platformContext(), destRect, platformImage); - } else { - // Slow path, boo! - // Create a new bitmap of the appropriate size and then draw that into our context. - - size_t csw = static_cast<size_t>(ceilf(sourceRect.width())); - size_t csh = static_cast<size_t>(ceilf(sourceRect.height())); - - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - size_t bytesPerRow = csw * 4; - void* buffer = fastMalloc(csh * bytesPerRow); - - CGContextRef clippedSourceContext = CGBitmapContextCreate(buffer, csw, csh, - 8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); - CGColorSpaceRelease(colorSpace); - CGContextTranslateCTM(clippedSourceContext, -sourceRect.x(), -sourceRect.y()); - CGContextDrawImage(clippedSourceContext, CGRectMake(0, 0, iw, ih), platformImage); - - CGImageRef clippedSourceImage = CGBitmapContextCreateImage(clippedSourceContext); - CGContextRelease(clippedSourceContext); - - CGContextDrawImage(c->platformContext(), destRect, clippedSourceImage); - CGImageRelease(clippedSourceImage); - - fastFree(buffer); - } - - CGImageRelease(platformImage); -#elif defined(ANDROID_CANVAS_IMPL) - willDraw(destRect); - c->drawOffscreenContext(canvas->drawingContext(), &srcRect, dstRect); -#elif PLATFORM(QT) - QImage px = canvas->createPlatformImage(); - if (px.isNull()) - return; - willDraw(dstRect); - QPainter* painter = static_cast<QPainter*>(c->platformContext()); - painter->drawImage(dstRect, px, srcRect); -#elif PLATFORM(CAIRO) - cairo_surface_t* image = canvas->createPlatformImage(); - if (!image) - return; - willDraw(dstRect); - cairo_t* cr = c->platformContext(); - cairo_save(cr); - cairo_set_source_surface(cr, image, srcRect.x(), srcRect.y()); - cairo_surface_destroy(image); - cairo_rectangle(cr, dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height()); - cairo_fill(cr); - cairo_restore(cr); -#endif + c->drawImage(buffer->image(), destRect, sourceRect, state().m_globalComposite); + willDraw(destRect); // This call comes after drawImage, since the buffer we draw into may be our own, and we need to make sure it is dirty. + // FIXME: Arguably willDraw should become didDraw and occur after drawing calls and not before them to avoid problems like this. } // FIXME: Why isn't this just another overload of drawImage? Why have a different name? @@ -1089,6 +974,12 @@ void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, if (!cachedImage) return; + if (m_canvas->originClean()) + checkOrigin(cachedImage->response().url()); + + if (m_canvas->originClean() && !cachedImage->image()->hasSingleSecurityOrigin()) + m_canvas->setOriginTainted(); + GraphicsContext* c = drawingContext(); if (!c) return; @@ -1112,14 +1003,24 @@ void CanvasRenderingContext2D::setCompositeOperation(const String& operation) setGlobalCompositeOperation(operation); } -PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1) +PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1, ExceptionCode& ec) { - return new CanvasGradient(FloatPoint(x0, y0), FloatPoint(x1, y1)); + if (!isfinite(x0) || !isfinite(y0) || !isfinite(x1) || !isfinite(y1)) { + ec = NOT_SUPPORTED_ERR; + return 0; + } + + return CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1)); } -PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1) +PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionCode& ec) { - return new CanvasGradient(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); + if (!isfinite(x0) || !isfinite(y0) || !isfinite(r0) || + !isfinite(x1) || !isfinite(y1) || !isfinite(r1)) { + ec = NOT_SUPPORTED_ERR; + return 0; + } + return CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); } PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElement* image, @@ -1130,42 +1031,40 @@ PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageEleme CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, ec); if (ec) return 0; - return new CanvasPattern(image ? image->cachedImage() : 0, repeatX, repeatY); + + if (!image->complete()) { + ec = INVALID_STATE_ERR; + return 0; + } + + CachedImage* cachedImage = image->cachedImage(); + if (!cachedImage || !image->cachedImage()->image()) + return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true); + + KURL url(cachedImage->url()); + RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url); + bool originClean = m_canvas->document()->securityOrigin()->canAccess(origin.get()); + return CanvasPattern::create(cachedImage->image(), repeatX, repeatY, originClean); } PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElement* canvas, const String& repetitionType, ExceptionCode& ec) { + if (!canvas->width() || !canvas->height()) { + ec = INVALID_STATE_ERR; + return 0; + } + bool repeatX, repeatY; ec = 0; CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, ec); if (ec) return 0; - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGImageRef image = canvas->createPlatformImage(); - if (!image) - return 0; - PassRefPtr<CanvasPattern> pattern = new CanvasPattern(image, repeatX, repeatY); - CGImageRelease(image); - return pattern; -#elif PLATFORM(CAIRO) - cairo_surface_t* surface = canvas->createPlatformImage(); - if (!surface) - return 0; - PassRefPtr<CanvasPattern> pattern = new CanvasPattern(surface, repeatX, repeatY); - cairo_surface_destroy(surface); - return pattern; -#else - notImplemented(); - return 0; -#endif + return CanvasPattern::create(canvas->buffer()->image(), repeatX, repeatY, canvas->originClean()); } void CanvasRenderingContext2D::willDraw(const FloatRect& r) { - if (!m_canvas) - return; GraphicsContext* c = drawingContext(); if (!c) return; @@ -1175,111 +1074,293 @@ void CanvasRenderingContext2D::willDraw(const FloatRect& r) GraphicsContext* CanvasRenderingContext2D::drawingContext() const { - if (!m_canvas) - return 0; return m_canvas->drawingContext(); } -void CanvasRenderingContext2D::applyStrokePattern() +static PassRefPtr<ImageData> createEmptyImageData(const IntSize& size) { - GraphicsContext* c = drawingContext(); - if (!c) - return; + PassRefPtr<ImageData> data = ImageData::create(size.width(), size.height()); + memset(data->data()->data().data(), 0, data->data()->length()); + return data; +} -#if PLATFORM(CG) - // Check for case where the pattern is already set. - CGAffineTransform m = CGContextGetCTM(c->platformContext()); - if (state().m_appliedStrokePattern - && CGAffineTransformEqualToTransform(m, state().m_strokeStylePatternTransform)) - return; +PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh) const +{ + FloatSize unscaledSize(sw, sh); + IntSize scaledSize = m_canvas->convertLogicalToDevice(unscaledSize); + if (scaledSize.width() < 1) + scaledSize.setWidth(1); + if (scaledSize.height() < 1) + scaledSize.setHeight(1); + + return createEmptyImageData(scaledSize); +} - CanvasPattern* pattern = state().m_strokeStyle->pattern(); - if (!pattern) - return; +PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionCode& ec) const +{ + if (!m_canvas->originClean()) { + ec = SECURITY_ERR; + return 0; + } + + FloatRect unscaledRect(sx, sy, sw, sh); + IntRect scaledRect = m_canvas->convertLogicalToDevice(unscaledRect); + if (scaledRect.width() < 1) + scaledRect.setWidth(1); + if (scaledRect.height() < 1) + scaledRect.setHeight(1); + ImageBuffer* buffer = m_canvas ? m_canvas->buffer() : 0; + if (!buffer) + return createEmptyImageData(scaledRect.size()); + return buffer->getImageData(scaledRect); +} - CGPatternRef platformPattern = pattern->createPattern(m); - if (!platformPattern) +void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionCode& ec) +{ + if (!data) { + ec = TYPE_MISMATCH_ERR; return; + } + putImageData(data, dx, dy, 0, 0, data->width(), data->height(), ec); +} - CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0); - CGContextSetStrokeColorSpace(c->platformContext(), patternSpace); - CGColorSpaceRelease(patternSpace); - - const CGFloat patternAlpha = 1; - CGContextSetStrokePattern(c->platformContext(), platformPattern, &patternAlpha); - CGPatternRelease(platformPattern); +void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, float dirtyX, float dirtyY, + float dirtyWidth, float dirtyHeight, ExceptionCode& ec) +{ + if (!data) { + ec = TYPE_MISMATCH_ERR; + return; + } + if (!isfinite(dx) || !isfinite(dy) || !isfinite(dirtyX) || + !isfinite(dirtyY) || !isfinite(dirtyWidth) || !isfinite(dirtyHeight)) { + ec = INDEX_SIZE_ERR; + return; + } - state().m_strokeStylePatternTransform = m; -#elif PLATFORM(QT) - fprintf(stderr, "FIXME: CanvasRenderingContext2D::applyStrokePattern\n"); -#elif PLATFORM(CAIRO) - CanvasPattern* pattern = state().m_strokeStyle->pattern(); - if (!pattern) + ImageBuffer* buffer = m_canvas->buffer(); + if (!buffer) return; - cairo_t* cr = c->platformContext(); - cairo_matrix_t m; - cairo_get_matrix(cr, &m); + if (dirtyWidth < 0) { + dirtyX += dirtyWidth; + dirtyWidth = -dirtyWidth; + } - cairo_pattern_t* platformPattern = pattern->createPattern(m); - if (!platformPattern) - return; + if (dirtyHeight < 0) { + dirtyY += dirtyHeight; + dirtyHeight = -dirtyHeight; + } - cairo_set_source(cr, platformPattern); - cairo_pattern_destroy(platformPattern); -#endif - state().m_appliedStrokePattern = true; + FloatRect clipRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight); + clipRect.intersect(IntRect(0, 0, data->width(), data->height())); + IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy)); + IntRect sourceRect = enclosingIntRect(clipRect); + sourceRect.move(destOffset); + sourceRect.intersect(IntRect(IntPoint(), buffer->size())); + if (sourceRect.isEmpty()) + return; + willDraw(sourceRect); + sourceRect.move(-destOffset); + IntPoint destPoint(destOffset.width(), destOffset.height()); + + buffer->putImageData(data, sourceRect, destPoint); +} + +String CanvasRenderingContext2D::font() const +{ + return state().m_unparsedFont; } -void CanvasRenderingContext2D::applyFillPattern() +void CanvasRenderingContext2D::setFont(const String& newFont) { + RefPtr<CSSMutableStyleDeclaration> tempDecl = CSSMutableStyleDeclaration::create(); + CSSParser parser(!m_canvas->document()->inCompatMode()); // Use the parse mode of the canvas' document when parsing CSS. + + String declarationText("font: "); + declarationText += newFont; + parser.parseDeclaration(tempDecl.get(), declarationText); + if (!tempDecl->length()) + return; + + // The parse succeeded. + state().m_unparsedFont = newFont; + + // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work + // relative to the canvas. + RefPtr<RenderStyle> newStyle = RenderStyle::create(); + if (m_canvas->computedStyle()) + newStyle->setFontDescription(m_canvas->computedStyle()->fontDescription()); + + // Now map the font property into the style. + CSSStyleSelector* styleSelector = m_canvas->document()->styleSelector(); + styleSelector->applyPropertyToStyle(CSSPropertyFont, tempDecl->getPropertyCSSValue(CSSPropertyFont).get(), newStyle.get()); + + state().m_font = newStyle->font(); + state().m_font.update(styleSelector->fontSelector()); + state().m_realizedFont = true; + + // Set the font in the graphics context. GraphicsContext* c = drawingContext(); if (!c) return; + c->setFont(state().m_font); +} + +String CanvasRenderingContext2D::textAlign() const +{ + return textAlignName(state().m_textAlign); +} -#if PLATFORM(CG) - // Check for case where the pattern is already set. - CGAffineTransform m = CGContextGetCTM(c->platformContext()); - if (state().m_appliedFillPattern - && CGAffineTransformEqualToTransform(m, state().m_fillStylePatternTransform)) +void CanvasRenderingContext2D::setTextAlign(const String& s) +{ + TextAlign align; + if (!parseTextAlign(s, align)) return; + state().m_textAlign = align; +} + +String CanvasRenderingContext2D::textBaseline() const +{ + return textBaselineName(state().m_textBaseline); +} - CanvasPattern* pattern = state().m_fillStyle->pattern(); - if (!pattern) +void CanvasRenderingContext2D::setTextBaseline(const String& s) +{ + TextBaseline baseline; + if (!parseTextBaseline(s, baseline)) return; + state().m_textBaseline = baseline; +} - CGPatternRef platformPattern = pattern->createPattern(m); - if (!platformPattern) - return; +void CanvasRenderingContext2D::fillText(const String& text, float x, float y) +{ + drawTextInternal(text, x, y, true); +} + +void CanvasRenderingContext2D::fillText(const String& text, float x, float y, float maxWidth) +{ + drawTextInternal(text, x, y, true, maxWidth, true); +} + +void CanvasRenderingContext2D::strokeText(const String& text, float x, float y) +{ + drawTextInternal(text, x, y, false); +} - CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0); - CGContextSetFillColorSpace(c->platformContext(), patternSpace); - CGColorSpaceRelease(patternSpace); +void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, float maxWidth) +{ + drawTextInternal(text, x, y, false, maxWidth, true); +} - const CGFloat patternAlpha = 1; - CGContextSetFillPattern(c->platformContext(), platformPattern, &patternAlpha); - CGPatternRelease(platformPattern); +PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text) +{ + RefPtr<TextMetrics> metrics = TextMetrics::create(); + metrics->setWidth(accessFont().width(TextRun(text.characters(), text.length()))); + return metrics; +} - state().m_fillStylePatternTransform = m; -#elif PLATFORM(QT) - fprintf(stderr, "FIXME: CanvasRenderingContext2D::applyFillPattern\n"); -#elif PLATFORM(CAIRO) - CanvasPattern* pattern = state().m_fillStyle->pattern(); - if (!pattern) +void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth, bool useMaxWidth) +{ + GraphicsContext* c = drawingContext(); + if (!c) return; + + const Font& font = accessFont(); + + // FIXME: Handle maxWidth. + // FIXME: Need to turn off font smoothing. + + bool rtl = m_canvas->computedStyle() ? m_canvas->computedStyle()->direction() == RTL : false; + bool override = m_canvas->computedStyle() ? m_canvas->computedStyle()->unicodeBidi() == Override : false; + + unsigned length = text.length(); + const UChar* string = text.characters(); + TextRun textRun(string, length, 0, 0, 0, rtl, override, false, false); + + // Draw the item text at the correct point. + FloatPoint location(x, y); + switch (state().m_textBaseline) { + case TopTextBaseline: + case HangingTextBaseline: + location.setY(y + font.ascent()); + break; + case BottomTextBaseline: + case IdeographicTextBaseline: + location.setY(y - font.descent()); + break; + case MiddleTextBaseline: + location.setY(y - font.descent() + font.height() / 2); + break; + case AlphabeticTextBaseline: + default: + // Do nothing. + break; + } + + float width = font.width(TextRun(text, false, 0, 0, rtl, override)); + + TextAlign align = state().m_textAlign; + if (align == StartTextAlign) + align = rtl ? RightTextAlign : LeftTextAlign; + else if (align == EndTextAlign) + align = rtl ? LeftTextAlign : RightTextAlign; + + switch (align) { + case CenterTextAlign: + location.setX(location.x() - width / 2); + break; + case RightTextAlign: + location.setX(location.x() - width); + break; + default: + break; + } + + // The slop built in to this mask rect matches the heuristic used in FontCGWin.cpp for GDI text. + FloatRect textRect = FloatRect(location.x() - font.height() / 2, location.y() - font.ascent() - font.lineGap(), + width + font.height(), font.lineSpacing()); + if (!fill) + textRect.inflate(c->strokeThickness() / 2); + + CanvasStyle* drawStyle = fill ? state().m_fillStyle.get() : state().m_strokeStyle.get(); + if (drawStyle->canvasGradient() || drawStyle->canvasPattern()) { + IntRect maskRect = enclosingIntRect(textRect); + + auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(maskRect.size(), false); + + GraphicsContext* maskImageContext = maskImage->context(); - cairo_t* cr = c->platformContext(); - cairo_matrix_t m; - cairo_get_matrix(cr, &m); + if (fill) + maskImageContext->setFillColor(Color::black); + else { + maskImageContext->setStrokeColor(Color::black); + maskImageContext->setStrokeThickness(c->strokeThickness()); + } + + maskImageContext->setTextDrawingMode(fill ? cTextFill : cTextStroke); + maskImageContext->translate(-maskRect.x(), -maskRect.y()); + + maskImageContext->setFont(font); + maskImageContext->drawBidiText(textRun, location); + + c->save(); + c->clipToImageBuffer(maskRect, maskImage.get()); + drawStyle->applyFillColor(c); + c->fillRect(maskRect); + c->restore(); - cairo_pattern_t* platformPattern = pattern->createPattern(m); - if (!platformPattern) return; + } - cairo_set_source(cr, platformPattern); - cairo_pattern_destroy(platformPattern); -#endif - state().m_appliedFillPattern = true; + c->setTextDrawingMode(fill ? cTextFill : cTextStroke); + c->drawBidiText(textRun, location); +} + +const Font& CanvasRenderingContext2D::accessFont() +{ + if (!state().m_realizedFont) + setFont(state().m_unparsedFont); + return state().m_font; } } // namespace WebCore diff --git a/WebCore/html/CanvasRenderingContext2D.h b/WebCore/html/CanvasRenderingContext2D.h index 30f7a53..e720f21 100644 --- a/WebCore/html/CanvasRenderingContext2D.h +++ b/WebCore/html/CanvasRenderingContext2D.h @@ -26,7 +26,9 @@ #ifndef CanvasRenderingContext2D_h #define CanvasRenderingContext2D_h +#include "AffineTransform.h" #include "FloatSize.h" +#include "Font.h" #include "GraphicsTypes.h" #include "Path.h" #include "PlatformString.h" @@ -45,13 +47,19 @@ namespace WebCore { class GraphicsContext; class HTMLCanvasElement; class HTMLImageElement; + class ImageData; + class KURL; + class TextMetrics; typedef int ExceptionCode; - class CanvasRenderingContext2D : public RefCounted<CanvasRenderingContext2D> { + class CanvasRenderingContext2D : Noncopyable { public: CanvasRenderingContext2D(HTMLCanvasElement*); - + + void ref(); + void deref(); + HTMLCanvasElement* canvas() const { return m_canvas; } CanvasStyle* strokeStyle() const; @@ -121,7 +129,7 @@ namespace WebCore { void bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y); void arcTo(float x0, float y0, float x1, float y1, float radius, ExceptionCode&); void arc(float x, float y, float r, float sa, float ea, bool clockwise, ExceptionCode&); - void rect(float x, float y, float width, float height, ExceptionCode&); + void rect(float x, float y, float width, float height); void fill(); void stroke(); @@ -129,10 +137,10 @@ namespace WebCore { bool isPointInPath(const float x, const float y); - void clearRect(float x, float y, float width, float height, ExceptionCode&); - void fillRect(float x, float y, float width, float height, ExceptionCode&); - void strokeRect(float x, float y, float width, float height, ExceptionCode&); - void strokeRect(float x, float y, float width, float height, float lineWidth, ExceptionCode&); + void clearRect(float x, float y, float width, float height); + void fillRect(float x, float y, float width, float height); + void strokeRect(float x, float y, float width, float height); + void strokeRect(float x, float y, float width, float height, float lineWidth); void setShadow(float width, float height, float blur); void setShadow(float width, float height, float blur, const String& color); @@ -158,21 +166,39 @@ namespace WebCore { void setCompositeOperation(const String&); - PassRefPtr<CanvasGradient> createLinearGradient(float x0, float y0, float x1, float y1); - PassRefPtr<CanvasGradient> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1); + PassRefPtr<CanvasGradient> createLinearGradient(float x0, float y0, float x1, float y1, ExceptionCode&); + PassRefPtr<CanvasGradient> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionCode&); PassRefPtr<CanvasPattern> createPattern(HTMLImageElement*, const String& repetitionType, ExceptionCode&); PassRefPtr<CanvasPattern> createPattern(HTMLCanvasElement*, const String& repetitionType, ExceptionCode&); - + + PassRefPtr<ImageData> createImageData(float width, float height) const; + PassRefPtr<ImageData> getImageData(float sx, float sy, float sw, float sh, ExceptionCode&) const; + void putImageData(ImageData*, float dx, float dy, ExceptionCode&); + void putImageData(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&); + void reset(); - void detachCanvas() { m_canvas = 0; } + + String font() const; + void setFont(const String&); + + String textAlign() const; + void setTextAlign(const String&); + + String textBaseline() const; + void setTextBaseline(const String&); + + void fillText(const String& text, float x, float y); + void fillText(const String& text, float x, float y, float maxWidth); + void strokeText(const String& text, float x, float y); + void strokeText(const String& text, float x, float y, float maxWidth); + PassRefPtr<TextMetrics> measureText(const String& text); private: struct State { State(); - + RefPtr<CanvasStyle> m_strokeStyle; RefPtr<CanvasStyle> m_fillStyle; - Path m_path; float m_lineWidth; LineCap m_lineCap; LineJoin m_lineJoin; @@ -182,13 +208,17 @@ namespace WebCore { String m_shadowColor; float m_globalAlpha; CompositeOperator m_globalComposite; - bool m_appliedStrokePattern; - bool m_appliedFillPattern; -#if PLATFORM(CG) - CGAffineTransform m_strokeStylePatternTransform; - CGAffineTransform m_fillStylePatternTransform; -#endif + AffineTransform m_transform; + + // Text state. + TextAlign m_textAlign; + TextBaseline m_textBaseline; + + String m_unparsedFont; + Font m_font; + bool m_realizedFont; }; + Path m_path; State& state() { return m_stateStack.last(); } const State& state() const { return m_stateStack.last(); } @@ -202,7 +232,15 @@ namespace WebCore { void applyStrokePattern(); void applyFillPattern(); + void drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth = 0, bool useMaxWidth = false); + + const Font& accessFont(); + +#if ENABLE(DASHBOARD_SUPPORT) void clearPathForDashboardBackwardCompatibilityMode(); +#endif + + void checkOrigin(const KURL&); HTMLCanvasElement* m_canvas; Vector<State, 1> m_stateStack; diff --git a/WebCore/html/CanvasRenderingContext2D.idl b/WebCore/html/CanvasRenderingContext2D.idl index 3d566d4..29c9a7a 100644 --- a/WebCore/html/CanvasRenderingContext2D.idl +++ b/WebCore/html/CanvasRenderingContext2D.idl @@ -26,6 +26,7 @@ module html { interface [ + GenerateConstructor, InterfaceUUID=98fb48ae-7216-489c-862b-8e1217fc4443, ImplementationUUID=ab4f0781-152f-450e-9546-5b3987491a54 ] CanvasRenderingContext2D { @@ -45,8 +46,10 @@ module html { attribute float globalAlpha; attribute [ConvertNullToNullString] DOMString globalCompositeOperation; - CanvasGradient createLinearGradient(in float x0, in float y0, in float x1, in float y1); - CanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1); + CanvasGradient createLinearGradient(in float x0, in float y0, in float x1, in float y1) + raises (DOMException); + CanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1) + raises (DOMException); attribute float lineWidth; attribute [ConvertNullToNullString] DOMString lineCap; @@ -58,10 +61,8 @@ module html { attribute float shadowBlur; attribute [ConvertNullToNullString] DOMString shadowColor; - void clearRect(in float x, in float y, in float width, in float height) - raises (DOMException); - void fillRect(in float x, in float y, in float width, in float height) - raises (DOMException); + void clearRect(in float x, in float y, in float width, in float height); + void fillRect(in float x, in float y, in float width, in float height); void beginPath(); void closePath(); @@ -71,8 +72,7 @@ module html { void bezierCurveTo(in float cp1x, in float cp1y, in float cp2x, in float cp2y, in float x, in float y); void arcTo(in float x1, in float y1, in float x2, in float y2, in float radius) raises (DOMException); - void rect(in float x, in float y, in float width, in float height) - raises (DOMException); + void rect(in float x, in float y, in float width, in float height); void arc(in float x, in float y, in float radius, in float startAngle, in float endAngle, in boolean anticlockwise) raises (DOMException); void fill(); @@ -80,6 +80,14 @@ module html { void clip(); boolean isPointInPath(in float x, in float y); + // text + attribute DOMString font; + attribute DOMString textAlign; + attribute DOMString textBaseline; + [Custom] void fillText(/* 4 */); + [Custom] void strokeText(/* 4 */); + TextMetrics measureText(in DOMString text); + // other void setAlpha(in float alpha); @@ -101,7 +109,13 @@ module html { [Custom] void createPattern(/* 2 */); attribute [Custom] custom strokeStyle; - attribute [Custom] custom fillStyle; + attribute [Custom] custom fillStyle; + + // pixel manipulation + ImageData createImageData(in float sw, in float sh); + ImageData getImageData(in float sx, in float sy, in float sw, in float sh) + raises(DOMException); + [Custom] void putImageData(/* in ImageData imagedata, in float dx, in float dy [, in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight] */); }; } diff --git a/WebCore/html/CanvasStyle.cpp b/WebCore/html/CanvasStyle.cpp index 073fb35..27d8a84 100644 --- a/WebCore/html/CanvasStyle.cpp +++ b/WebCore/html/CanvasStyle.cpp @@ -1,7 +1,8 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2007 Trolltech ASA + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,11 +35,8 @@ #include "GraphicsContext.h" #include <wtf/PassRefPtr.h> -#ifdef ANDROID_CANVAS_IMPL -static int F2B(float unit) -{ - return (int)(unit * 255); -} +#if PLATFORM(CG) +#include <CoreGraphics/CGContext.h> #endif #if PLATFORM(QT) @@ -48,28 +46,34 @@ static int F2B(float unit) #include <QColor> #elif PLATFORM(CAIRO) #include "NotImplemented.h" -#include <cairo.h> #endif namespace WebCore { CanvasStyle::CanvasStyle(const String& color) - : m_type(ColorString), m_color(color) + : m_type(ColorString) + , m_color(color) { } CanvasStyle::CanvasStyle(float grayLevel) - : m_type(GrayLevel), m_alpha(1), m_grayLevel(grayLevel) + : m_type(GrayLevel) + , m_alpha(1) + , m_grayLevel(grayLevel) { } CanvasStyle::CanvasStyle(const String& color, float alpha) - : m_type(ColorStringWithAlpha), m_color(color), m_alpha(alpha) + : m_type(ColorStringWithAlpha) + , m_color(color) + , m_alpha(alpha) { } CanvasStyle::CanvasStyle(float grayLevel, float alpha) - : m_type(GrayLevel), m_alpha(alpha), m_grayLevel(grayLevel) + : m_type(GrayLevel) + , m_alpha(alpha) + , m_grayLevel(grayLevel) { } @@ -84,12 +88,14 @@ CanvasStyle::CanvasStyle(float c, float m, float y, float k, float a) } CanvasStyle::CanvasStyle(PassRefPtr<CanvasGradient> gradient) - : m_type(gradient ? Gradient : ColorString), m_gradient(gradient) + : m_type(gradient ? Gradient : ColorString) + , m_gradient(gradient) { } CanvasStyle::CanvasStyle(PassRefPtr<CanvasPattern> pattern) - : m_type(pattern ? ImagePattern : ColorString), m_pattern(pattern) + : m_type(pattern ? ImagePattern : ColorString) + , m_pattern(pattern) { } @@ -97,230 +103,104 @@ void CanvasStyle::applyStrokeColor(GraphicsContext* context) { if (!context) return; -#if PLATFORM(QT) - QPainter* p = static_cast<QPainter*>(context->platformContext()); -#elif PLATFORM(CAIRO) - cairo_t* cr = context->platformContext(); -#endif switch (m_type) { case ColorString: { RGBA32 color = 0; // default is transparant black - CSSParser::parseColor(color, m_color); - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGContextSetRGBStrokeColor(context->platformContext(), - ((color >> 16) & 0xFF) / 255.0f, - ((color >> 8) & 0xFF) / 255.0f, - (color & 0xFF) / 255.0f, - ((color >> 24) & 0xFF) / 255.0f); -#elif defined(ANDROID_CANVAS_IMPL) - context->setStrokeColor(Color(color)); -#elif PLATFORM(QT) - QPen currentPen = p->pen(); - currentPen.setColor((QColor(QRgb(color)))); - p->setPen(currentPen); -#elif PLATFORM(CAIRO) - // FIXME: fill and stroke color should be dealt with separately - cairo_set_source_rgba(cr, - ((color >> 16) & 0xFF) / 255.0f, - ((color >> 8) & 0xFF) / 255.0f, - (color & 0xFF) / 255.0f, - ((color >> 24) & 0xFF) / 255.0f); -#endif + if (CSSParser::parseColor(color, m_color)) + context->setStrokeColor(color); break; } case ColorStringWithAlpha: { RGBA32 color = 0; // default is transparant black - CSSParser::parseColor(color, m_color); - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGContextSetRGBStrokeColor(context->platformContext(), - ((color >> 16) & 0xFF) / 255.0f, - ((color >> 8) & 0xFF) / 255.0f, - (color & 0xFF) / 255.0f, - m_alpha); -#elif defined(ANDROID_CANVAS_IMPL) - context->setStrokeColor(Color((color & 0x00FFFFFF) | (F2B(m_alpha) << 8))); -#elif PLATFORM(QT) - QPen currentPen = p->pen(); - QColor clr = QColor(QRgb(color)); - clr.setAlphaF(m_alpha); - currentPen.setColor(clr); - p->setPen(currentPen); -#elif PLATFORM(CAIRO) - // FIXME: fill and stroke color should be dealt with separately - cairo_set_source_rgba(cr, - ((color >> 16) & 0xFF) / 255.0f, - ((color >> 8) & 0xFF) / 255.0f, - (color & 0xFF) / 255.0f, - ((color >> 24) & 0xFF) / 255.0f); -#endif + if (CSSParser::parseColor(color, m_color)) + context->setStrokeColor(colorWithOverrideAlpha(color, m_alpha)); break; } - case GrayLevel: { - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGContextSetGrayStrokeColor(context->platformContext(), m_grayLevel, m_alpha); -#elif defined(ANDROID_CANVAS_IMPL) - { - int gray = F2B(m_grayLevel); - context->setStrokeColor(Color(makeRGBA(gray, gray, gray, F2B(m_alpha)))); - } -#elif PLATFORM(QT) - QColor clr; - QPen currentPen = p->pen(); - clr.setRgbF(m_grayLevel, m_grayLevel, m_grayLevel, m_alpha); - currentPen.setColor(clr); - p->setPen(currentPen); -#elif PLATFORM(CAIRO) - cairo_set_source_rgba(cr, m_grayLevel, m_grayLevel, m_grayLevel, m_alpha); -#endif + case GrayLevel: + // We're only supporting 255 levels of gray here. Since this isn't + // even part of HTML5, I don't expect anyone will care. If they do + // we'll make a fancier Color abstraction. + context->setStrokeColor(Color(m_grayLevel, m_grayLevel, m_grayLevel, m_alpha)); break; - } - case RGBA: { - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGContextSetRGBStrokeColor(context->platformContext(), m_red, m_green, m_blue, m_alpha); -#elif defined(ANDROID_CANVAS_IMPL) - context->setStrokeColor(Color(makeRGBA(F2B(m_red), F2B(m_green), F2B(m_blue), F2B(m_alpha)))); -#elif PLATFORM(QT) - QPen currentPen = p->pen(); - QColor clr; - clr.setRgbF(m_red, m_green, m_blue, m_alpha); - currentPen.setColor(clr); - p->setPen(currentPen); -#elif PLATFORM(CAIRO) - // FIXME: fill and stroke color should be dealt with separately - cairo_set_source_rgba(cr, m_red, m_green, m_blue, m_alpha); -#endif + case RGBA: + context->setStrokeColor(Color(m_red, m_green, m_blue, m_alpha)); break; - } case CMYKA: { // FIXME: Do this through platform-independent GraphicsContext API. + // We'll need a fancier Color abstraction to support CYMKA correctly #if PLATFORM(CG) CGContextSetCMYKStrokeColor(context->platformContext(), m_cyan, m_magenta, m_yellow, m_black, m_alpha); #elif PLATFORM(QT) - QPen currentPen = p->pen(); + QPen currentPen = context->platformContext()->pen(); QColor clr; clr.setCmykF(m_cyan, m_magenta, m_yellow, m_black, m_alpha); currentPen.setColor(clr); - p->setPen(currentPen); + context->platformContext()->setPen(currentPen); #elif PLATFORM(CAIRO) notImplemented(); +#elif PLATFORM(SGL) + context->setCMYKAStrokeColor(m_cyan, m_magenta, m_yellow, m_black, m_alpha); #endif break; } case Gradient: + context->setStrokeGradient(canvasGradient()->gradient()); + break; case ImagePattern: + context->setStrokePattern(canvasPattern()->pattern()); break; } } -// Cairo's graphics model allows us to share a single code path for -// stroke and fill. -#if !PLATFORM(CAIRO) void CanvasStyle::applyFillColor(GraphicsContext* context) { if (!context) return; -#if PLATFORM(QT) - QPainter* p = static_cast<QPainter*>(context->platformContext()); -#endif switch (m_type) { case ColorString: { - RGBA32 color = 0; // default is transparant black - CSSParser::parseColor(color, m_color); - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGContextSetRGBFillColor(context->platformContext(), - ((color >> 16) & 0xFF) / 255.0f, - ((color >> 8) & 0xFF) / 255.0f, - (color & 0xFF) / 255.0f, - ((color >> 24) & 0xFF) / 255.0f); -#elif defined(ANDROID_CANVAS_IMPL) - context->setFillColor(Color(color)); -#elif PLATFORM(QT) - QBrush currentBrush = p->brush(); - QColor clr; - clr.setRgb(QRgb(color)); - currentBrush.setColor(clr); - p->setBrush(currentBrush); -#endif + RGBA32 rgba = 0; // default is transparant black + if (CSSParser::parseColor(rgba, m_color)) + context->setFillColor(rgba); break; } case ColorStringWithAlpha: { RGBA32 color = 0; // default is transparant black - CSSParser::parseColor(color, m_color); - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGContextSetRGBFillColor(context->platformContext(), - ((color >> 16) & 0xFF) / 255.0f, - ((color >> 8) & 0xFF) / 255.0f, - (color & 0xFF) / 255.0f, - m_alpha); -#elif defined(ANDROID_CANVAS_IMPL) - context->setFillColor(Color((color & 0x00FFFFFF) | (F2B(m_alpha) << 8))); -#elif PLATFORM(QT) - QBrush currentBrush = p->brush(); - QColor clr; - clr.setRgb(QRgb(color)); - clr.setAlphaF(m_alpha); - currentBrush.setColor(clr); - p->setBrush(currentBrush); -#endif + if (CSSParser::parseColor(color, m_color)) + context->setFillColor(colorWithOverrideAlpha(color, m_alpha)); break; } - case GrayLevel: { - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGContextSetGrayFillColor(context->platformContext(), m_grayLevel, m_alpha); -#elif defined(ANDROID_CANVAS_IMPL) - { - int gray = F2B(m_grayLevel); - context->setFillColor(Color(gray, gray, gray, F2B(m_alpha))); - } -#elif PLATFORM(QT) - QBrush currentBrush = p->brush(); - QColor clr; - clr.setRgbF(m_grayLevel, m_grayLevel, m_grayLevel, m_alpha); - currentBrush.setColor(clr); - p->setBrush(currentBrush); -#endif + case GrayLevel: + // We're only supporting 255 levels of gray here. Since this isn't + // even part of HTML5, I don't expect anyone will care. If they do + // we'll make a fancier Color abstraction. + context->setFillColor(Color(m_grayLevel, m_grayLevel, m_grayLevel, m_alpha)); break; - } - case RGBA: { - // FIXME: Do this through platform-independent GraphicsContext API. -#if PLATFORM(CG) - CGContextSetRGBFillColor(context->platformContext(), m_red, m_green, m_blue, m_alpha); -#elif defined(ANDROID_CANVAS_IMPL) - context->setFillColor(Color(F2B(m_red), F2B(m_green), F2B(m_blue), F2B(m_alpha))); -#elif PLATFORM(QT) - QBrush currentBrush = p->brush(); - QColor clr; - clr.setRgbF(m_red, m_green, m_blue, m_alpha); - currentBrush.setColor(clr); - p->setBrush(currentBrush); -#endif + case RGBA: + context->setFillColor(Color(m_red, m_green, m_blue, m_alpha)); break; - } case CMYKA: { // FIXME: Do this through platform-independent GraphicsContext API. + // We'll need a fancier Color abstraction to support CYMKA correctly #if PLATFORM(CG) CGContextSetCMYKFillColor(context->platformContext(), m_cyan, m_magenta, m_yellow, m_black, m_alpha); #elif PLATFORM(QT) - QBrush currentBrush = p->brush(); + QBrush currentBrush = context->platformContext()->brush(); QColor clr; clr.setCmykF(m_cyan, m_magenta, m_yellow, m_black, m_alpha); currentBrush.setColor(clr); - p->setBrush(currentBrush); + context->platformContext()->setBrush(currentBrush); +#elif PLATFORM(SGL) + context->setCMYKAFillColor(m_cyan, m_magenta, m_yellow, m_black, m_alpha); #endif break; } case Gradient: + context->setFillGradient(canvasGradient()->gradient()); + break; case ImagePattern: + context->setFillPattern(canvasPattern()->pattern()); break; } } -#endif } diff --git a/WebCore/html/CanvasStyle.h b/WebCore/html/CanvasStyle.h index b98e79a..fe01bd1 100644 --- a/WebCore/html/CanvasStyle.h +++ b/WebCore/html/CanvasStyle.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,6 +36,23 @@ namespace WebCore { class CanvasStyle : public RefCounted<CanvasStyle> { public: + static PassRefPtr<CanvasStyle> create(const String& color) { return adoptRef(new CanvasStyle(color)); } + static PassRefPtr<CanvasStyle> create(float grayLevel) { return adoptRef(new CanvasStyle(grayLevel)); } + static PassRefPtr<CanvasStyle> create(const String& color, float alpha) { return adoptRef(new CanvasStyle(color, alpha)); } + static PassRefPtr<CanvasStyle> create(float grayLevel, float alpha) { return adoptRef(new CanvasStyle(grayLevel, alpha)); } + static PassRefPtr<CanvasStyle> create(float r, float g, float b, float a) { return adoptRef(new CanvasStyle(r, g, b, a)); } + static PassRefPtr<CanvasStyle> create(float c, float m, float y, float k, float a) { return adoptRef(new CanvasStyle(c, m, y, k, a)); } + static PassRefPtr<CanvasStyle> create(PassRefPtr<CanvasGradient> gradient) { return adoptRef(new CanvasStyle(gradient)); } + static PassRefPtr<CanvasStyle> create(PassRefPtr<CanvasPattern> pattern) { return adoptRef(new CanvasStyle(pattern)); } + + String color() const { return m_color; } + CanvasGradient* canvasGradient() const { return m_gradient.get(); } + CanvasPattern* canvasPattern() const { return m_pattern.get(); } + + void applyFillColor(GraphicsContext*); + void applyStrokeColor(GraphicsContext*); + + private: CanvasStyle(const String& color); CanvasStyle(float grayLevel); CanvasStyle(const String& color, float alpha); @@ -45,17 +62,6 @@ namespace WebCore { CanvasStyle(PassRefPtr<CanvasGradient>); CanvasStyle(PassRefPtr<CanvasPattern>); - String color() const { return m_color; } - CanvasGradient* gradient() const { return m_gradient.get(); } - CanvasPattern* pattern() const { return m_pattern.get(); } - - // These do nothing for gradients or patterns. -#if !PLATFORM(CAIRO) - void applyFillColor(GraphicsContext*); -#endif - void applyStrokeColor(GraphicsContext*); - - private: enum Type { ColorString, ColorStringWithAlpha, GrayLevel, RGBA, CMYKA, Gradient, ImagePattern }; Type m_type; diff --git a/WebCore/html/File.cpp b/WebCore/html/File.cpp new file mode 100644 index 0000000..dbbbfa6 --- /dev/null +++ b/WebCore/html/File.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "File.h" + +#include "FileSystem.h" +#include "PlatformString.h" + +namespace WebCore { + +File::File(const String& path) + : m_path(path) + , m_fileName(pathGetFileName(path)) +{ +} + +unsigned long long File::fileSize() +{ + // FIXME: Should we cache this? + // FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to + // come up with an exception to throw if file size is not represetable. + long long size; + if (!getFileSize(m_path, size)) + return 0; + return size; +} + +} // namespace WebCore diff --git a/WebCore/html/File.h b/WebCore/html/File.h new file mode 100644 index 0000000..7d79aa5 --- /dev/null +++ b/WebCore/html/File.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef File_h +#define File_h + +#include "PlatformString.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + + class File : public RefCounted<File> { + public: + static PassRefPtr<File> create(const String& path) + { + return adoptRef(new File(path)); + } + + const String& fileName() const { return m_fileName; } + unsigned long long fileSize(); + + const String& path() const { return m_path; } + + private: + File(const String& path); + + String m_path; + String m_fileName; + }; + +} // namespace WebCore + +#endif // FileList_h diff --git a/WebCore/html/File.idl b/WebCore/html/File.idl new file mode 100644 index 0000000..ada9f0c --- /dev/null +++ b/WebCore/html/File.idl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module html { + + interface [ + GenerateConstructor + ] File { + readonly attribute DOMString fileName; + readonly attribute unsigned long long fileSize; + }; + +} diff --git a/WebCore/html/FileList.cpp b/WebCore/html/FileList.cpp new file mode 100644 index 0000000..ba81087 --- /dev/null +++ b/WebCore/html/FileList.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FileList.h" + +#include "File.h" + +namespace WebCore { + +FileList::FileList() +{ +} + +File* FileList::item(unsigned index) const +{ + if (index >= m_files.size()) + return 0; + return m_files[index].get(); +} + +} // namespace WebCore diff --git a/WebCore/html/FileList.h b/WebCore/html/FileList.h new file mode 100644 index 0000000..e078191 --- /dev/null +++ b/WebCore/html/FileList.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FileList_h +#define FileList_h + +#include "File.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> + +namespace WebCore { + + class FileList : public RefCounted<FileList> { + public: + static PassRefPtr<FileList> create() + { + return adoptRef(new FileList); + } + + unsigned length() const { return m_files.size(); } + File* item(unsigned index) const; + + bool isEmpty() const { return m_files.isEmpty(); } + void clear() { m_files.clear(); } + void append(PassRefPtr<File> file) { m_files.append(file); } + + private: + FileList(); + + Vector<RefPtr<File> > m_files; + }; + +} // namespace WebCore + +#endif // FileList_h diff --git a/WebCore/html/FileList.idl b/WebCore/html/FileList.idl new file mode 100644 index 0000000..01c286e --- /dev/null +++ b/WebCore/html/FileList.idl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module html { + + interface [ + GenerateConstructor, + HasIndexGetter + ] FileList { + readonly attribute unsigned long length; + File item(in [IsIndex] unsigned long index); + }; + +} diff --git a/WebCore/html/FormDataList.cpp b/WebCore/html/FormDataList.cpp index 8698666..281c9fe 100644 --- a/WebCore/html/FormDataList.cpp +++ b/WebCore/html/FormDataList.cpp @@ -1,11 +1,5 @@ /* - * This file is part of the DOM implementation for KDE. - * - * 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 Apple Computer, Inc. - * (C) 2006 Alexey Proskuryakov (ap@nypop.com) + * Copyright (C) 2005, 2006, 2008 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 @@ -40,11 +34,11 @@ void FormDataList::appendString(const CString& s) } // Change plain CR and plain LF to CRLF pairs. -static CString fixLineBreaks(const CString &s) +static CString fixLineBreaks(const CString& s) { // Compute the length. unsigned newLen = 0; - const char *p = s.data(); + const char* p = s.data(); while (char c = *p++) { if (c == '\r') { // Safe to look ahead because of trailing '\0'. @@ -66,7 +60,7 @@ static CString fixLineBreaks(const CString &s) // Make a copy of the string. p = s.data(); - char *q; + char* q; CString result = CString::newUninitialized(newLen, q); while (char c = *p++) { if (c == '\r') { @@ -90,14 +84,8 @@ static CString fixLineBreaks(const CString &s) void FormDataList::appendString(const String& s) { - CString cstr = fixLineBreaks(m_encoding.encode(s.characters(), s.length(), true)); + CString cstr = fixLineBreaks(m_encoding.encode(s.characters(), s.length(), EntitiesForUnencodables)); m_list.append(cstr); } -void FormDataList::appendFile(const String& key, const String& filename) -{ - appendString(key); - m_list.append(filename); -} - } // namespace diff --git a/WebCore/html/FormDataList.h b/WebCore/html/FormDataList.h index cdff8f7..aec1a52 100644 --- a/WebCore/html/FormDataList.h +++ b/WebCore/html/FormDataList.h @@ -1,11 +1,5 @@ /* - * This file is part of the DOM implementation for KDE. - * - * 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 Apple Computer, Inc. - * (C) 2006 Alexey Proskuryakov (ap@nypop.com) + * Copyright (C) 2005, 2006, 2008 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 @@ -28,21 +22,11 @@ #define FormDataList_h #include "CString.h" -#include "PlatformString.h" +#include "File.h" #include "TextEncoding.h" -#include <wtf/Vector.h> namespace WebCore { -struct FormDataListItem { - FormDataListItem() { } - FormDataListItem(const CString& data) : m_data(data) { } - FormDataListItem(const String& path) : m_path(path) { } - - String m_path; - CString m_data; -}; - class FormDataList { public: FormDataList(const TextEncoding&); @@ -53,16 +37,31 @@ public: { appendString(key); appendString(value); } void appendData(const String& key, int value) { appendString(key); appendString(String::number(value)); } - void appendFile(const String& key, const String& filename); + void appendFile(const String& key, PassRefPtr<File> file) + { appendString(key); m_list.append(file); } + + class Item { + public: + Item() { } + Item(const CString& data) : m_data(data) { } + Item(PassRefPtr<File> file) : m_file(file) { } + + const CString& data() const { return m_data; } + File* file() const { return m_file.get(); } + + private: + CString m_data; + RefPtr<File> m_file; + }; - const Vector<FormDataListItem>& list() const { return m_list; } + const Vector<Item>& list() const { return m_list; } private: void appendString(const CString&); void appendString(const String&); TextEncoding m_encoding; - Vector<FormDataListItem> m_list; + Vector<Item> m_list; }; } // namespace WebCore diff --git a/WebCore/html/HTMLAnchorElement.cpp b/WebCore/html/HTMLAnchorElement.cpp index 5daf2a0..0e09b5d 100644 --- a/WebCore/html/HTMLAnchorElement.cpp +++ b/WebCore/html/HTMLAnchorElement.cpp @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Simon Hausmann <hausmann@kde.org> - * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. * (C) 2006 Graham Dennis (graham.dennis@gmail.com) * * This library is free software; you can redistribute it and/or @@ -25,12 +25,14 @@ #include "HTMLAnchorElement.h" #include "CSSHelper.h" +#include "DNS.h" #include "Document.h" #include "Event.h" #include "EventHandler.h" #include "EventNames.h" #include "Frame.h" #include "FrameLoader.h" +#include "FrameLoaderClient.h" #include "HTMLImageElement.h" #include "HTMLNames.h" #include "KeyboardEvent.h" @@ -46,7 +48,6 @@ namespace WebCore { using namespace HTMLNames; -using namespace EventNames; HTMLAnchorElement::HTMLAnchorElement(Document* doc) : HTMLElement(aTag, doc) @@ -70,7 +71,7 @@ bool HTMLAnchorElement::supportsFocus() const { if (isContentEditable()) return HTMLElement::supportsFocus(); - return isFocusable() || (m_isLink && document() && !document()->haveStylesheetsLoaded()); + return isFocusable() || (isLink() && document() && !document()->haveStylesheetsLoaded()); } bool HTMLAnchorElement::isFocusable() const @@ -80,7 +81,30 @@ bool HTMLAnchorElement::isFocusable() const // FIXME: Even if we are not visible, we might have a child that is visible. // Dave wants to fix that some day with a "has visible content" flag or the like. - if (!(m_isLink && renderer() && renderer()->style()->visibility() == VISIBLE)) + if (!(isLink() && renderer() && renderer()->style()->visibility() == VISIBLE)) + return false; + + return true; +} + +bool HTMLAnchorElement::isMouseFocusable() const +{ +#if PLATFORM(GTK) + return HTMLElement::isMouseFocusable(); +#else + return false; +#endif +} + +bool HTMLAnchorElement::isKeyboardFocusable(KeyboardEvent* event) const +{ + if (!isFocusable()) + return false; + + if (!document()->frame()) + return false; + + if (!document()->frame()->eventHandler()->tabsToLinks(event)) return false; // Before calling absoluteRects, check for the common case where the renderer @@ -102,34 +126,18 @@ bool HTMLAnchorElement::isFocusable() const return false; } -bool HTMLAnchorElement::isMouseFocusable() const -{ - return false; -} - -bool HTMLAnchorElement::isKeyboardFocusable(KeyboardEvent* event) const -{ - if (!isFocusable()) - return false; - - if (!document()->frame()) - return false; - - return document()->frame()->eventHandler()->tabsToLinks(event); -} - void HTMLAnchorElement::defaultEventHandler(Event* evt) { // React on clicks and on keypresses. // Don't make this KEYUP_EVENT again, it makes khtml follow links it shouldn't, // when pressing Enter in the combo. - if (m_isLink && (evt->type() == clickEvent || (evt->type() == keydownEvent && m_focused))) { + if (isLink() && (evt->type() == eventNames().clickEvent || (evt->type() == eventNames().keydownEvent && focused()))) { MouseEvent* e = 0; - if (evt->type() == clickEvent && evt->isMouseEvent()) + if (evt->type() == eventNames().clickEvent && evt->isMouseEvent()) e = static_cast<MouseEvent*>(evt); KeyboardEvent* k = 0; - if (evt->type() == keydownEvent && evt->isKeyboardEvent()) + if (evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent()) k = static_cast<KeyboardEvent*>(evt); if (e && e->button() == RightButton) { @@ -197,9 +205,9 @@ void HTMLAnchorElement::defaultEventHandler(Event* evt) int x = e->pageX() - absx; int y = e->pageY() - absy; url += "?"; - url += DeprecatedString::number(x); + url += String::number(x); url += ","; - url += DeprecatedString::number(y); + url += String::number(y); } else { evt->setDefaultHandled(); HTMLElement::defaultEventHandler(evt); @@ -212,17 +220,17 @@ void HTMLAnchorElement::defaultEventHandler(Event* evt) document()->frame()->loader()->urlSelected(document()->completeURL(url), getAttribute(targetAttr), evt, false, true); evt->setDefaultHandled(); - } else if (m_isLink && isContentEditable()) { - // This keeps track of the editable block that the selection was in (if it was in one) just before the link was clicked - // for the LiveWhenNotFocused editable link behavior - if (evt->type() == mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() != RightButton && document()->frame() && document()->frame()->selectionController()) { + } else if (isLink() && isContentEditable()) { + // This keeps track of the editable block that the selection was in (if it was in one) just before the link was clicked + // for the LiveWhenNotFocused editable link behavior + if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() != RightButton && document()->frame() && document()->frame()->selection()) { MouseEvent* e = static_cast<MouseEvent*>(evt); - m_rootEditableElementForSelectionOnMouseDown = document()->frame()->selectionController()->rootEditableElement(); + m_rootEditableElementForSelectionOnMouseDown = document()->frame()->selection()->rootEditableElement(); m_wasShiftKeyDownOnMouseDown = e && e->shiftKey(); - } else if (evt->type() == mouseoverEvent) { - // These are cleared on mouseover and not mouseout because their values are needed for drag events, but these happen - // after mouse out events. + } else if (evt->type() == eventNames().mouseoverEvent) { + // These are cleared on mouseover and not mouseout because their values are needed for drag events, but these happen + // after mouse out events. m_rootEditableElementForSelectionOnMouseDown = 0; m_wasShiftKeyDownOnMouseDown = false; } @@ -250,8 +258,8 @@ void HTMLAnchorElement::setActive(bool down, bool pause) // Don't set the link to be active if the current selection is in the same editable block as // this link case EditableLinkLiveWhenNotFocused: - if (down && document()->frame() && document()->frame()->selectionController() && - document()->frame()->selectionController()->rootEditableElement() == rootEditableElement()) + if (down && document()->frame() && document()->frame()->selection() && + document()->frame()->selection()->rootEditableElement() == rootEditableElement()) return; break; @@ -267,10 +275,15 @@ void HTMLAnchorElement::setActive(bool down, bool pause) void HTMLAnchorElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == hrefAttr) { - bool wasLink = m_isLink; - m_isLink = !attr->isNull(); - if (wasLink != m_isLink) + bool wasLink = isLink(); + setIsLink(!attr->isNull()); + if (wasLink != isLink()) setChanged(); + if (isLink() && document()->isDNSPrefetchEnabled()) { + String value = attr->value(); + if (protocolIs(value, "http") || protocolIs(value, "https") || value.startsWith("//")) + prefetchDNS(document()->completeURL(value).host()); + } } else if (attr->name() == nameAttr || attr->name() == titleAttr || attr->name() == relAttr) { @@ -328,7 +341,7 @@ void HTMLAnchorElement::setCoords(const String &value) setAttribute(coordsAttr, value); } -String HTMLAnchorElement::href() const +KURL HTMLAnchorElement::href() const { return document()->completeURL(getAttribute(hrefAttr)); } @@ -388,9 +401,10 @@ void HTMLAnchorElement::setShape(const String &value) setAttribute(shapeAttr, value); } -void HTMLAnchorElement::setTabIndex(int tabIndex) +short HTMLAnchorElement::tabIndex() const { - setAttribute(tabindexAttr, String::number(tabIndex)); + // Skip the supportsFocus check in HTMLElement. + return Element::tabIndex(); } String HTMLAnchorElement::target() const @@ -415,41 +429,40 @@ void HTMLAnchorElement::setType(const String &value) String HTMLAnchorElement::hash() const { - return '#' + KURL(href().deprecatedString()).ref(); + return "#" + href().ref(); } String HTMLAnchorElement::host() const { - return KURL(href().deprecatedString()).host(); + return href().host(); } String HTMLAnchorElement::hostname() const { - KURL url(href().deprecatedString()); - if (url.port()==0) + const KURL& url = href(); + if (url.port() == 0) return url.host(); - else - return url.host() + ":" + String::number(url.port()); + return url.host() + ":" + String::number(url.port()); } String HTMLAnchorElement::pathname() const { - return KURL(href().deprecatedString()).path(); + return href().path(); } String HTMLAnchorElement::port() const { - return DeprecatedString::number(KURL(href().deprecatedString()).port()); + return String::number(href().port()); } String HTMLAnchorElement::protocol() const { - return KURL(href().deprecatedString()).protocol() + ":"; + return href().protocol() + ":"; } String HTMLAnchorElement::search() const { - return KURL(href().deprecatedString()).query(); + return href().query(); } String HTMLAnchorElement::text() const @@ -459,12 +472,12 @@ String HTMLAnchorElement::text() const String HTMLAnchorElement::toString() const { - return href(); + return href().string(); } bool HTMLAnchorElement::isLiveLink() const { - if (!m_isLink) + if (!isLink()) return false; if (!isContentEditable()) return true; diff --git a/WebCore/html/HTMLAnchorElement.h b/WebCore/html/HTMLAnchorElement.h index 98e37e0..2457acb 100644 --- a/WebCore/html/HTMLAnchorElement.h +++ b/WebCore/html/HTMLAnchorElement.h @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Simon Hausmann <hausmann@kde.org> - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008 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 @@ -28,8 +28,6 @@ namespace WebCore { -class String; - class HTMLAnchorElement : public HTMLElement { public: HTMLAnchorElement(Document*); @@ -60,7 +58,7 @@ public: String coords() const; void setCoords(const String&); - String href() const; + KURL href() const; void setHref(const String&); String hreflang() const; @@ -78,7 +76,7 @@ public: String shape() const; void setShape(const String&); - void setTabIndex(int); + virtual short tabIndex() const; virtual String target() const; void setTarget(const String&); diff --git a/WebCore/html/HTMLAnchorElement.idl b/WebCore/html/HTMLAnchorElement.idl index c7789ab..f3a15ee 100644 --- a/WebCore/html/HTMLAnchorElement.idl +++ b/WebCore/html/HTMLAnchorElement.idl @@ -34,13 +34,9 @@ module html { attribute [ConvertNullToNullString] DOMString rel; attribute [ConvertNullToNullString] DOMString rev; attribute [ConvertNullToNullString] DOMString shape; - attribute long tabIndex; attribute [ConvertNullToNullString] DOMString target; attribute [ConvertNullToNullString] DOMString type; - void blur(); - void focus(); - // IE Extensions readonly attribute DOMString hash; readonly attribute DOMString host; diff --git a/WebCore/html/HTMLAppletElement.cpp b/WebCore/html/HTMLAppletElement.cpp index d5100d1..d637ce0 100644 --- a/WebCore/html/HTMLAppletElement.cpp +++ b/WebCore/html/HTMLAppletElement.cpp @@ -1,11 +1,9 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Stefan Schimanski (1Stein@gmx.de) - * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. - * Copyright (C) 2007 Trolltech ASA + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,6 +20,7 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "HTMLAppletElement.h" @@ -31,13 +30,14 @@ #include "RenderApplet.h" #include "RenderInline.h" #include "Settings.h" +#include "ScriptController.h" namespace WebCore { using namespace HTMLNames; -HTMLAppletElement::HTMLAppletElement(Document *doc) -: HTMLPlugInElement(appletTag, doc) +HTMLAppletElement::HTMLAppletElement(Document* doc) + : HTMLPlugInElement(appletTag, doc) { } @@ -45,21 +45,16 @@ HTMLAppletElement::~HTMLAppletElement() { #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure the m_name and m_id are removed from HTMLDocument's NameCountMap if (oldNameIdCount && document()->isHTMLDocument()) { HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - doc->removeNamedItem(oldNameAttr); - doc->removeDocExtraNamedItem(oldIdAttr); + doc->removeNamedItem(m_name); + doc->removeExtraNamedItem(m_id); } #endif - -#if USE(JAVASCRIPTCORE_BINDINGS) - // m_instance should have been cleaned up in detach(). - ASSERT(!m_instance); -#endif } -void HTMLAppletElement::parseMappedAttribute(MappedAttribute *attr) +void HTMLAppletElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == altAttr || attr->name() == archiveAttr || @@ -69,21 +64,21 @@ void HTMLAppletElement::parseMappedAttribute(MappedAttribute *attr) attr->name() == objectAttr) { // Do nothing. } else if (attr->name() == nameAttr) { - String newNameAttr = attr->value(); + const AtomicString& newName = attr->value(); if (inDocument() && document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->removeNamedItem(oldNameAttr); - doc->addNamedItem(newNameAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeNamedItem(m_name); + document->addNamedItem(newName); } - oldNameAttr = newNameAttr; + m_name = newName; } else if (attr->name() == idAttr) { - String newIdAttr = attr->value(); + const AtomicString& newId = attr->value(); if (inDocument() && document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->removeDocExtraNamedItem(oldIdAttr); - doc->addDocExtraNamedItem(newIdAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeExtraNamedItem(m_id); + document->addExtraNamedItem(newId); } - oldIdAttr = newIdAttr; + m_id = newId; // also call superclass HTMLPlugInElement::parseMappedAttribute(attr); } else @@ -93,12 +88,12 @@ void HTMLAppletElement::parseMappedAttribute(MappedAttribute *attr) void HTMLAppletElement::insertedIntoDocument() { if (document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->addNamedItem(oldNameAttr); - doc->addDocExtraNamedItem(oldIdAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->addNamedItem(m_name); + document->addExtraNamedItem(m_id); #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure the m_name and m_id are removed from HTMLDocument's NameCountMap oldNameIdCount++; #endif } @@ -109,12 +104,12 @@ void HTMLAppletElement::insertedIntoDocument() void HTMLAppletElement::removedFromDocument() { if (document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->removeNamedItem(oldNameAttr); - doc->removeDocExtraNamedItem(oldIdAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeNamedItem(m_name); + document->removeExtraNamedItem(m_id); #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure the m_name and m_id are removed from HTMLDocument's NameCountMap oldNameIdCount--; #endif } @@ -122,12 +117,12 @@ void HTMLAppletElement::removedFromDocument() HTMLPlugInElement::removedFromDocument(); } -bool HTMLAppletElement::rendererIsNeeded(RenderStyle *style) +bool HTMLAppletElement::rendererIsNeeded(RenderStyle* style) { return !getAttribute(codeAttr).isNull(); } -RenderObject *HTMLAppletElement::createRenderer(RenderArena *arena, RenderStyle *style) +RenderObject* HTMLAppletElement::createRenderer(RenderArena* arena, RenderStyle* style) { Settings* settings = document()->settings(); @@ -138,14 +133,14 @@ RenderObject *HTMLAppletElement::createRenderer(RenderArena *arena, RenderStyle const AtomicString& codeBase = getAttribute(codebaseAttr); if(!codeBase.isNull()) args.set("codeBase", codeBase); - const AtomicString& name = getAttribute(document()->htmlMode() != Document::XHtml ? nameAttr : idAttr); + const AtomicString& name = getAttribute(document()->isHTMLDocument() ? nameAttr : idAttr); if (!name.isNull()) args.set("name", name); const AtomicString& archive = getAttribute(archiveAttr); if (!archive.isNull()) args.set("archive", archive); - args.set("baseURL", document()->baseURL()); + args.set("baseURL", document()->baseURL().string()); const AtomicString& mayScript = getAttribute(mayscriptAttr); if (!mayScript.isNull()) @@ -159,24 +154,18 @@ RenderObject *HTMLAppletElement::createRenderer(RenderArena *arena, RenderStyle return RenderObject::createObject(this, style); } -#if USE(JAVASCRIPTCORE_BINDINGS) -KJS::Bindings::Instance *HTMLAppletElement::getInstance() const +RenderWidget* HTMLAppletElement::renderWidgetForJSBindings() const { Settings* settings = document()->settings(); if (!settings || !settings->isJavaEnabled()) return 0; - if (m_instance) - return m_instance.get(); - - if (RenderApplet* r = static_cast<RenderApplet*>(renderer())) { - r->createWidgetIfNecessary(); - if (r->widget() && document()->frame()) - m_instance = document()->frame()->createScriptInstanceForWidget(r->widget()); - } - return m_instance.get(); + RenderApplet* applet = static_cast<RenderApplet*>(renderer()); + if (applet) + applet->createWidgetIfNecessary(); + + return applet; } -#endif void HTMLAppletElement::finishParsingChildren() { @@ -186,14 +175,6 @@ void HTMLAppletElement::finishParsingChildren() renderer()->setNeedsLayout(true); // This will cause it to create its widget & the Java applet } -void HTMLAppletElement::detach() -{ -#if USE(JAVASCRIPTCORE_BINDINGS) - m_instance = 0; -#endif - HTMLPlugInElement::detach(); -} - String HTMLAppletElement::alt() const { return getAttribute(altAttr); diff --git a/WebCore/html/HTMLAppletElement.h b/WebCore/html/HTMLAppletElement.h index 5025277..6c23170 100644 --- a/WebCore/html/HTMLAppletElement.h +++ b/WebCore/html/HTMLAppletElement.h @@ -1,9 +1,7 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2006 Apple Computer, Inc. + * Copyright (C) 2004, 2006, 2008 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,12 +25,6 @@ #include "HTMLPlugInElement.h" -#if USE(JAVASCRIPTCORE_BINDINGS) -#include <bindings/runtime.h> -#else -namespace KJS { namespace Bindings { class Instance; } } -#endif - namespace WebCore { class HTMLFormElement; @@ -51,11 +43,8 @@ public: virtual bool rendererIsNeeded(RenderStyle*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); virtual void finishParsingChildren(); - virtual void detach(); -#if USE(JAVASCRIPTCORE_BINDINGS) - virtual KJS::Bindings::Instance* getInstance() const; -#endif + virtual RenderWidget* renderWidgetForJSBindings() const; String alt() const; void setAlt(const String&); @@ -84,7 +73,7 @@ public: virtual void removedFromDocument(); private: - String oldIdAttr; + AtomicString m_id; }; } diff --git a/WebCore/html/HTMLAreaElement.cpp b/WebCore/html/HTMLAreaElement.cpp index 09e1e30..7c6d65f 100644 --- a/WebCore/html/HTMLAreaElement.cpp +++ b/WebCore/html/HTMLAreaElement.cpp @@ -1,6 +1,4 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. @@ -20,13 +18,15 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "HTMLAreaElement.h" #include "Document.h" -#include "HTMLNames.h" #include "FloatRect.h" +#include "HTMLNames.h" #include "HitTestResult.h" +#include "Length.h" #include "RenderObject.h" #ifdef ANDROID_NAVIGATE_AREAMAPS @@ -69,7 +69,7 @@ void HTMLAreaElement::parseMappedAttribute(MappedAttribute *attr) m_shape = Rect; } else if (attr->name() == coordsAttr) { delete [] m_coords; - m_coords = attr->value().toCoordsArray(m_coordsLen); + m_coords = newCoordsArray(attr->value().string(), m_coordsLen); } else if (attr->name() == altAttr || attr->name() == accesskeyAttr) { // Do nothing. } else @@ -186,7 +186,7 @@ void HTMLAreaElement::setCoords(const String& value) setAttribute(coordsAttr, value); } -String HTMLAreaElement::href() const +KURL HTMLAreaElement::href() const { return document()->completeURL(getAttribute(hrefAttr)); } @@ -216,9 +216,9 @@ void HTMLAreaElement::setShape(const String& value) setAttribute(shapeAttr, value); } -void HTMLAreaElement::setTabIndex(int tabIndex) +bool HTMLAreaElement::isFocusable() const { - setAttribute(tabindexAttr, String::number(tabIndex)); + return HTMLElement::isFocusable(); } String HTMLAreaElement::target() const diff --git a/WebCore/html/HTMLAreaElement.h b/WebCore/html/HTMLAreaElement.h index 98e10f5..2cce901 100644 --- a/WebCore/html/HTMLAreaElement.h +++ b/WebCore/html/HTMLAreaElement.h @@ -1,9 +1,7 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004 Apple Computer, Inc. + * Copyright (C) 2004, 2008 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 @@ -43,8 +41,6 @@ class HitTestResult; class HTMLAreaElement : public HTMLAnchorElement { public: - enum Shape { Default, Poly, Rect, Circle, Unknown }; - HTMLAreaElement(Document*); ~HTMLAreaElement(); @@ -68,7 +64,7 @@ public: String coords() const; void setCoords(const String&); - String href() const; + KURL href() const; void setHref(const String&); bool noHref() const; @@ -77,7 +73,7 @@ public: String shape() const; void setShape(const String&); - void setTabIndex(int); + virtual bool isFocusable() const; virtual String target() const; void setTarget(const String&); @@ -87,7 +83,8 @@ public: void setMap(RenderImage* map) { m_map = map; } #endif -protected: +private: + enum Shape { Default, Poly, Rect, Circle, Unknown }; Path getRegion(const IntSize&) const; Path region; Length* m_coords; diff --git a/WebCore/html/HTMLAreaElement.idl b/WebCore/html/HTMLAreaElement.idl index 7effb98..39cc719 100644 --- a/WebCore/html/HTMLAreaElement.idl +++ b/WebCore/html/HTMLAreaElement.idl @@ -31,7 +31,6 @@ module html { attribute [ConvertNullToNullString] DOMString href; attribute boolean noHref; attribute [ConvertNullToNullString] DOMString shape; - attribute long tabIndex; attribute [ConvertNullToNullString] DOMString target; // IE Extensions diff --git a/WebCore/html/HTMLAttributeNames.in b/WebCore/html/HTMLAttributeNames.in index a949640..3b70aee 100644 --- a/WebCore/html/HTMLAttributeNames.in +++ b/WebCore/html/HTMLAttributeNames.in @@ -1,3 +1,8 @@ +namespace="HTML" +namespacePrefix="xhtml" +namespaceURI="http://www.w3.org/1999/xhtml" +attrsNullNamespace="1" + abbr accept_charset accept @@ -7,7 +12,18 @@ align alink alt archive +aria-activedescendant +aria-checked +aria-describedby +aria-labeledby +aria-labelledby +aria-level +aria-pressed +aria-valuemax +aria-valuemin +aria-valuenow autocomplete +autofocus autoplay autosave axis @@ -26,7 +42,7 @@ charset checked cellborder cite -class +class exportString="1" classid clear code @@ -77,6 +93,7 @@ playcount loopend loopstart lowsrc +manifest marginheight marginwidth max @@ -131,8 +148,19 @@ onscroll onsearch onselect onselectstart +onstorage onsubmit +/* #if ENABLE(TOUCH_EVENTS) // Android */ +ontouchstart +ontouchmove +ontouchend +ontouchcancel +/* #endif */ onunload +onwebkitanimationstart +onwebkitanimationiteration +onwebkitanimationend +onwebkittransitionend pagex pagey placeholder @@ -148,6 +176,7 @@ readonly rel results rev +role rows rowspan rules diff --git a/WebCore/html/HTMLBRElement.cpp b/WebCore/html/HTMLBRElement.cpp index 44bdf59..75ee30c 100644 --- a/WebCore/html/HTMLBRElement.cpp +++ b/WebCore/html/HTMLBRElement.cpp @@ -58,9 +58,9 @@ void HTMLBRElement::parseMappedAttribute(MappedAttribute *attr) const AtomicString& str = attr->value(); if (!str.isEmpty()) { if (equalIgnoringCase(str, "all")) - addCSSProperty(attr, CSS_PROP_CLEAR, "both"); + addCSSProperty(attr, CSSPropertyClear, "both"); else - addCSSProperty(attr, CSS_PROP_CLEAR, str); + addCSSProperty(attr, CSSPropertyClear, str); } } else HTMLElement::parseMappedAttribute(attr); diff --git a/WebCore/html/HTMLBaseElement.cpp b/WebCore/html/HTMLBaseElement.cpp index 7a94c7b..4de62f9 100644 --- a/WebCore/html/HTMLBaseElement.cpp +++ b/WebCore/html/HTMLBaseElement.cpp @@ -1,10 +1,8 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003 Apple Computer, Inc. + * Copyright (C) 2003, 2008 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 @@ -36,7 +34,7 @@ namespace WebCore { using namespace HTMLNames; -HTMLBaseElement::HTMLBaseElement(Document *doc) +HTMLBaseElement::HTMLBaseElement(Document* doc) : HTMLElement(baseTag, doc) { } @@ -45,7 +43,7 @@ HTMLBaseElement::~HTMLBaseElement() { } -void HTMLBaseElement::parseMappedAttribute(MappedAttribute *attr) +void HTMLBaseElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == hrefAttr) { m_href = parseURL(attr->value()); @@ -69,8 +67,8 @@ void HTMLBaseElement::removedFromDocument() // Since the document doesn't have a base element... // (This will break in the case of multiple base elements, but that's not valid anyway (?)) - document()->setBaseURL(DeprecatedString::null); - document()->setBaseTarget(DeprecatedString::null); + document()->setBaseElementURL(KURL()); + document()->setBaseElementTarget(String()); } void HTMLBaseElement::process() @@ -78,11 +76,11 @@ void HTMLBaseElement::process() if (!inDocument()) return; - if (!m_href.isEmpty() && document()->frame()) - document()->setBaseURL(KURL(document()->frame()->loader()->url(), m_href.deprecatedString()).deprecatedString()); + if (!m_href.isEmpty()) + document()->setBaseElementURL(KURL(document()->url(), m_href)); if (!m_target.isEmpty()) - document()->setBaseTarget(m_target); + document()->setBaseElementTarget(m_target); // ### should changing a document's base URL dynamically automatically update all images, stylesheets etc? } diff --git a/WebCore/html/HTMLBodyElement.cpp b/WebCore/html/HTMLBodyElement.cpp index 6231fc2..7dca064 100644 --- a/WebCore/html/HTMLBodyElement.cpp +++ b/WebCore/html/HTMLBodyElement.cpp @@ -1,9 +1,9 @@ -/** +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Simon Hausmann (hausmann@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2006, 2007, 2008 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 @@ -38,7 +38,6 @@ namespace WebCore { -using namespace EventNames; using namespace HTMLNames; HTMLBodyElement::HTMLBodyElement(Document* doc) @@ -56,7 +55,7 @@ HTMLBodyElement::~HTMLBodyElement() void HTMLBodyElement::createLinkDecl() { - m_linkDecl = new CSSMutableStyleDeclaration; + m_linkDecl = CSSMutableStyleDeclaration::create(); m_linkDecl->setParent(document()->elementSheet()); m_linkDecl->setNode(this); m_linkDecl->setStrictParsing(!document()->inCompatMode()); @@ -88,20 +87,20 @@ void HTMLBodyElement::parseMappedAttribute(MappedAttribute *attr) if (attr->name() == backgroundAttr) { String url = parseURL(attr->value()); if (!url.isEmpty()) - addCSSImageProperty(attr, CSS_PROP_BACKGROUND_IMAGE, document()->completeURL(url)); + addCSSImageProperty(attr, CSSPropertyBackgroundImage, document()->completeURL(url).string()); } else if (attr->name() == marginwidthAttr || attr->name() == leftmarginAttr) { - addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value()); + addCSSLength(attr, CSSPropertyMarginRight, attr->value()); + addCSSLength(attr, CSSPropertyMarginLeft, attr->value()); } else if (attr->name() == marginheightAttr || attr->name() == topmarginAttr) { - addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value()); + addCSSLength(attr, CSSPropertyMarginBottom, attr->value()); + addCSSLength(attr, CSSPropertyMarginTop, attr->value()); } else if (attr->name() == bgcolorAttr) { - addCSSColor(attr, CSS_PROP_BACKGROUND_COLOR, attr->value()); + addCSSColor(attr, CSSPropertyBackgroundColor, attr->value()); } else if (attr->name() == textAttr) { - addCSSColor(attr, CSS_PROP_COLOR, attr->value()); + addCSSColor(attr, CSSPropertyColor, attr->value()); } else if (attr->name() == bgpropertiesAttr) { if (equalIgnoringCase(attr->value(), "fixed")) - addCSSProperty(attr, CSS_PROP_BACKGROUND_ATTACHMENT, CSS_VAL_FIXED); + addCSSProperty(attr, CSSPropertyBackgroundAttachment, CSSValueFixed); } else if (attr->name() == vlinkAttr || attr->name() == alinkAttr || attr->name() == linkAttr) { @@ -115,8 +114,8 @@ void HTMLBodyElement::parseMappedAttribute(MappedAttribute *attr) } else { if (!m_linkDecl) createLinkDecl(); - m_linkDecl->setProperty(CSS_PROP_COLOR, attr->value(), false, false); - RefPtr<CSSValue> val = m_linkDecl->getPropertyCSSValue(CSS_PROP_COLOR); + m_linkDecl->setProperty(CSSPropertyColor, attr->value(), false, false); + RefPtr<CSSValue> val = m_linkDecl->getPropertyCSSValue(CSSPropertyColor); if (val && val->isPrimitiveValue()) { Color col = document()->styleSelector()->getColorFromPrimitiveValue(static_cast<CSSPrimitiveValue*>(val.get())); if (attr->name() == linkAttr) @@ -130,20 +129,25 @@ void HTMLBodyElement::parseMappedAttribute(MappedAttribute *attr) if (attached()) document()->recalcStyle(Force); - } else if (attr->name() == onloadAttr) { - document()->setHTMLWindowEventListener(loadEvent, attr); - } else if (attr->name() == onbeforeunloadAttr) { - document()->setHTMLWindowEventListener(beforeunloadEvent, attr); - } else if (attr->name() == onunloadAttr) { - document()->setHTMLWindowEventListener(unloadEvent, attr); - } else if (attr->name() == onblurAttr) { - document()->setHTMLWindowEventListener(blurEvent, attr); - } else if (attr->name() == onfocusAttr) { - document()->setHTMLWindowEventListener(focusEvent, attr); - } else if (attr->name() == onresizeAttr) { - document()->setHTMLWindowEventListener(resizeEvent, attr); - } else if (attr->name() == onscrollAttr) { - document()->setHTMLWindowEventListener(scrollEvent, attr); + } else if (attr->name() == onloadAttr) + document()->setWindowInlineEventListenerForTypeAndAttribute(eventNames().loadEvent, attr); + else if (attr->name() == onbeforeunloadAttr) + document()->setWindowInlineEventListenerForTypeAndAttribute(eventNames().beforeunloadEvent, attr); + else if (attr->name() == onunloadAttr) + document()->setWindowInlineEventListenerForTypeAndAttribute(eventNames().unloadEvent, attr); + else if (attr->name() == onblurAttr) + document()->setWindowInlineEventListenerForTypeAndAttribute(eventNames().blurEvent, attr); + else if (attr->name() == onfocusAttr) + document()->setWindowInlineEventListenerForTypeAndAttribute(eventNames().focusEvent, attr); + else if (attr->name() == onresizeAttr) + document()->setWindowInlineEventListenerForTypeAndAttribute(eventNames().resizeEvent, attr); + else if (attr->name() == onscrollAttr) + document()->setWindowInlineEventListenerForTypeAndAttribute(eventNames().scrollEvent, attr); + else if (attr->name() == onstorageAttr) { + // The HTML5 spec currently specifies that storage events are fired only at the body element of + // an HTMLDocument, which is why the onstorage attribute differs from the ones before it. + // The spec might change on this, and then so should we! + setInlineEventListenerForTypeAndAttribute(eventNames().storageEvent, attr); } else HTMLElement::parseMappedAttribute(attr); } @@ -180,7 +184,7 @@ String HTMLBodyElement::aLink() const return getAttribute(alinkAttr); } -void HTMLBodyElement::setALink(const String &value) +void HTMLBodyElement::setALink(const String& value) { setAttribute(alinkAttr, value); } @@ -190,7 +194,7 @@ String HTMLBodyElement::background() const return getAttribute(backgroundAttr); } -void HTMLBodyElement::setBackground(const String &value) +void HTMLBodyElement::setBackground(const String& value) { setAttribute(backgroundAttr, value); } @@ -200,7 +204,7 @@ String HTMLBodyElement::bgColor() const return getAttribute(bgcolorAttr); } -void HTMLBodyElement::setBgColor(const String &value) +void HTMLBodyElement::setBgColor(const String& value) { setAttribute(bgcolorAttr, value); } @@ -210,7 +214,7 @@ String HTMLBodyElement::link() const return getAttribute(linkAttr); } -void HTMLBodyElement::setLink(const String &value) +void HTMLBodyElement::setLink(const String& value) { setAttribute(linkAttr, value); } @@ -220,7 +224,7 @@ String HTMLBodyElement::text() const return getAttribute(textAttr); } -void HTMLBodyElement::setText(const String &value) +void HTMLBodyElement::setText(const String& value) { setAttribute(textAttr, value); } @@ -230,7 +234,7 @@ String HTMLBodyElement::vLink() const return getAttribute(vlinkAttr); } -void HTMLBodyElement::setVLink(const String &value) +void HTMLBodyElement::setVLink(const String& value) { setAttribute(vlinkAttr, value); } @@ -241,8 +245,7 @@ int HTMLBodyElement::scrollLeft() const Document* doc = document(); doc->updateLayoutIgnorePendingStylesheets(); FrameView* view = doc->view(); - - return view ? view->contentsX() : 0; + return view ? view->scrollX() : 0; } void HTMLBodyElement::setScrollLeft(int scrollLeft) @@ -251,7 +254,7 @@ void HTMLBodyElement::setScrollLeft(int scrollLeft) if (sview) { // Update the document's layout document()->updateLayoutIgnorePendingStylesheets(); - sview->setContentsPos(scrollLeft, sview->contentsY()); + sview->setScrollPosition(IntPoint(scrollLeft, sview->scrollY())); } } @@ -261,8 +264,7 @@ int HTMLBodyElement::scrollTop() const Document* doc = document(); doc->updateLayoutIgnorePendingStylesheets(); FrameView* view = doc->view(); - - return view ? view->contentsY() : 0; + return view ? view->scrollY() : 0; } void HTMLBodyElement::setScrollTop(int scrollTop) @@ -271,7 +273,7 @@ void HTMLBodyElement::setScrollTop(int scrollTop) if (sview) { // Update the document's layout document()->updateLayoutIgnorePendingStylesheets(); - sview->setContentsPos(sview->contentsX(), scrollTop); + sview->setScrollPosition(IntPoint(sview->scrollX(), scrollTop)); } } @@ -281,7 +283,6 @@ int HTMLBodyElement::scrollHeight() const Document* doc = document(); doc->updateLayoutIgnorePendingStylesheets(); FrameView* view = doc->view(); - return view ? view->contentsHeight() : 0; } @@ -291,8 +292,12 @@ int HTMLBodyElement::scrollWidth() const Document* doc = document(); doc->updateLayoutIgnorePendingStylesheets(); FrameView* view = doc->view(); - return view ? view->contentsWidth() : 0; } +void HTMLBodyElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + urls.append(background()); +} + } diff --git a/WebCore/html/HTMLBodyElement.h b/WebCore/html/HTMLBodyElement.h index 6fe5b17..2c5ce98 100644 --- a/WebCore/html/HTMLBodyElement.h +++ b/WebCore/html/HTMLBodyElement.h @@ -70,6 +70,8 @@ public: int scrollHeight() const; int scrollWidth() const; + virtual void getSubresourceAttributeStrings(Vector<String>&) const; + protected: RefPtr<CSSMutableStyleDeclaration> m_linkDecl; }; diff --git a/WebCore/html/HTMLButtonElement.cpp b/WebCore/html/HTMLButtonElement.cpp index 6e57540..f65e748 100644 --- a/WebCore/html/HTMLButtonElement.cpp +++ b/WebCore/html/HTMLButtonElement.cpp @@ -35,11 +35,10 @@ namespace WebCore { -using namespace EventNames; using namespace HTMLNames; HTMLButtonElement::HTMLButtonElement(Document* doc, HTMLFormElement* form) - : HTMLGenericFormElement(buttonTag, doc, form) + : HTMLFormControlElement(buttonTag, doc, form) , m_type(SUBMIT) , m_activeSubmit(false) { @@ -56,32 +55,48 @@ RenderObject* HTMLButtonElement::createRenderer(RenderArena* arena, RenderStyle* const AtomicString& HTMLButtonElement::type() const { - return getAttribute(typeAttr); + switch (m_type) { + case SUBMIT: { + static const AtomicString submit("submit"); + return submit; + } + case BUTTON: { + static const AtomicString button("button"); + return button; + } + case RESET: { + static const AtomicString reset("reset"); + return reset; + } + } + + ASSERT_NOT_REACHED(); + return emptyAtom; } void HTMLButtonElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == typeAttr) { - if (equalIgnoringCase(attr->value(), "submit")) - m_type = SUBMIT; - else if (equalIgnoringCase(attr->value(), "reset")) + if (equalIgnoringCase(attr->value(), "reset")) m_type = RESET; else if (equalIgnoringCase(attr->value(), "button")) m_type = BUTTON; + else + m_type = SUBMIT; } else if (attr->name() == alignAttr) { // Don't map 'align' attribute. This matches what Firefox and IE do, but not Opera. // See http://bugs.webkit.org/show_bug.cgi?id=12071 } else if (attr->name() == onfocusAttr) { - setHTMLEventListener(focusEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().focusEvent, attr); } else if (attr->name() == onblurAttr) { - setHTMLEventListener(blurEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().blurEvent, attr); } else - HTMLGenericFormElement::parseMappedAttribute(attr); + HTMLFormControlElement::parseMappedAttribute(attr); } void HTMLButtonElement::defaultEventHandler(Event* evt) { - if (evt->type() == DOMActivateEvent && !disabled()) { + if (evt->type() == eventNames().DOMActivateEvent && !disabled()) { if (form() && m_type == SUBMIT) { m_activeSubmit = true; form()->prepareSubmit(evt); @@ -92,12 +107,12 @@ void HTMLButtonElement::defaultEventHandler(Event* evt) } if (evt->isKeyboardEvent()) { - if (evt->type() == keydownEvent && static_cast<KeyboardEvent*>(evt)->keyIdentifier() == "U+0020") { + if (evt->type() == eventNames().keydownEvent && static_cast<KeyboardEvent*>(evt)->keyIdentifier() == "U+0020") { setActive(true, true); // No setDefaultHandled() - IE dispatches a keypress in this case. return; } - if (evt->type() == keypressEvent) { + if (evt->type() == eventNames().keypressEvent) { switch (static_cast<KeyboardEvent*>(evt)->charCode()) { case '\r': dispatchSimulatedClick(evt); @@ -111,7 +126,7 @@ void HTMLButtonElement::defaultEventHandler(Event* evt) break; } } - if (evt->type() == keyupEvent && static_cast<KeyboardEvent*>(evt)->keyIdentifier() == "U+0020") { + if (evt->type() == eventNames().keyupEvent && static_cast<KeyboardEvent*>(evt)->keyIdentifier() == "U+0020") { if (active()) dispatchSimulatedClick(evt); evt->setDefaultHandled(); @@ -119,7 +134,7 @@ void HTMLButtonElement::defaultEventHandler(Event* evt) } } - HTMLGenericFormElement::defaultEventHandler(evt); + HTMLFormControlElement::defaultEventHandler(evt); } bool HTMLButtonElement::isSuccessfulSubmitButton() const diff --git a/WebCore/html/HTMLButtonElement.h b/WebCore/html/HTMLButtonElement.h index fc42b42..4d55ba5 100644 --- a/WebCore/html/HTMLButtonElement.h +++ b/WebCore/html/HTMLButtonElement.h @@ -24,11 +24,11 @@ #ifndef HTMLButtonElement_h #define HTMLButtonElement_h -#include "HTMLGenericFormElement.h" +#include "HTMLFormControlElement.h" namespace WebCore { -class HTMLButtonElement : public HTMLGenericFormElement { +class HTMLButtonElement : public HTMLFormControlElement { public: HTMLButtonElement(Document*, HTMLFormElement* = 0); virtual ~HTMLButtonElement(); @@ -56,6 +56,8 @@ public: String value() const; void setValue(const String&); + + virtual bool willValidate() const { return false; } private: enum Type { SUBMIT, RESET, BUTTON }; diff --git a/WebCore/html/HTMLButtonElement.idl b/WebCore/html/HTMLButtonElement.idl index be39119..028e92b 100644 --- a/WebCore/html/HTMLButtonElement.idl +++ b/WebCore/html/HTMLButtonElement.idl @@ -28,11 +28,11 @@ module html { readonly attribute HTMLFormElement form; attribute [ConvertNullToNullString] DOMString accessKey; attribute boolean disabled; + attribute boolean autofocus; attribute [ConvertNullToNullString] DOMString name; - attribute long tabIndex; readonly attribute DOMString type; attribute [ConvertNullToNullString] DOMString value; - + readonly attribute boolean willValidate; void click(); }; diff --git a/WebCore/html/HTMLCanvasElement.cpp b/WebCore/html/HTMLCanvasElement.cpp index 8c3fc15..f3ca1fd 100644 --- a/WebCore/html/HTMLCanvasElement.cpp +++ b/WebCore/html/HTMLCanvasElement.cpp @@ -33,20 +33,18 @@ #include "CanvasStyle.h" #include "Chrome.h" #include "Document.h" +#include "ExceptionCode.h" #include "Frame.h" #include "GraphicsContext.h" #include "HTMLNames.h" +#include "ImageBuffer.h" +#include "MIMETypeRegistry.h" #include "Page.h" #include "RenderHTMLCanvas.h" #include "Settings.h" +#include <kjs/interpreter.h> #include <math.h> - -#if PLATFORM(QT) -#include <QPainter> -#include <QPixmap> -#elif PLATFORM(CAIRO) -#include <cairo.h> -#endif +#include <stdio.h> namespace WebCore { @@ -59,38 +57,24 @@ static const int defaultHeight = 150; // Firefox limits width/height to 32767 pixels, but slows down dramatically before it // reaches that limit. We limit by area instead, giving us larger maximum dimensions, // in exchange for a smaller maximum canvas size. -static const float maxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels +const float HTMLCanvasElement::MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels HTMLCanvasElement::HTMLCanvasElement(Document* doc) : HTMLElement(canvasTag, doc) , m_size(defaultWidth, defaultHeight) - , m_createdDrawingContext(false) - , m_data(0) -#if PLATFORM(QT) - , m_painter(0) -#elif PLATFORM(CAIRO) - , m_surface(0) -#endif - , m_drawingContext(0) + , m_observer(0) + , m_originClean(true) + , m_ignoreReset(false) + , m_createdImageBuffer(false) { } HTMLCanvasElement::~HTMLCanvasElement() { - if (m_2DContext) - m_2DContext->detachCanvas(); -#if PLATFORM(CG) - fastFree(m_data); -#elif PLATFORM(QT) - delete m_painter; - delete m_data; -#elif PLATFORM(CAIRO) - if (m_surface) - cairo_surface_destroy(m_surface); -#endif - delete m_drawingContext; } +#if ENABLE(DASHBOARD_SUPPORT) + HTMLTagStatus HTMLCanvasElement::endTagRequirement() const { Settings* settings = document()->settings(); @@ -109,6 +93,8 @@ int HTMLCanvasElement::tagPriority() const return HTMLElement::tagPriority(); } +#endif + void HTMLCanvasElement::parseMappedAttribute(MappedAttribute* attr) { const QualifiedName& attrName = attr->name(); @@ -139,11 +125,27 @@ void HTMLCanvasElement::setWidth(int value) setAttribute(widthAttr, String::number(value)); } +String HTMLCanvasElement::toDataURL(const String& mimeType, ExceptionCode& ec) +{ + if (!m_originClean) { + ec = SECURITY_ERR; + return String(); + } + + if (m_size.isEmpty()) + return String("data:,"); + + if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)) + return buffer()->toDataURL("image/png"); + + return buffer()->toDataURL(mimeType); +} + CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type) { if (type == "2d") { if (!m_2DContext) - m_2DContext = new CanvasRenderingContext2D(this); + m_2DContext.set(new CanvasRenderingContext2D(this)); return m_2DContext.get(); } return 0; @@ -151,6 +153,8 @@ CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type) void HTMLCanvasElement::willDraw(const FloatRect& rect) { + m_imageBuffer->clearImage(); + if (RenderObject* ro = renderer()) { #ifdef CANVAS_INCREMENTAL_REPAINT // Handle CSS triggered scaling @@ -162,10 +166,16 @@ void HTMLCanvasElement::willDraw(const FloatRect& rect) ro->repaint(); #endif } + + if (m_observer) + m_observer->canvasChanged(this, rect); } void HTMLCanvasElement::reset() { + if (m_ignoreReset) + return; + bool ok; int w = getAttribute(widthAttr).toInt(&ok); if (!ok) @@ -177,22 +187,9 @@ void HTMLCanvasElement::reset() IntSize oldSize = m_size; m_size = IntSize(w, h); - bool hadDrawingContext = m_createdDrawingContext; - m_createdDrawingContext = false; -#if PLATFORM(CG) - fastFree(m_data); -#elif PLATFORM(QT) - delete m_painter; - m_painter = 0; - delete m_data; -#elif PLATFORM(CAIRO) - if (m_surface) - cairo_surface_destroy(m_surface); - m_surface = 0; -#endif - m_data = 0; - delete m_drawingContext; - m_drawingContext = 0; + bool hadImageBuffer = m_createdImageBuffer; + m_createdImageBuffer = false; + m_imageBuffer.clear(); if (m_2DContext) m_2DContext->reset(); @@ -200,156 +197,75 @@ void HTMLCanvasElement::reset() if (m_rendererIsCanvas) { if (oldSize != m_size) static_cast<RenderHTMLCanvas*>(ro)->canvasSizeChanged(); - if (hadDrawingContext) + if (hadImageBuffer) ro->repaint(); } + + if (m_observer) + m_observer->canvasResized(this); } -void HTMLCanvasElement::paint(GraphicsContext* p, const IntRect& r) +void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r) { - if (p->paintingDisabled()) + if (context->paintingDisabled()) return; -#if PLATFORM(CG) - if (CGImageRef image = createPlatformImage()) { - CGContextDrawImage(p->platformContext(), p->roundToDevicePixels(r), image); - CGImageRelease(image); + + if (m_imageBuffer) { + Image* image = m_imageBuffer->image(); + if (image) + context->drawImage(image, r); } -#elif defined(ANDROID_CANVAS_IMPL) - if (m_drawingContext) { - p->drawOffscreenContext(m_drawingContext, NULL, FloatRect(r)); - } -#elif PLATFORM(QT) - if (m_data) { - QPen currentPen = m_painter->pen(); - qreal currentOpacity = m_painter->opacity(); - QBrush currentBrush = m_painter->brush(); - QBrush currentBackground = m_painter->background(); - if (m_painter->isActive()) - m_painter->end(); - static_cast<QPainter*>(p->platformContext())->drawImage(r, *m_data); - m_painter->begin(m_data); - m_painter->setPen(currentPen); - m_painter->setBrush(currentBrush); - m_painter->setOpacity(currentOpacity); - m_painter->setBackground(currentBackground); - } -#elif PLATFORM(CAIRO) - if (cairo_surface_t* image = createPlatformImage()) { - cairo_t* cr = p->platformContext(); - cairo_save(cr); - cairo_translate(cr, r.x(), r.y()); - cairo_set_source_surface(cr, image, 0, 0); - cairo_surface_destroy(image); - cairo_rectangle(cr, 0, 0, r.width(), r.height()); - cairo_fill(cr); - cairo_restore(cr); - } -#endif } -void HTMLCanvasElement::createDrawingContext() const +IntRect HTMLCanvasElement::convertLogicalToDevice(const FloatRect& logicalRect) const { - ASSERT(!m_createdDrawingContext); - ASSERT(!m_data); - - m_createdDrawingContext = true; + return IntRect(convertLogicalToDevice(logicalRect.location()), convertLogicalToDevice(logicalRect.size())); +} - float unscaledWidth = width(); - float unscaledHeight = height(); +IntSize HTMLCanvasElement::convertLogicalToDevice(const FloatSize& logicalSize) const +{ float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f; - float wf = ceilf(unscaledWidth * pageScaleFactor); - float hf = ceilf(unscaledHeight * pageScaleFactor); - - if (!(wf >= 1 && hf >= 1 && wf * hf <= maxCanvasArea)) - return; - - unsigned w = static_cast<unsigned>(wf); - unsigned h = static_cast<unsigned>(hf); + float wf = ceilf(logicalSize.width() * pageScaleFactor); + float hf = ceilf(logicalSize.height() * pageScaleFactor); + + if (!(wf >= 1 && hf >= 1 && wf * hf <= MaxCanvasArea)) + return IntSize(); -#if PLATFORM(CG) - size_t bytesPerRow = w * 4; - if (bytesPerRow / 4 != w) // check for overflow - return; - m_data = fastCalloc(h, bytesPerRow); - if (!m_data) - return; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGContextRef bitmapContext = CGBitmapContextCreate(m_data, w, h, 8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); - CGContextScaleCTM(bitmapContext, w / unscaledWidth, h / unscaledHeight); - CGColorSpaceRelease(colorSpace); - m_drawingContext = new GraphicsContext(bitmapContext); - CGContextRelease(bitmapContext); -#elif PLATFORM(QT) - m_data = new QImage(w, h, QImage::Format_ARGB32_Premultiplied); - if (!m_data) - return; - m_painter = new QPainter(m_data); - m_painter->setBackground(QBrush(Qt::transparent)); - m_painter->fillRect(0, 0, w, h, QColor(Qt::transparent)); - m_drawingContext = new GraphicsContext(m_painter); -#elif defined(ANDROID_CANVAS_IMPL) - m_drawingContext = GraphicsContext::createOffscreenContext(w, h); - m_drawingContext->scale(FloatSize(w / unscaledWidth, h / unscaledHeight)); -#elif PLATFORM(CAIRO) - m_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); - // m_data is owned by m_surface - m_data = cairo_image_surface_get_data(m_surface); - cairo_t* cr = cairo_create(m_surface); - cairo_scale(cr, w / unscaledWidth, h / unscaledHeight); - m_drawingContext = new GraphicsContext(cr); - cairo_destroy(cr); -#endif + return IntSize(static_cast<unsigned>(wf), static_cast<unsigned>(hf)); } -GraphicsContext* HTMLCanvasElement::drawingContext() const +IntPoint HTMLCanvasElement::convertLogicalToDevice(const FloatPoint& logicalPos) const { - if (!m_createdDrawingContext) - createDrawingContext(); - return m_drawingContext; + float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f; + float xf = logicalPos.x() * pageScaleFactor; + float yf = logicalPos.y() * pageScaleFactor; + + return IntPoint(static_cast<unsigned>(xf), static_cast<unsigned>(yf)); } -#if PLATFORM(CG) - -CGImageRef HTMLCanvasElement::createPlatformImage() const +void HTMLCanvasElement::createImageBuffer() const { - GraphicsContext* context = drawingContext(); - if (!context) - return 0; - - CGContextRef contextRef = context->platformContext(); - if (!contextRef) - return 0; - - CGContextFlush(contextRef); + ASSERT(!m_imageBuffer); - return CGBitmapContextCreateImage(contextRef); + m_createdImageBuffer = true; + + FloatSize unscaledSize(width(), height()); + IntSize size = convertLogicalToDevice(unscaledSize); + if (!size.width() || !size.height()) + return; + m_imageBuffer.set(ImageBuffer::create(size, false).release()); } -#elif PLATFORM(QT) - -QImage HTMLCanvasElement::createPlatformImage() const +GraphicsContext* HTMLCanvasElement::drawingContext() const { - if (m_data) - return *m_data; - return QImage(); + return buffer() ? m_imageBuffer->context() : 0; } -#elif PLATFORM(CAIRO) - -cairo_surface_t* HTMLCanvasElement::createPlatformImage() const +ImageBuffer* HTMLCanvasElement::buffer() const { - if (!m_surface) - return 0; - - // Note that unlike CG, our returned image is not a copy or - // copy-on-write, but the original. This is fine, since it is only - // ever used as a source. - - cairo_surface_flush(m_surface); - cairo_surface_reference(m_surface); - return m_surface; + if (!m_createdImageBuffer) + createImageBuffer(); + return m_imageBuffer.get(); } -#endif - } diff --git a/WebCore/html/HTMLCanvasElement.h b/WebCore/html/HTMLCanvasElement.h index add1bf7..a118364 100644 --- a/WebCore/html/HTMLCanvasElement.h +++ b/WebCore/html/HTMLCanvasElement.h @@ -30,83 +30,97 @@ #include "HTMLElement.h" #include "IntSize.h" -#if PLATFORM(CG) -// FIXME: CG-specific parts need to move to the platform directory. -typedef struct CGContext* CGContextRef; -typedef struct CGImage* CGImageRef; -#elif PLATFORM(QT) -class QImage; -class QPainter; -#elif PLATFORM(CAIRO) -typedef struct _cairo_surface cairo_surface_t; -#endif - namespace WebCore { class CanvasRenderingContext2D; typedef CanvasRenderingContext2D CanvasRenderingContext; +class FloatPoint; class FloatRect; +class FloatSize; class GraphicsContext; +class HTMLCanvasElement; +class ImageBuffer; +class IntPoint; +class InttRect; +class IntSize; + +class CanvasObserver { +public: + virtual ~CanvasObserver() {}; + + virtual void canvasChanged(HTMLCanvasElement* element, const FloatRect& changedRect) = 0; + virtual void canvasResized(HTMLCanvasElement* element) = 0; +}; class HTMLCanvasElement : public HTMLElement { public: HTMLCanvasElement(Document*); virtual ~HTMLCanvasElement(); +#if ENABLE(DASHBOARD_SUPPORT) virtual HTMLTagStatus endTagRequirement() const; virtual int tagPriority() const; +#endif int width() const { return m_size.width(); } int height() const { return m_size.height(); } void setWidth(int); void setHeight(int); + String toDataURL(const String& mimeType, ExceptionCode&); + CanvasRenderingContext* getContext(const String&); - // FIXME: Web Applications 1.0 describes a toDataURL function. virtual void parseMappedAttribute(MappedAttribute*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); IntSize size() const { return m_size; } + void setSize(const IntSize& size) + { + if (size == m_size) + return; + m_ignoreReset = true; + setWidth(size.width()); + setHeight(size.height()); + m_ignoreReset = false; + reset(); + } + void willDraw(const FloatRect&); void paint(GraphicsContext*, const IntRect&); GraphicsContext* drawingContext() const; -#if PLATFORM(CG) - CGImageRef createPlatformImage() const; -#elif PLATFORM(QT) - QImage createPlatformImage() const; -#elif PLATFORM(CAIRO) - cairo_surface_t* createPlatformImage() const; -#endif + ImageBuffer* buffer() const; + + IntRect convertLogicalToDevice(const FloatRect&) const; + IntSize convertLogicalToDevice(const FloatSize&) const; + IntPoint convertLogicalToDevice(const FloatPoint&) const; + + void setOriginTainted() { m_originClean = false; } + bool originClean() const { return m_originClean; } + + static const float MaxCanvasArea; + + void setObserver(CanvasObserver* o) { m_observer = o; } private: - void createDrawingContext() const; + void createImageBuffer() const; void reset(); bool m_rendererIsCanvas; - RefPtr<CanvasRenderingContext2D> m_2DContext; - IntSize m_size; - - // FIXME: Web Applications 1.0 describes a security feature where we track - // if we ever drew any images outside the domain, so we can disable toDataURL. - - mutable bool m_createdDrawingContext; -#if PLATFORM(CG) - mutable void* m_data; -#elif PLATFORM(QT) - mutable QImage* m_data; - mutable QPainter* m_painter; -#elif PLATFORM(CAIRO) - mutable void* m_data; - mutable cairo_surface_t* m_surface; -#else - mutable void* m_data; -#endif - mutable GraphicsContext* m_drawingContext; + OwnPtr<CanvasRenderingContext2D> m_2DContext; + IntSize m_size; + CanvasObserver* m_observer; + + bool m_originClean; + bool m_ignoreReset; + + // m_createdImageBuffer means we tried to malloc the buffer. We didn't necessarily get it. + mutable bool m_createdImageBuffer; + mutable OwnPtr<ImageBuffer> m_imageBuffer; }; } //namespace diff --git a/WebCore/html/HTMLCanvasElement.idl b/WebCore/html/HTMLCanvasElement.idl index 35c7383..e457c15 100644 --- a/WebCore/html/HTMLCanvasElement.idl +++ b/WebCore/html/HTMLCanvasElement.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,6 +34,9 @@ module html { attribute long width; attribute long height; + DOMString toDataURL(in [ConvertUndefinedOrNullToNullString] DOMString type) + raises(DOMException); + #if !defined(LANGUAGE_OBJECTIVE_C) DOMObject getContext(in DOMString contextId); #endif diff --git a/WebCore/html/HTMLCollection.cpp b/WebCore/html/HTMLCollection.cpp index 474e6a6..44b84a0 100644 --- a/WebCore/html/HTMLCollection.cpp +++ b/WebCore/html/HTMLCollection.cpp @@ -53,6 +53,11 @@ HTMLCollection::HTMLCollection(PassRefPtr<Node> base, Type type, CollectionInfo* { } +PassRefPtr<HTMLCollection> HTMLCollection::create(PassRefPtr<Node> base, Type type) +{ + return adoptRef(new HTMLCollection(base, type)); +} + HTMLCollection::~HTMLCollection() { if (m_ownsInfo) @@ -346,11 +351,10 @@ bool HTMLCollection::checkForNameMatch(Element* element, bool checkName, const S e->hasLocalName(selectTag))) return false; - return e->getAttribute(nameAttr).domString().lower() == name.lower() && - e->getAttribute(idAttr).domString().lower() != name.lower(); - } else { - return e->getAttribute(idAttr).domString().lower() == name.lower(); - } + return equalIgnoringCase(e->getAttribute(nameAttr), name) + && !equalIgnoringCase(e->getAttribute(idAttr), name); + } else + return equalIgnoringCase(e->getAttribute(idAttr), name); } } diff --git a/WebCore/html/HTMLCollection.h b/WebCore/html/HTMLCollection.h index d992c81..3d75108 100644 --- a/WebCore/html/HTMLCollection.h +++ b/WebCore/html/HTMLCollection.h @@ -76,7 +76,7 @@ public: static const Type FirstNamedDocumentCachedType = WindowNamedItems; static const unsigned NumNamedDocumentCachedTypes = DocumentNamedItems - WindowNamedItems + 1; - HTMLCollection(PassRefPtr<Node> base, Type); + static PassRefPtr<HTMLCollection> create(PassRefPtr<Node> base, Type); virtual ~HTMLCollection(); unsigned length() const; @@ -139,6 +139,8 @@ protected: mutable bool m_idsDone; // for nextNamedItem() private: + HTMLCollection(PassRefPtr<Node> base, Type); + virtual Element* itemAfter(Element*) const; virtual unsigned calcLength() const; virtual void updateNameCache() const; diff --git a/WebCore/html/HTMLDivElement.cpp b/WebCore/html/HTMLDivElement.cpp index 0951de8..3aab91b 100644 --- a/WebCore/html/HTMLDivElement.cpp +++ b/WebCore/html/HTMLDivElement.cpp @@ -55,13 +55,13 @@ void HTMLDivElement::parseMappedAttribute(MappedAttribute *attr) if (attr->name() == alignAttr) { String v = attr->value(); if (equalIgnoringCase(attr->value(), "middle") || equalIgnoringCase(attr->value(), "center")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__WEBKIT_CENTER); + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitCenter); else if (equalIgnoringCase(attr->value(), "left")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__WEBKIT_LEFT); + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitLeft); else if (equalIgnoringCase(attr->value(), "right")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__WEBKIT_RIGHT); + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitRight); else - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, v); + addCSSProperty(attr, CSSPropertyTextAlign, v); } else HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLDocument.cpp b/WebCore/html/HTMLDocument.cpp index 8db8422..97557f9 100644 --- a/WebCore/html/HTMLDocument.cpp +++ b/WebCore/html/HTMLDocument.cpp @@ -1,7 +1,7 @@ -/** +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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 @@ -60,8 +60,10 @@ #include "DocumentLoader.h" #include "DocumentType.h" #include "ExceptionCode.h" +#include "FocusController.h" #include "Frame.h" #include "FrameLoader.h" +#include "FrameTree.h" #include "FrameView.h" #include "HTMLBodyElement.h" #include "HTMLElement.h" @@ -83,10 +85,11 @@ namespace WebCore { using namespace HTMLNames; -HTMLDocument::HTMLDocument(DOMImplementation* implementation, Frame* frame) - : Document(implementation, frame) +HTMLDocument::HTMLDocument(Frame* frame) + : Document(frame, false) { clearXMLVersion(); + setParseMode(Compat); } HTMLDocument::~HTMLDocument() @@ -144,6 +147,25 @@ String HTMLDocument::compatMode() const return inCompatMode() ? "BackCompat" : "CSS1Compat"; } +Element* HTMLDocument::activeElement() +{ + if (Node* node = focusedNode()) + if (node->isElementNode()) + return static_cast<Element*>(node); + return body(); +} + +bool HTMLDocument::hasFocus() +{ + if (!page()->focusController()->isActive()) + return false; + if (Frame* focusedFrame = page()->focusController()->focusedFrame()) { + if (focusedFrame->tree()->isDescendantOf(frame())) + return true; + } + return false; +} + String HTMLDocument::bgColor() { HTMLElement* b = body(); @@ -278,22 +300,22 @@ Tokenizer *HTMLDocument::createTokenizer() bool HTMLDocument::childAllowed(Node *newChild) { - return newChild->hasTagName(htmlTag) || newChild->isCommentNode(); + return newChild->hasTagName(htmlTag) || newChild->isCommentNode() || (newChild->nodeType() == DOCUMENT_TYPE_NODE && !doctype()); } -PassRefPtr<Element> HTMLDocument::createElement(const String &name, ExceptionCode& ec) +PassRefPtr<Element> HTMLDocument::createElement(const AtomicString& name, ExceptionCode& ec) { - String lowerName(name.lower()); - if (!isValidName(lowerName)) { + if (!isValidName(name)) { ec = INVALID_CHARACTER_ERR; return 0; } - return HTMLElementFactory::createHTMLElement(AtomicString(lowerName), this, 0, false); + AtomicString lowerName = name.string().impl()->isLower() ? name : AtomicString(name.string().lower()); + return HTMLElementFactory::createHTMLElement(lowerName, this, 0, false); } -static void addItemToMap(HTMLDocument::NameCountMap& map, const String& name) +static void addItemToMap(HTMLDocument::NameCountMap& map, const AtomicString& name) { - if (name.length() == 0) + if (name.isEmpty()) return; HTMLDocument::NameCountMap::iterator it = map.find(name.impl()); @@ -303,9 +325,9 @@ static void addItemToMap(HTMLDocument::NameCountMap& map, const String& name) ++(it->second); } -static void removeItemFromMap(HTMLDocument::NameCountMap& map, const String& name) +static void removeItemFromMap(HTMLDocument::NameCountMap& map, const AtomicString& name) { - if (name.length() == 0) + if (name.isEmpty()) return; HTMLDocument::NameCountMap::iterator it = map.find(name.impl()); @@ -321,266 +343,96 @@ static void removeItemFromMap(HTMLDocument::NameCountMap& map, const String& nam it->second = newVal; } -void HTMLDocument::addNamedItem(const String& name) +void HTMLDocument::addNamedItem(const AtomicString& name) { - addItemToMap(namedItemCounts, name); + addItemToMap(m_namedItemCounts, name); } -void HTMLDocument::removeNamedItem(const String &name) +void HTMLDocument::removeNamedItem(const AtomicString &name) { - removeItemFromMap(namedItemCounts, name); -} - -bool HTMLDocument::hasNamedItem(const String& name) -{ - return namedItemCounts.get(name.impl()) != 0; + removeItemFromMap(m_namedItemCounts, name); } -void HTMLDocument::addDocExtraNamedItem(const String& name) +void HTMLDocument::addExtraNamedItem(const AtomicString& name) { - addItemToMap(docExtraNamedItemCounts, name); + addItemToMap(m_extraNamedItemCounts, name); } -void HTMLDocument::removeDocExtraNamedItem(const String& name) +void HTMLDocument::removeExtraNamedItem(const AtomicString& name) { - removeItemFromMap(docExtraNamedItemCounts, name); + removeItemFromMap(m_extraNamedItemCounts, name); } -bool HTMLDocument::hasDocExtraNamedItem(const String& name) +void HTMLDocument::determineParseMode() { - return docExtraNamedItemCounts.get(name.impl()) != 0; -} - -const int PARSEMODE_HAVE_DOCTYPE = (1<<0); -const int PARSEMODE_HAVE_PUBLIC_ID = (1<<1); -const int PARSEMODE_HAVE_SYSTEM_ID = (1<<2); -const int PARSEMODE_HAVE_INTERNAL = (1<<3); - -static int parseDocTypePart(const String& buffer, int index) -{ - while (true) { - UChar ch = buffer[index]; - if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') - ++index; - else if (ch == '-') { - int tmpIndex=index; - if (buffer[index+1] == '-' && - ((tmpIndex=buffer.find("--", index+2)) != -1)) - index = tmpIndex+2; - else - return index; - } - else - return index; - } -} - -static bool containsString(const char* str, const String& buffer, int offset) -{ - String startString(str); - if (offset + startString.length() > buffer.length()) - return false; - - String bufferString = buffer.substring(offset, startString.length()).lower(); - String lowerStart = startString.lower(); - - return bufferString.startsWith(lowerStart); -} - -static bool parseDocTypeDeclaration(const String& buffer, - int* resultFlags, - String& name, - String& publicID, - String& systemID) -{ - bool haveDocType = false; - *resultFlags = 0; - - // Skip through any comments and processing instructions. - int index = 0; - do { - index = buffer.find('<', index); - if (index == -1) break; - UChar nextChar = buffer[index+1]; - if (nextChar == '!') { - if (containsString("doctype", buffer, index+2)) { - haveDocType = true; - index += 9; // Skip "<!DOCTYPE" - break; - } - index = parseDocTypePart(buffer,index); - index = buffer.find('>', index); - } - else if (nextChar == '?') - index = buffer.find('>', index); - else - break; - } while (index != -1); - - if (!haveDocType) - return true; - *resultFlags |= PARSEMODE_HAVE_DOCTYPE; - - index = parseDocTypePart(buffer, index); - if (!containsString("html", buffer, index)) - return false; - - name = buffer.substring(index, 4); - index = parseDocTypePart(buffer, index+4); - bool hasPublic = containsString("public", buffer, index); - if (hasPublic) { - index = parseDocTypePart(buffer, index+6); - - // We've read <!DOCTYPE HTML PUBLIC (not case sensitive). - // Now we find the beginning and end of the public identifers - // and system identifiers (assuming they're even present). - UChar theChar = buffer[index]; - if (theChar != '\"' && theChar != '\'') - return false; - - // |start| is the first character (after the quote) and |end| - // is the final quote, so there are |end|-|start| characters. - int publicIDStart = index+1; - int publicIDEnd = buffer.find(theChar, publicIDStart); - if (publicIDEnd == -1) - return false; - index = parseDocTypePart(buffer, publicIDEnd+1); - UChar next = buffer[index]; - if (next == '>') { - // Public identifier present, but no system identifier. - // Do nothing. Note that this is the most common - // case. - } - else if (next == '\"' || next == '\'') { - // We have a system identifier. - *resultFlags |= PARSEMODE_HAVE_SYSTEM_ID; - int systemIDStart = index+1; - int systemIDEnd = buffer.find(next, systemIDStart); - if (systemIDEnd == -1) - return false; - systemID = buffer.substring(systemIDStart, systemIDEnd - systemIDStart); - } - else if (next == '[') { - // We found an internal subset. - *resultFlags |= PARSEMODE_HAVE_INTERNAL; - } - else - return false; // Something's wrong. - - // We need to trim whitespace off the public identifier. - publicID = buffer.substring(publicIDStart, publicIDEnd - publicIDStart); - publicID = publicID.stripWhiteSpace(); - *resultFlags |= PARSEMODE_HAVE_PUBLIC_ID; - } else { - if (containsString("system", buffer, index)) { - // Doctype has a system ID but no public ID - *resultFlags |= PARSEMODE_HAVE_SYSTEM_ID; - index = parseDocTypePart(buffer, index+6); - UChar next = buffer[index]; - if (next != '\"' && next != '\'') - return false; - int systemIDStart = index+1; - int systemIDEnd = buffer.find(next, systemIDStart); - if (systemIDEnd == -1) - return false; - systemID = buffer.substring(systemIDStart, systemIDEnd - systemIDStart); - index = parseDocTypePart(buffer, systemIDEnd+1); - } - - UChar nextChar = buffer[index]; - if (nextChar == '[') - *resultFlags |= PARSEMODE_HAVE_INTERNAL; - else if (nextChar != '>') - return false; - } + // FIXME: It's terrible that this code runs separately and isn't just built in to the + // HTML tokenizer/parser. - return true; -} - -void HTMLDocument::determineParseMode(const String& str) -{ // This code more or less mimics Mozilla's implementation (specifically the // doctype parsing implemented by David Baron in Mozilla's nsParser.cpp). // // There are three possible parse modes: - // COMPAT - quirks mode emulates WinIE - // and NS4. CSS parsing is also relaxed in this mode, e.g., unit types can + // COMPAT - quirks mode emulates WinIE and NS4. CSS parsing is also relaxed in this mode, e.g., unit types can // be omitted from numbers. - // ALMOST STRICT - This mode is identical to strict mode - // except for its treatment of line-height in the inline box model. For - // now (until the inline box model is re-written), this mode is identical - // to STANDARDS mode. - // STRICT - no quirks apply. Web pages will obey the specifications to - // the letter. - - String name, systemID, publicID; - int resultFlags = 0; - if (parseDocTypeDeclaration(str, &resultFlags, name, publicID, systemID)) { - if (resultFlags & PARSEMODE_HAVE_DOCTYPE) - setDocType(new DocumentType(this, name, publicID, systemID)); - if (!(resultFlags & PARSEMODE_HAVE_DOCTYPE)) { - // No doctype found at all. Default to quirks mode and Html4. - setParseMode(Compat); - setHTMLMode(Html4); + // ALMOST STRICT - This mode is identical to strict mode except for its treatment of line-height in the inline box model. For + // now (until the inline box model is re-written), this mode is identical to STANDARDS mode. + // STRICT - no quirks apply. Web pages will obey the specifications to the letter. + bool wasInCompatMode = inCompatMode(); + DocumentType* docType = doctype(); + if (!docType || !equalIgnoringCase(docType->name(), "html")) + // No doctype found at all or the doctype is not HTML. Default to quirks mode and Html4. + setParseMode(Compat); + else if (!doctype()->systemId().isEmpty() && equalIgnoringCase(docType->systemId(), "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd")) + // Assume quirks mode for this particular system ID. In the HTML5 spec, this is the only + // system identifier that is examined. + setParseMode(Compat); + else if (docType->publicId().isEmpty()) + // A doctype without a public ID means use strict mode. + setParseMode(Strict); + else { + // We have to check a list of public IDs to see what we + // should do. + String lowerPubID = docType->publicId().lower(); + CString pubIDStr = lowerPubID.latin1(); + +#ifdef ANDROID_META_SUPPORT + if ((!frame()->tree() || !frame()->tree()->parent()) && + strstr(pubIDStr.data(), "-//wapforum//dtd xhtml mobile 1.") == pubIDStr.data()) { + // fit mobile sites directly in the screen + frame()->settings()->setMetadataSettings("width", "device-width"); } - else if ((resultFlags & PARSEMODE_HAVE_INTERNAL) || - !(resultFlags & PARSEMODE_HAVE_PUBLIC_ID)) { - // Internal subsets always denote full standards, as does - // a doctype without a public ID. +#endif + // Look up the entry in our gperf-generated table. + const PubIDInfo* doctypeEntry = findDoctypeEntry(pubIDStr.data(), pubIDStr.length()); + if (!doctypeEntry) + // The DOCTYPE is not in the list. Assume strict mode. setParseMode(Strict); - setHTMLMode(Html4); - } else { - // We have to check a list of public IDs to see what we - // should do. - String lowerPubID = publicID.lower(); - CString pubIDStr = lowerPubID.latin1(); - -#ifdef ANDROID_META_SUPPORT - if ((!frame()->tree() || !frame()->tree()->parent()) && - strstr(pubIDStr.data(), "-//wapforum//dtd xhtml mobile 1.") == pubIDStr.data()) { - // fit mobile sites directly in the screen - frame()->settings()->setMetadataSettings("width", "device-width"); - } -#endif - // Look up the entry in our gperf-generated table. - const PubIDInfo* doctypeEntry = findDoctypeEntry(pubIDStr.data(), pubIDStr.length()); - if (!doctypeEntry) { - // The DOCTYPE is not in the list. Assume strict mode. - setParseMode(Strict); - setHTMLMode(Html4); - return; - } - - switch ((resultFlags & PARSEMODE_HAVE_SYSTEM_ID) ? - doctypeEntry->mode_if_sysid : - doctypeEntry->mode_if_no_sysid) - { + switch (docType->systemId().isEmpty() ? + doctypeEntry->mode_if_no_sysid : + doctypeEntry->mode_if_sysid) { case PubIDInfo::eQuirks3: - setParseMode(Compat); - setHTMLMode(Html3); - break; case PubIDInfo::eQuirks: setParseMode(Compat); - setHTMLMode(Html4); break; case PubIDInfo::eAlmostStandards: setParseMode(AlmostStrict); - setHTMLMode(Html4); break; default: ASSERT(false); } - } - } - else { - // Malformed doctype implies quirks mode. - setParseMode(Compat); - setHTMLMode(Html3); + } } - - styleSelector()->strictParsing = !inCompatMode(); - + + if (inCompatMode() != wasInCompatMode) + updateStyleSelector(); +} + +void HTMLDocument::clear() +{ + // FIXME: This does nothing, and that seems unlikely to be correct. + // We've long had a comment saying that IE doesn't support this. + // But I do see it in the documentation for Mozilla. } } diff --git a/WebCore/html/HTMLDocument.h b/WebCore/html/HTMLDocument.h index fefbdb7..de84c70 100644 --- a/WebCore/html/HTMLDocument.h +++ b/WebCore/html/HTMLDocument.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2006, 2007, 2008 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 @@ -33,11 +33,12 @@ class HTMLElement; class HTMLDocument : public Document, public CachedResourceClient { public: - HTMLDocument(DOMImplementation*, Frame*); + static PassRefPtr<HTMLDocument> create(Frame* frame) + { + return new HTMLDocument(frame); + } virtual ~HTMLDocument(); - virtual bool isHTMLDocument() const { return true; } - int width(); int height(); @@ -49,6 +50,9 @@ public: String compatMode() const; + Element* activeElement(); + bool hasFocus(); + String bgColor(); void setBgColor(const String&); String fgColor(); @@ -60,32 +64,49 @@ public: String vlinkColor(); void setVlinkColor(const String&); + void clear(); + void captureEvents(); void releaseEvents(); - virtual Tokenizer* createTokenizer(); - virtual bool childAllowed(Node*); - virtual PassRefPtr<Element> createElement(const String& tagName, ExceptionCode&); + virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&); - virtual void determineParseMode(const String&); + void addNamedItem(const AtomicString& name); + void removeNamedItem(const AtomicString& name); + bool hasNamedItem(AtomicStringImpl* name); - void addNamedItem(const String& name); - void removeNamedItem(const String& name); - bool hasNamedItem(const String& name); + void addExtraNamedItem(const AtomicString& name); + void removeExtraNamedItem(const AtomicString& name); + bool hasExtraNamedItem(AtomicStringImpl* name); - void addDocExtraNamedItem(const String& name); - void removeDocExtraNamedItem(const String& name); - bool hasDocExtraNamedItem(const String& name); + typedef HashMap<AtomicStringImpl*, int> NameCountMap; - typedef HashMap<StringImpl*, int> NameCountMap; +protected: + HTMLDocument(Frame*); private: - NameCountMap namedItemCounts; - NameCountMap docExtraNamedItemCounts; + virtual bool isHTMLDocument() const { return true; } + virtual Tokenizer* createTokenizer(); + virtual void determineParseMode(); + + NameCountMap m_namedItemCounts; + NameCountMap m_extraNamedItemCounts; }; +inline bool HTMLDocument::hasNamedItem(AtomicStringImpl* name) +{ + ASSERT(name); + return m_namedItemCounts.contains(name); +} + +inline bool HTMLDocument::hasExtraNamedItem(AtomicStringImpl* name) +{ + ASSERT(name); + return m_extraNamedItemCounts.contains(name); +} + } // namespace #endif diff --git a/WebCore/html/HTMLDocument.idl b/WebCore/html/HTMLDocument.idl index c0aabfe..4345195 100644 --- a/WebCore/html/HTMLDocument.idl +++ b/WebCore/html/HTMLDocument.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> * * This library is free software; you can redistribute it and/or @@ -38,13 +38,12 @@ module html { // Extensions #if defined(LANGUAGE_JAVASCRIPT) - // FIXME: These should eventually be available (if they are wanted) for all languages. - + // FIXME: This should eventually be available (if they are wanted) for all languages. attribute [Custom, Deletable] HTMLCollection all; - - [Custom] void clear(); #endif + void clear(); + void captureEvents(); void releaseEvents(); @@ -54,6 +53,9 @@ module html { attribute [ConvertNullToNullString] DOMString designMode; readonly attribute DOMString compatMode; + readonly attribute Element activeElement; + boolean hasFocus(); + // Deprecated attributes attribute [ConvertNullToNullString] DOMString bgColor; attribute [ConvertNullToNullString] DOMString fgColor; diff --git a/WebCore/html/HTMLElement.cpp b/WebCore/html/HTMLElement.cpp index 1f84e23..3f8a983 100644 --- a/WebCore/html/HTMLElement.cpp +++ b/WebCore/html/HTMLElement.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, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 @@ -46,7 +46,6 @@ namespace WebCore { -using namespace EventNames; using namespace HTMLNames; using std::min; @@ -66,7 +65,7 @@ String HTMLElement::nodeName() const // FIXME: Would be nice to have an atomicstring lookup based off uppercase chars that does not have to copy // the string on a hit in the hash. if (document()->isHTMLDocument()) - return tagQName().localName().domString().upper(); + return tagQName().localName().string().upper(); return Element::nodeName(); } @@ -103,7 +102,7 @@ PassRefPtr<Node> HTMLElement::cloneNode(bool deep) return 0; if (namedAttrMap) - *clone->attributes() = *namedAttrMap; + clone->attributes()->setAttributes(*namedAttrMap); clone->copyNonAttributeProperties(this); @@ -136,85 +135,107 @@ void HTMLElement::parseMappedAttribute(MappedAttribute *attr) String indexstring; if (attr->name() == alignAttr) { if (equalIgnoringCase(attr->value(), "middle")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, "center"); + addCSSProperty(attr, CSSPropertyTextAlign, "center"); else - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, attr->value()); + addCSSProperty(attr, CSSPropertyTextAlign, attr->value()); } else if (attr->name() == contenteditableAttr) { setContentEditable(attr); } else if (attr->name() == tabindexAttr) { indexstring = getAttribute(tabindexAttr); - if (indexstring.length()) - // Clamp tabindex to the range of 'short' to match Firefox's behavior. - setTabIndex(max(static_cast<int>(std::numeric_limits<short>::min()), min(indexstring.toInt(), static_cast<int>(std::numeric_limits<short>::max())))); + if (indexstring.length()) { + bool parsedOK; + int tabindex = indexstring.toIntStrict(&parsedOK); + if (parsedOK) + // Clamp tabindex to the range of 'short' to match Firefox's behavior. + setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max())))); + } } else if (attr->name() == langAttr) { // FIXME: Implement } else if (attr->name() == dirAttr) { - addCSSProperty(attr, CSS_PROP_DIRECTION, attr->value()); - addCSSProperty(attr, CSS_PROP_UNICODE_BIDI, hasLocalName(bdoTag) ? CSS_VAL_BIDI_OVERRIDE : CSS_VAL_EMBED); + addCSSProperty(attr, CSSPropertyDirection, attr->value()); + addCSSProperty(attr, CSSPropertyUnicodeBidi, hasLocalName(bdoTag) ? CSSValueBidiOverride : CSSValueEmbed); } // standard events else if (attr->name() == onclickAttr) { - setHTMLEventListener(clickEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().clickEvent, attr); } else if (attr->name() == oncontextmenuAttr) { - setHTMLEventListener(contextmenuEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().contextmenuEvent, attr); } else if (attr->name() == ondblclickAttr) { - setHTMLEventListener(dblclickEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().dblclickEvent, attr); } else if (attr->name() == onmousedownAttr) { - setHTMLEventListener(mousedownEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().mousedownEvent, attr); } else if (attr->name() == onmousemoveAttr) { - setHTMLEventListener(mousemoveEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().mousemoveEvent, attr); } else if (attr->name() == onmouseoutAttr) { - setHTMLEventListener(mouseoutEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().mouseoutEvent, attr); } else if (attr->name() == onmouseoverAttr) { - setHTMLEventListener(mouseoverEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().mouseoverEvent, attr); } else if (attr->name() == onmouseupAttr) { - setHTMLEventListener(mouseupEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().mouseupEvent, attr); } else if (attr->name() == onmousewheelAttr) { - setHTMLEventListener(mousewheelEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().mousewheelEvent, attr); } else if (attr->name() == onfocusAttr) { - setHTMLEventListener(focusEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().focusEvent, attr); } else if (attr->name() == onblurAttr) { - setHTMLEventListener(blurEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().blurEvent, attr); } else if (attr->name() == onkeydownAttr) { - setHTMLEventListener(keydownEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().keydownEvent, attr); } else if (attr->name() == onkeypressAttr) { - setHTMLEventListener(keypressEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().keypressEvent, attr); } else if (attr->name() == onkeyupAttr) { - setHTMLEventListener(keyupEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().keyupEvent, attr); } else if (attr->name() == onscrollAttr) { - setHTMLEventListener(scrollEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().scrollEvent, attr); } else if (attr->name() == onbeforecutAttr) { - setHTMLEventListener(beforecutEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().beforecutEvent, attr); } else if (attr->name() == oncutAttr) { - setHTMLEventListener(cutEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().cutEvent, attr); } else if (attr->name() == onbeforecopyAttr) { - setHTMLEventListener(beforecopyEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().beforecopyEvent, attr); } else if (attr->name() == oncopyAttr) { - setHTMLEventListener(copyEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().copyEvent, attr); } else if (attr->name() == onbeforepasteAttr) { - setHTMLEventListener(beforepasteEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().beforepasteEvent, attr); } else if (attr->name() == onpasteAttr) { - setHTMLEventListener(pasteEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().pasteEvent, attr); } else if (attr->name() == ondragenterAttr) { - setHTMLEventListener(dragenterEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().dragenterEvent, attr); } else if (attr->name() == ondragoverAttr) { - setHTMLEventListener(dragoverEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().dragoverEvent, attr); } else if (attr->name() == ondragleaveAttr) { - setHTMLEventListener(dragleaveEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().dragleaveEvent, attr); } else if (attr->name() == ondropAttr) { - setHTMLEventListener(dropEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().dropEvent, attr); } else if (attr->name() == ondragstartAttr) { - setHTMLEventListener(dragstartEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().dragstartEvent, attr); } else if (attr->name() == ondragAttr) { - setHTMLEventListener(dragEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().dragEvent, attr); } else if (attr->name() == ondragendAttr) { - setHTMLEventListener(dragendEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().dragendEvent, attr); } else if (attr->name() == onselectstartAttr) { - setHTMLEventListener(selectstartEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().selectstartEvent, attr); } else if (attr->name() == onsubmitAttr) { - setHTMLEventListener(submitEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().submitEvent, attr); } else if (attr->name() == onerrorAttr) { - setHTMLEventListener(errorEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().errorEvent, attr); + } else if (attr->name() == onwebkitanimationstartAttr) { + setInlineEventListenerForTypeAndAttribute(eventNames().webkitAnimationStartEvent, attr); + } else if (attr->name() == onwebkitanimationiterationAttr) { + setInlineEventListenerForTypeAndAttribute(eventNames().webkitAnimationIterationEvent, attr); + } else if (attr->name() == onwebkitanimationendAttr) { + setInlineEventListenerForTypeAndAttribute(eventNames().webkitAnimationEndEvent, attr); + } else if (attr->name() == onwebkittransitionendAttr) { + setInlineEventListenerForTypeAndAttribute(eventNames().webkitTransitionEndEvent, attr); +#if ENABLE(TOUCH_EVENTS) // Android + } else if (attr->name() == ontouchstartAttr) { + setInlineEventListenerForTypeAndAttribute(eventNames().touchstartEvent, attr); + } else if (attr->name() == ontouchendAttr) { + setInlineEventListenerForTypeAndAttribute(eventNames().touchendEvent, attr); + } else if (attr->name() == ontouchmoveAttr) { + setInlineEventListenerForTypeAndAttribute(eventNames().touchmoveEvent, attr); + } else if (attr->name() == ontouchcancelAttr) { + setInlineEventListenerForTypeAndAttribute(eventNames().touchcancelEvent, attr); +#endif } } @@ -492,6 +513,71 @@ void HTMLElement::setOuterText(const String &text, ExceptionCode& ec) } } +Node* HTMLElement::insertAdjacent(const String& where, Node* newChild, ExceptionCode& ec) +{ + // In Internet Explorer if the element has no parent and where is "beforeBegin" or "afterEnd", + // a document fragment is created and the elements appended in the correct order. This document + // fragment isn't returned anywhere. + // + // This is impossible for us to implement as the DOM tree does not allow for such structures, + // Opera also appears to disallow such usage. + + if (equalIgnoringCase(where, "beforeBegin")) { + if (Node* p = parent()) + return p->insertBefore(newChild, this, ec) ? newChild : 0; + return 0; + } + + if (equalIgnoringCase(where, "afterBegin")) + return insertBefore(newChild, firstChild(), ec) ? newChild : 0; + + if (equalIgnoringCase(where, "beforeEnd")) + return appendChild(newChild, ec) ? newChild : 0; + + if (equalIgnoringCase(where, "afterEnd")) { + if (Node* p = parent()) + return p->insertBefore(newChild, nextSibling(), ec) ? newChild : 0; + return 0; + } + + // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative + ec = NOT_SUPPORTED_ERR; + return 0; +} + +Element* HTMLElement::insertAdjacentElement(const String& where, Element* newChild, ExceptionCode& ec) +{ + if (!newChild) { + // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative + ec = TYPE_MISMATCH_ERR; + return 0; + } + + Node* returnValue = insertAdjacent(where, newChild, ec); + ASSERT(!returnValue || returnValue->isElementNode()); + return static_cast<Element*>(returnValue); +} + +void HTMLElement::insertAdjacentHTML(const String& where, const String& html, ExceptionCode& ec) +{ + RefPtr<DocumentFragment> fragment = document()->createDocumentFragment(); + if (document()->isHTMLDocument()) + parseHTMLDocumentFragment(html, fragment.get()); + else { + if (!parseXMLDocumentFragment(html, fragment.get(), this)) + // FIXME: We should propagate a syntax error exception out here. + return; + } + + insertAdjacent(where, fragment.get(), ec); +} + +void HTMLElement::insertAdjacentText(const String& where, const String& text, ExceptionCode& ec) +{ + RefPtr<Text> textNode = document()->createTextNode(text); + insertAdjacent(where, textNode.get(), ec); +} + void HTMLElement::addHTMLAlignment(MappedAttribute* attr) { // vertical alignment with respect to the current baseline of the text @@ -500,36 +586,36 @@ void HTMLElement::addHTMLAlignment(MappedAttribute* attr) int propvalign = -1; const AtomicString& alignment = attr->value(); if (equalIgnoringCase(alignment, "absmiddle")) { - propvalign = CSS_VAL_MIDDLE; + propvalign = CSSValueMiddle; } else if (equalIgnoringCase(alignment, "absbottom")) { - propvalign = CSS_VAL_BOTTOM; + propvalign = CSSValueBottom; } else if (equalIgnoringCase(alignment, "left")) { - propfloat = CSS_VAL_LEFT; - propvalign = CSS_VAL_TOP; + propfloat = CSSValueLeft; + propvalign = CSSValueTop; } else if (equalIgnoringCase(alignment, "right")) { - propfloat = CSS_VAL_RIGHT; - propvalign = CSS_VAL_TOP; + propfloat = CSSValueRight; + propvalign = CSSValueTop; } else if (equalIgnoringCase(alignment, "top")) { - propvalign = CSS_VAL_TOP; + propvalign = CSSValueTop; } else if (equalIgnoringCase(alignment, "middle")) { - propvalign = CSS_VAL__WEBKIT_BASELINE_MIDDLE; + propvalign = CSSValueWebkitBaselineMiddle; } else if (equalIgnoringCase(alignment, "center")) { - propvalign = CSS_VAL_MIDDLE; + propvalign = CSSValueMiddle; } else if (equalIgnoringCase(alignment, "bottom")) { - propvalign = CSS_VAL_BASELINE; + propvalign = CSSValueBaseline; } else if (equalIgnoringCase(alignment, "texttop")) { - propvalign = CSS_VAL_TEXT_TOP; + propvalign = CSSValueTextTop; } if ( propfloat != -1 ) - addCSSProperty( attr, CSS_PROP_FLOAT, propfloat ); + addCSSProperty( attr, CSSPropertyFloat, propfloat ); if ( propvalign != -1 ) - addCSSProperty( attr, CSS_PROP_VERTICAL_ALIGN, propvalign ); + addCSSProperty( attr, CSSPropertyVerticalAlign, propvalign ); } bool HTMLElement::isFocusable() const { - return isContentEditable() && parent() && !parent()->isContentEditable(); + return Element::isFocusable() || (isContentEditable() && parent() && !parent()->isContentEditable()); } bool HTMLElement::isContentEditable() const @@ -589,25 +675,25 @@ void HTMLElement::setContentEditable(MappedAttribute* attr) { const AtomicString& enabled = attr->value(); if (enabled.isEmpty() || equalIgnoringCase(enabled, "true")) { - addCSSProperty(attr, CSS_PROP__WEBKIT_USER_MODIFY, CSS_VAL_READ_WRITE); - addCSSProperty(attr, CSS_PROP_WORD_WRAP, CSS_VAL_BREAK_WORD); - addCSSProperty(attr, CSS_PROP__WEBKIT_NBSP_MODE, CSS_VAL_SPACE); - addCSSProperty(attr, CSS_PROP__WEBKIT_LINE_BREAK, CSS_VAL_AFTER_WHITE_SPACE); + addCSSProperty(attr, CSSPropertyWebkitUserModify, CSSValueReadWrite); + addCSSProperty(attr, CSSPropertyWordWrap, CSSValueBreakWord); + addCSSProperty(attr, CSSPropertyWebkitNbspMode, CSSValueSpace); + addCSSProperty(attr, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace); } else if (equalIgnoringCase(enabled, "false")) { - addCSSProperty(attr, CSS_PROP__WEBKIT_USER_MODIFY, CSS_VAL_READ_ONLY); - attr->decl()->removeProperty(CSS_PROP_WORD_WRAP, false); - attr->decl()->removeProperty(CSS_PROP__WEBKIT_NBSP_MODE, false); - attr->decl()->removeProperty(CSS_PROP__WEBKIT_LINE_BREAK, false); + addCSSProperty(attr, CSSPropertyWebkitUserModify, CSSValueReadOnly); + attr->decl()->removeProperty(CSSPropertyWordWrap, false); + attr->decl()->removeProperty(CSSPropertyWebkitNbspMode, false); + attr->decl()->removeProperty(CSSPropertyWebkitLineBreak, false); } else if (equalIgnoringCase(enabled, "inherit")) { - addCSSProperty(attr, CSS_PROP__WEBKIT_USER_MODIFY, CSS_VAL_INHERIT); - attr->decl()->removeProperty(CSS_PROP_WORD_WRAP, false); - attr->decl()->removeProperty(CSS_PROP__WEBKIT_NBSP_MODE, false); - attr->decl()->removeProperty(CSS_PROP__WEBKIT_LINE_BREAK, false); + addCSSProperty(attr, CSSPropertyWebkitUserModify, CSSValueInherit); + attr->decl()->removeProperty(CSSPropertyWordWrap, false); + attr->decl()->removeProperty(CSSPropertyWebkitNbspMode, false); + attr->decl()->removeProperty(CSSPropertyWebkitLineBreak, false); } else if (equalIgnoringCase(enabled, "plaintext-only")) { - addCSSProperty(attr, CSS_PROP__WEBKIT_USER_MODIFY, CSS_VAL_READ_WRITE_PLAINTEXT_ONLY); - addCSSProperty(attr, CSS_PROP_WORD_WRAP, CSS_VAL_BREAK_WORD); - addCSSProperty(attr, CSS_PROP__WEBKIT_NBSP_MODE, CSS_VAL_SPACE); - addCSSProperty(attr, CSS_PROP__WEBKIT_LINE_BREAK, CSS_VAL_AFTER_WHITE_SPACE); + addCSSProperty(attr, CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly); + addCSSProperty(attr, CSSPropertyWordWrap, CSSValueBreakWord); + addCSSProperty(attr, CSSPropertyWebkitNbspMode, CSSValueSpace); + addCSSProperty(attr, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace); } } @@ -639,24 +725,6 @@ void HTMLElement::accessKeyAction(bool sendToAnyElement) dispatchSimulatedClick(0, true); } -String HTMLElement::toString() const -{ - if (!hasChildNodes() && document()->isHTMLDocument()) { - String result = openTagStartToString(); - result += ">"; - - if (endTagRequirement() == TagStatusRequired) { - result += "</"; - result += nodeName(); - result += ">"; - } - - return result; - } - - return Element::toString(); -} - String HTMLElement::id() const { return getAttribute(idAttr); @@ -707,9 +775,21 @@ void HTMLElement::setClassName(const String &value) setAttribute(classAttr, value); } +short HTMLElement::tabIndex() const +{ + if (supportsFocus()) + return Element::tabIndex(); + return -1; +} + +void HTMLElement::setTabIndex(int value) +{ + setAttribute(tabindexAttr, String::number(value)); +} + PassRefPtr<HTMLCollection> HTMLElement::children() { - return new HTMLCollection(this, HTMLCollection::NodeChildren); + return HTMLCollection::create(this, HTMLCollection::NodeChildren); } // DOM Section 1.1.1 @@ -786,6 +866,8 @@ HashSet<AtomicStringImpl*>* inlineTagList() tagList.add(basefontTag.localName().impl()); tagList.add(brTag.localName().impl()); tagList.add(scriptTag.localName().impl()); + tagList.add(styleTag.localName().impl()); + tagList.add(linkTag.localName().impl()); tagList.add(mapTag.localName().impl()); tagList.add(qTag.localName().impl()); tagList.add(subTag.localName().impl()); @@ -803,8 +885,10 @@ HashSet<AtomicStringImpl*>* inlineTagList() tagList.add(delTag.localName().impl()); tagList.add(nobrTag.localName().impl()); tagList.add(wbrTag.localName().impl()); +#if ENABLE(VIDEO) tagList.add(audioTag.localName().impl()); tagList.add(videoTag.localName().impl()); +#endif } return &tagList; } @@ -902,12 +986,6 @@ bool HTMLElement::checkDTD(const Node* newChild) return true; return inEitherTagList(newChild); } - -void HTMLElement::setHTMLEventListener(const AtomicString& eventType, Attribute* attr) -{ - Element::setHTMLEventListener(eventType, - document()->createHTMLEventListener(attr->localName().domString(), attr->value(), this)); -} bool HTMLElement::rendererIsNeeded(RenderStyle *style) { diff --git a/WebCore/html/HTMLElement.h b/WebCore/html/HTMLElement.h index 729dd91..1fba130 100644 --- a/WebCore/html/HTMLElement.h +++ b/WebCore/html/HTMLElement.h @@ -59,6 +59,8 @@ public: void setDir(const String&); String className() const; void setClassName(const String&); + virtual short tabIndex() const; + void setTabIndex(int); String innerHTML() const; String outerHTML() const; @@ -67,7 +69,11 @@ public: void setOuterHTML(const String&, ExceptionCode&); void setInnerText(const String&, ExceptionCode&); void setOuterText(const String&, ExceptionCode&); - + + Element* insertAdjacentElement(const String& where, Element* newChild, ExceptionCode&); + void insertAdjacentHTML(const String& where, const String& html, ExceptionCode&); + void insertAdjacentText(const String& where, const String& text, ExceptionCode&); + virtual bool isFocusable() const; virtual bool isContentEditable() const; virtual bool isContentRichlyEditable() const; @@ -81,8 +87,6 @@ public: virtual bool isGenericFormElement() const { return false; } - virtual String toString() const; - virtual HTMLTagStatus endTagRequirement() const; virtual int tagPriority() const; virtual bool childAllowed(Node* newChild); // Error-checking during parsing that checks the DTD @@ -94,8 +98,6 @@ public: static bool inBlockTagList(const Node*); static bool isRecognizedTagName(const QualifiedName&); - void setHTMLEventListener(const AtomicString& eventType, Attribute*); - virtual bool rendererIsNeeded(RenderStyle*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); @@ -107,8 +109,9 @@ protected: private: virtual HTMLFormElement* virtualForm() const; + Node* insertAdjacent(const String& where, Node* newChild, ExceptionCode&); }; -} //namespace +} // namespace WebCore -#endif +#endif // HTMLElement_h diff --git a/WebCore/html/HTMLElement.idl b/WebCore/html/HTMLElement.idl index 819b610..8ce5542 100644 --- a/WebCore/html/HTMLElement.idl +++ b/WebCore/html/HTMLElement.idl @@ -35,6 +35,10 @@ module html { attribute [ConvertNullToNullString] DOMString dir; attribute [ConvertNullToNullString] DOMString className; + attribute long tabIndex; + void blur(); + void focus(); + // Extensions attribute [ConvertNullToNullString] DOMString innerHTML setter raises(DOMException); @@ -45,6 +49,16 @@ module html { attribute [ConvertNullToNullString] DOMString outerText setter raises(DOMException); + Element insertAdjacentElement(in DOMString where, + in Element element) + raises(DOMException); + void insertAdjacentHTML(in DOMString where, + in DOMString html) + raises(DOMException); + void insertAdjacentText(in DOMString where, + in DOMString text) + raises(DOMException); + readonly attribute HTMLCollection children; attribute [ConvertNullToNullString] DOMString contentEditable; diff --git a/WebCore/html/HTMLElementFactory.cpp b/WebCore/html/HTMLElementFactory.cpp index e8a2bbe..1b9b0cc 100644 --- a/WebCore/html/HTMLElementFactory.cpp +++ b/WebCore/html/HTMLElementFactory.cpp @@ -113,9 +113,11 @@ static PassRefPtr<HTMLElement> baseConstructor(const AtomicString&, Document* do return new HTMLBaseElement(doc); } -static PassRefPtr<HTMLElement> linkConstructor(const AtomicString&, Document* doc, HTMLFormElement*, bool) +static PassRefPtr<HTMLElement> linkConstructor(const AtomicString&, Document* doc, HTMLFormElement*, bool createdByParser) { - return new HTMLLinkElement(doc); + RefPtr<HTMLLinkElement> link = new HTMLLinkElement(doc); + link->setCreatedByParser(createdByParser); + return link.release(); } static PassRefPtr<HTMLElement> metaConstructor(const AtomicString&, Document* doc, HTMLFormElement*, bool) @@ -135,9 +137,11 @@ static PassRefPtr<HTMLElement> titleConstructor(const AtomicString&, Document* d return new HTMLTitleElement(doc); } -static PassRefPtr<HTMLElement> frameConstructor(const AtomicString&, Document* doc, HTMLFormElement*, bool) +static PassRefPtr<HTMLElement> frameConstructor(const AtomicString&, Document* doc, HTMLFormElement*, bool createdByParser) { - return new HTMLFrameElement(doc); + RefPtr<HTMLFrameElement> frame = new HTMLFrameElement(doc); + frame->setCreatedByParser(createdByParser); + return frame.release(); } static PassRefPtr<HTMLElement> framesetConstructor(const AtomicString&, Document* doc, HTMLFormElement*, bool) @@ -145,9 +149,11 @@ static PassRefPtr<HTMLElement> framesetConstructor(const AtomicString&, Document return new HTMLFrameSetElement(doc); } -static PassRefPtr<HTMLElement> iframeConstructor(const AtomicString&, Document* doc, HTMLFormElement*, bool) +static PassRefPtr<HTMLElement> iframeConstructor(const AtomicString&, Document* doc, HTMLFormElement*, bool createdByParser) { - return new HTMLIFrameElement(doc); + RefPtr<HTMLIFrameElement> iFrame = new HTMLIFrameElement(doc); + iFrame->setCreatedByParser(createdByParser); + return iFrame.release(); } static PassRefPtr<HTMLElement> formConstructor(const AtomicString&, Document* doc, HTMLFormElement*, bool) diff --git a/WebCore/html/HTMLEmbedElement.cpp b/WebCore/html/HTMLEmbedElement.cpp index eb449fc..7ffe3b1 100644 --- a/WebCore/html/HTMLEmbedElement.cpp +++ b/WebCore/html/HTMLEmbedElement.cpp @@ -1,11 +1,9 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Stefan Schimanski (1Stein@gmx.de) - * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. - * Copyright (C) 2007 Trolltech ASA + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,24 +20,28 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "HTMLEmbedElement.h" #include "CSSHelper.h" #include "CSSPropertyNames.h" #include "Frame.h" -#include "FrameView.h" #include "HTMLDocument.h" -#include "HTMLObjectElement.h" +#include "HTMLImageLoader.h" #include "HTMLNames.h" +#include "HTMLObjectElement.h" +#include "RenderImage.h" #include "RenderPartObject.h" +#include "RenderWidget.h" +#include "ScriptController.h" namespace WebCore { using namespace HTMLNames; HTMLEmbedElement::HTMLEmbedElement(Document* doc) - : HTMLPlugInElement(embedTag, doc) + : HTMLPlugInImageElement(embedTag, doc) , m_needWidgetUpdate(false) { } @@ -48,52 +50,36 @@ HTMLEmbedElement::~HTMLEmbedElement() { #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name is removed from HTMLDocument's NameCountMap if (oldNameIdCount && document()->isHTMLDocument()) { HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - doc->removeNamedItem(oldNameAttr); + doc->removeNamedItem(m_name); } #endif - -#if USE(JAVASCRIPTCORE_BINDINGS) - // m_instance should have been cleaned up in detach(). - ASSERT(!m_instance); -#endif } -#if USE(JAVASCRIPTCORE_BINDINGS) static inline RenderWidget* findWidgetRenderer(const Node* n) { if (!n->renderer()) do n = n->parentNode(); while (n && !n->hasTagName(objectTag)); - - return (n && n->renderer() && n->renderer()->isWidget()) - ? static_cast<RenderWidget*>(n->renderer()) : 0; + + if (n && n->renderer() && n->renderer()->isWidget()) + return static_cast<RenderWidget*>(n->renderer()); + + return 0; } - -KJS::Bindings::Instance *HTMLEmbedElement::getInstance() const -{ - Frame* frame = document()->frame(); - if (!frame) - return 0; - if (m_instance) - return m_instance.get(); - +RenderWidget* HTMLEmbedElement::renderWidgetForJSBindings() const +{ RenderWidget* renderWidget = findWidgetRenderer(this); if (renderWidget && !renderWidget->widget()) { document()->updateLayoutIgnorePendingStylesheets(); renderWidget = findWidgetRenderer(this); } - - if (renderWidget && renderWidget->widget()) - m_instance = frame->createScriptInstanceForWidget(renderWidget->widget()); - - return m_instance.get(); + return renderWidget; } -#endif bool HTMLEmbedElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const { @@ -107,42 +93,54 @@ bool HTMLEmbedElement::mapToEntry(const QualifiedName& attrName, MappedAttribute void HTMLEmbedElement::parseMappedAttribute(MappedAttribute* attr) { - String val = attr->value(); + const AtomicString& value = attr->value(); if (attr->name() == typeAttr) { - m_serviceType = val.lower(); + m_serviceType = value.string().lower(); int pos = m_serviceType.find(";"); if (pos != -1) m_serviceType = m_serviceType.left(pos); - } else if (attr->name() == codeAttr || attr->name() == srcAttr) - url = parseURL(val).deprecatedString(); - else if (attr->name() == pluginpageAttr || attr->name() == pluginspageAttr) - m_pluginPage = val; + if (!isImageType() && m_imageLoader) + m_imageLoader.clear(); + } else if (attr->name() == codeAttr) + m_url = parseURL(value.string()); + else if (attr->name() == srcAttr) { + m_url = parseURL(value.string()); + if (renderer() && isImageType()) { + if (!m_imageLoader) + m_imageLoader.set(new HTMLImageLoader(this)); + m_imageLoader->updateFromElement(); + } + } else if (attr->name() == pluginpageAttr || attr->name() == pluginspageAttr) + m_pluginPage = value; else if (attr->name() == hiddenAttr) { - if (val.lower() == "yes" || val.lower() == "true") { - // FIXME: Not dynamic, but it's not really important that such a rarely-used - // feature work dynamically. - addCSSLength(attr, CSS_PROP_WIDTH, "0"); - addCSSLength(attr, CSS_PROP_HEIGHT, "0"); + if (equalIgnoringCase(value.string(), "yes") || equalIgnoringCase(value.string(), "true")) { + // FIXME: Not dynamic, since we add this but don't remove it, but it may be OK for now + // that this rarely-used attribute won't work properly if you remove it. + addCSSLength(attr, CSSPropertyWidth, "0"); + addCSSLength(attr, CSSPropertyHeight, "0"); } } else if (attr->name() == nameAttr) { if (inDocument() && document()->isHTMLDocument()) { - HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - doc->removeNamedItem(oldNameAttr); - doc->addNamedItem(val); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeNamedItem(m_name); + document->addNamedItem(value); } - oldNameAttr = val; + m_name = value; } else HTMLPlugInElement::parseMappedAttribute(attr); } -bool HTMLEmbedElement::rendererIsNeeded(RenderStyle *style) +bool HTMLEmbedElement::rendererIsNeeded(RenderStyle* style) { - Frame *frame = document()->frame(); + if (isImageType()) + return HTMLPlugInElement::rendererIsNeeded(style); + + Frame* frame = document()->frame(); if (!frame) return false; - Node *p = parentNode(); + Node* p = parentNode(); if (p && p->hasTagName(objectTag)) { ASSERT(p->renderer()); return false; @@ -151,43 +149,51 @@ bool HTMLEmbedElement::rendererIsNeeded(RenderStyle *style) return true; } -RenderObject *HTMLEmbedElement::createRenderer(RenderArena *arena, RenderStyle *style) +RenderObject* HTMLEmbedElement::createRenderer(RenderArena* arena, RenderStyle* style) { + if (isImageType()) + return new (arena) RenderImage(this); return new (arena) RenderPartObject(this); } void HTMLEmbedElement::attach() { m_needWidgetUpdate = true; - queuePostAttachCallback(&HTMLPlugInElement::updateWidgetCallback, this); + + bool isImage = isImageType(); + + if (!isImage) + queuePostAttachCallback(&HTMLPlugInElement::updateWidgetCallback, this); + HTMLPlugInElement::attach(); -} -void HTMLEmbedElement::detach() -{ -#if USE(JAVASCRIPTCORE_BINDINGS) - m_instance = 0; -#endif - HTMLPlugInElement::detach(); + if (isImage && renderer()) { + if (!m_imageLoader) + m_imageLoader.set(new HTMLImageLoader(this)); + m_imageLoader->updateFromElement(); + + if (renderer()) + static_cast<RenderImage*>(renderer())->setCachedImage(m_imageLoader->image()); + } } void HTMLEmbedElement::updateWidget() { - if (m_needWidgetUpdate && renderer()) + document()->updateRendering(); + if (m_needWidgetUpdate && renderer() && !isImageType()) static_cast<RenderPartObject*>(renderer())->updateWidget(true); } void HTMLEmbedElement::insertedIntoDocument() { - if (document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->addNamedItem(oldNameAttr); + if (document()->isHTMLDocument()) + static_cast<HTMLDocument*>(document())->addNamedItem(m_name); #ifdef ANDROID_FIX - // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 + // ensure that m_name is removed from HTMLDocument's NameCountMap + if (document()->isHTMLDocument()) oldNameIdCount++; #endif - } String width = getAttribute(widthAttr); String height = getAttribute(heightAttr); @@ -208,15 +214,14 @@ void HTMLEmbedElement::insertedIntoDocument() void HTMLEmbedElement::removedFromDocument() { - if (document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->removeNamedItem(oldNameAttr); + if (document()->isHTMLDocument()) + static_cast<HTMLDocument*>(document())->removeNamedItem(m_name); #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name is removed from HTMLDocument's NameCountMap + if (document()->isHTMLDocument()) oldNameIdCount--; #endif - } HTMLPlugInElement::removedFromDocument(); } @@ -234,11 +239,16 @@ void HTMLEmbedElement::attributeChanged(Attribute* attr, bool preserveDecls) } } -bool HTMLEmbedElement::isURLAttribute(Attribute *attr) const +bool HTMLEmbedElement::isURLAttribute(Attribute* attr) const { return attr->name() == srcAttr; } +const QualifiedName& HTMLEmbedElement::imageSourceAttributeName() const +{ + return srcAttr; +} + String HTMLEmbedElement::src() const { return getAttribute(srcAttr); @@ -259,4 +269,9 @@ void HTMLEmbedElement::setType(const String& value) setAttribute(typeAttr, value); } +void HTMLEmbedElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + urls.append(src()); +} + } diff --git a/WebCore/html/HTMLEmbedElement.h b/WebCore/html/HTMLEmbedElement.h index 8645489..2f45998 100644 --- a/WebCore/html/HTMLEmbedElement.h +++ b/WebCore/html/HTMLEmbedElement.h @@ -1,9 +1,7 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2006 Apple Computer, Inc. + * Copyright (C) 2004, 2006, 2008 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,15 +23,11 @@ #ifndef HTMLEmbedElement_h #define HTMLEmbedElement_h -#include "HTMLPlugInElement.h" - -#if USE(JAVASCRIPTCORE_BINDINGS) -#include <bindings/runtime.h> -#endif +#include "HTMLPlugInImageElement.h" namespace WebCore { -class HTMLEmbedElement : public HTMLPlugInElement { +class HTMLEmbedElement : public HTMLPlugInImageElement { public: HTMLEmbedElement(Document*); ~HTMLEmbedElement(); @@ -45,7 +39,7 @@ public: virtual void parseMappedAttribute(MappedAttribute*); virtual void attach(); - virtual void detach(); + virtual bool canLazyAttach() { return false; } virtual bool rendererIsNeeded(RenderStyle*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); virtual void insertedIntoDocument(); @@ -53,13 +47,12 @@ public: virtual void attributeChanged(Attribute*, bool preserveDecls = false); virtual bool isURLAttribute(Attribute*) const; + virtual const QualifiedName& imageSourceAttributeName() const; virtual void updateWidget(); void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; } -#if USE(JAVASCRIPTCORE_BINDINGS) - virtual KJS::Bindings::Instance* getInstance() const; -#endif + virtual RenderWidget* renderWidgetForJSBindings() const; String src() const; void setSrc(const String&); @@ -67,9 +60,10 @@ public: String type() const; void setType(const String&); - DeprecatedString url; + virtual void getSubresourceAttributeStrings(Vector<String>&) const; + +private: String m_pluginPage; - String m_serviceType; bool m_needWidgetUpdate; }; diff --git a/WebCore/html/HTMLFieldSetElement.cpp b/WebCore/html/HTMLFieldSetElement.cpp index 00ae7fa..c4594de 100644 --- a/WebCore/html/HTMLFieldSetElement.cpp +++ b/WebCore/html/HTMLFieldSetElement.cpp @@ -35,7 +35,7 @@ namespace WebCore { using namespace HTMLNames; HTMLFieldSetElement::HTMLFieldSetElement(Document *doc, HTMLFormElement *f) - : HTMLGenericFormElement(fieldsetTag, doc, f) + : HTMLFormControlElement(fieldsetTag, doc, f) { } @@ -50,7 +50,7 @@ bool HTMLFieldSetElement::checkDTD(const Node* newChild) bool HTMLFieldSetElement::isFocusable() const { - return false; + return HTMLElement::isFocusable(); } const AtomicString& HTMLFieldSetElement::type() const diff --git a/WebCore/html/HTMLFieldSetElement.h b/WebCore/html/HTMLFieldSetElement.h index 645b173..637a2ff 100644 --- a/WebCore/html/HTMLFieldSetElement.h +++ b/WebCore/html/HTMLFieldSetElement.h @@ -26,7 +26,7 @@ #ifndef HTMLFieldSetElement_h #define HTMLFieldSetElement_h -#include "HTMLGenericFormElement.h" +#include "HTMLFormControlElement.h" namespace WebCore { class RenderStyle; @@ -38,7 +38,7 @@ class HTMLFormElement; class Document; class Node; -class HTMLFieldSetElement : public HTMLGenericFormElement { +class HTMLFieldSetElement : public HTMLFormControlElement { public: HTMLFieldSetElement(Document*, HTMLFormElement* = 0); virtual ~HTMLFieldSetElement(); @@ -49,6 +49,8 @@ public: virtual bool isFocusable() const; virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); virtual const AtomicString& type() const; + + virtual bool willValidate() const { return false; } }; } //namespace diff --git a/WebCore/html/HTMLFieldSetElement.idl b/WebCore/html/HTMLFieldSetElement.idl index 80f8e8e..c48f8d6 100644 --- a/WebCore/html/HTMLFieldSetElement.idl +++ b/WebCore/html/HTMLFieldSetElement.idl @@ -25,6 +25,7 @@ module html { ImplementationUUID=93573758-96db-415d-9bdc-ee7238604094 ] HTMLFieldSetElement : HTMLElement { readonly attribute HTMLFormElement form; + readonly attribute boolean willValidate; }; } diff --git a/WebCore/html/HTMLFontElement.cpp b/WebCore/html/HTMLFontElement.cpp index c776f15..b32f492 100644 --- a/WebCore/html/HTMLFontElement.cpp +++ b/WebCore/html/HTMLFontElement.cpp @@ -1,10 +1,8 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Simon Hausmann <hausmann@kde.org> - * Copyright (C) 2003, 2006 Apple Computer, Inc. + * Copyright (C) 2003, 2006, 2008 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 @@ -35,12 +33,8 @@ namespace WebCore { using namespace HTMLNames; -HTMLFontElement::HTMLFontElement(Document* doc) - : HTMLElement(fontTag, doc) -{ -} - -HTMLFontElement::~HTMLFontElement() +HTMLFontElement::HTMLFontElement(Document* document) + : HTMLElement(fontTag, document) { } @@ -67,12 +61,12 @@ static bool parseFontSizeNumber(const String& s, int& size) } // Parse a single digit. - if (!Unicode::isDigit(s[pos])) + if (!isASCIIDigit(s[pos])) return false; - int num = Unicode::digitValue(s[pos++]); + int num = s[pos++] - '0'; // Check for an additional digit. - if (Unicode::isDigit(s[pos])) + if (isASCIIDigit(s[pos])) num = 10; if (sawPlus) { @@ -110,26 +104,26 @@ bool HTMLFontElement::cssValueFromFontSizeNumber(const String& s, int& size) switch (num) { case 2: - size = CSS_VAL_SMALL; + size = CSSValueSmall; break; case 0: // treat 0 the same as 3, because people expect it to be between -1 and +1 case 3: - size = CSS_VAL_MEDIUM; + size = CSSValueMedium; break; case 4: - size = CSS_VAL_LARGE; + size = CSSValueLarge; break; case 5: - size = CSS_VAL_X_LARGE; + size = CSSValueXLarge; break; case 6: - size = CSS_VAL_XX_LARGE; + size = CSSValueXxLarge; break; default: if (num > 6) - size = CSS_VAL__WEBKIT_XXX_LARGE; + size = CSSValueWebkitXxxLarge; else - size = CSS_VAL_X_SMALL; + size = CSSValueXSmall; } return true; } @@ -139,11 +133,11 @@ void HTMLFontElement::parseMappedAttribute(MappedAttribute *attr) if (attr->name() == sizeAttr) { int size; if (cssValueFromFontSizeNumber(attr->value(), size)) - addCSSProperty(attr, CSS_PROP_FONT_SIZE, size); + addCSSProperty(attr, CSSPropertyFontSize, size); } else if (attr->name() == colorAttr) { - addCSSColor(attr, CSS_PROP_COLOR, attr->value()); + addCSSColor(attr, CSSPropertyColor, attr->value()); } else if (attr->name() == faceAttr) { - addCSSProperty(attr, CSS_PROP_FONT_FAMILY, attr->value()); + addCSSProperty(attr, CSSPropertyFontFamily, attr->value()); } else HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLFontElement.h b/WebCore/html/HTMLFontElement.h index fd889f7..272f63c 100644 --- a/WebCore/html/HTMLFontElement.h +++ b/WebCore/html/HTMLFontElement.h @@ -1,6 +1,4 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Simon Hausmann <hausmann@kde.org> @@ -28,13 +26,9 @@ namespace WebCore { -class String; - -class HTMLFontElement : public HTMLElement -{ +class HTMLFontElement : public HTMLElement { public: HTMLFontElement(Document*); - ~HTMLFontElement(); virtual HTMLTagStatus endTagRequirement() const { return TagStatusRequired; } virtual int tagPriority() const { return 1; } diff --git a/WebCore/html/HTMLFormCollection.cpp b/WebCore/html/HTMLFormCollection.cpp index fa69710..823291a 100644 --- a/WebCore/html/HTMLFormCollection.cpp +++ b/WebCore/html/HTMLFormCollection.cpp @@ -23,7 +23,7 @@ #include "config.h" #include "HTMLFormCollection.h" -#include "HTMLGenericFormElement.h" +#include "HTMLFormControlElement.h" #include "HTMLFormElement.h" #include "HTMLImageElement.h" #include "HTMLNames.h" @@ -47,6 +47,11 @@ HTMLFormCollection::HTMLFormCollection(PassRefPtr<HTMLFormElement> form) { } +PassRefPtr<HTMLFormCollection> HTMLFormCollection::create(PassRefPtr<HTMLFormElement> form) +{ + return adoptRef(new HTMLFormCollection(form)); +} + HTMLFormCollection::~HTMLFormCollection() { } @@ -72,7 +77,7 @@ Node* HTMLFormCollection::item(unsigned index) const info()->elementsArrayPosition = 0; } - Vector<HTMLGenericFormElement*>& l = static_cast<HTMLFormElement*>(base())->formElements; + Vector<HTMLFormControlElement*>& l = static_cast<HTMLFormElement*>(base())->formElements; unsigned currentIndex = info()->position; for (unsigned i = info()->elementsArrayPosition; i < l.size(); i++) { @@ -103,13 +108,13 @@ Element* HTMLFormCollection::getNamedFormItem(const QualifiedName& attrName, con bool foundInputElements = false; for (unsigned i = 0; i < form->formElements.size(); ++i) { - HTMLGenericFormElement* e = form->formElements[i]; + HTMLFormControlElement* e = form->formElements[i]; if (e->isEnumeratable()) { bool found; if (caseSensitive) found = e->getAttribute(attrName) == name; else - found = e->getAttribute(attrName).domString().lower() == name.lower(); + found = equalIgnoringCase(e->getAttribute(attrName), name); if (found) { foundInputElements = true; if (!duplicateNumber) @@ -126,7 +131,7 @@ Element* HTMLFormCollection::getNamedFormItem(const QualifiedName& attrName, con if (caseSensitive) found = e->getAttribute(attrName) == name; else - found = e->getAttribute(attrName).domString().lower() == name.lower(); + found = equalIgnoringCase(e->getAttribute(attrName), name); if (found) { if (!duplicateNumber) return e; @@ -195,7 +200,7 @@ void HTMLFormCollection::updateNameCache() const HTMLFormElement* f = static_cast<HTMLFormElement*>(base()); for (unsigned i = 0; i < f->formElements.size(); ++i) { - HTMLGenericFormElement* e = f->formElements[i]; + HTMLFormControlElement* e = f->formElements[i]; if (e->isEnumeratable()) { const AtomicString& idAttrVal = e->getAttribute(idAttr); const AtomicString& nameAttrVal = e->getAttribute(nameAttr); diff --git a/WebCore/html/HTMLFormCollection.h b/WebCore/html/HTMLFormCollection.h index ae2fb11..b81138f 100644 --- a/WebCore/html/HTMLFormCollection.h +++ b/WebCore/html/HTMLFormCollection.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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 @@ -35,8 +35,9 @@ class QualifiedName; class HTMLFormCollection : public HTMLCollection { public: - HTMLFormCollection(PassRefPtr<HTMLFormElement>); - ~HTMLFormCollection(); + static PassRefPtr<HTMLFormCollection> create(PassRefPtr<HTMLFormElement>); + + virtual ~HTMLFormCollection(); virtual Node* item(unsigned index) const; virtual Node* nextItem() const; @@ -45,6 +46,8 @@ public: virtual Node* nextNamedItem(const String& name) const; private: + HTMLFormCollection(PassRefPtr<HTMLFormElement>); + virtual void updateNameCache() const; virtual unsigned calcLength() const; diff --git a/WebCore/html/HTMLGenericFormElement.cpp b/WebCore/html/HTMLFormControlElement.cpp index 2eab0a8..8e879fd 100644 --- a/WebCore/html/HTMLGenericFormElement.cpp +++ b/WebCore/html/HTMLFormControlElement.cpp @@ -23,7 +23,7 @@ */ #include "config.h" -#include "HTMLGenericFormElement.h" +#include "HTMLFormControlElement.h" #include "Document.h" #include "EventHandler.h" @@ -37,16 +37,11 @@ #include "RenderTheme.h" #include "Tokenizer.h" -#if USE(LOW_BANDWIDTH_DISPLAY) -#include "FrameLoader.h" -#endif - namespace WebCore { -using namespace EventNames; using namespace HTMLNames; -HTMLGenericFormElement::HTMLGenericFormElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f) +HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f) : HTMLElement(tagName, doc) , m_form(f) , m_disabled(false) @@ -59,13 +54,13 @@ HTMLGenericFormElement::HTMLGenericFormElement(const QualifiedName& tagName, Doc m_form->registerFormElement(this); } -HTMLGenericFormElement::~HTMLGenericFormElement() +HTMLFormControlElement::~HTMLFormControlElement() { if (m_form) m_form->removeFormElement(this); } -void HTMLGenericFormElement::parseMappedAttribute(MappedAttribute *attr) +void HTMLFormControlElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == nameAttr) { // Do nothing. @@ -89,7 +84,7 @@ void HTMLGenericFormElement::parseMappedAttribute(MappedAttribute *attr) HTMLElement::parseMappedAttribute(attr); } -void HTMLGenericFormElement::attach() +void HTMLFormControlElement::attach() { ASSERT(!attached()); @@ -100,9 +95,17 @@ void HTMLGenericFormElement::attach() // on the renderer. if (renderer()) renderer()->updateFromElement(); + + // 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. + if (autofocus() && renderer() && !document()->ignoreAutofocus() && !isReadOnlyControl() && + ((hasTagName(inputTag) && !isInputTypeHidden()) || hasTagName(selectTag) || + hasTagName(buttonTag) || hasTagName(textareaTag))) + focus(); } -void HTMLGenericFormElement::insertedIntoTree(bool deep) +void HTMLFormControlElement::insertedIntoTree(bool deep) { if (!m_form) { // This handles the case of a new form element being created by @@ -127,7 +130,7 @@ static inline Node* findRoot(Node* n) return root; } -void HTMLGenericFormElement::removedFromTree(bool deep) +void HTMLFormControlElement::removedFromTree(bool deep) { // If the form and element are both in the same tree, preserve the connection to the form. // Otherwise, null out our form and remove ourselves from the form's list of elements. @@ -144,38 +147,48 @@ void HTMLGenericFormElement::removedFromTree(bool deep) HTMLElement::removedFromTree(deep); } -const AtomicString& HTMLGenericFormElement::name() const +const AtomicString& HTMLFormControlElement::name() const { const AtomicString& n = getAttribute(nameAttr); return n.isNull() ? emptyAtom : n; } -void HTMLGenericFormElement::setName(const AtomicString &value) +void HTMLFormControlElement::setName(const AtomicString &value) { setAttribute(nameAttr, value); } -void HTMLGenericFormElement::onChange() +void HTMLFormControlElement::onChange() { - dispatchHTMLEvent(changeEvent, true, false); + dispatchEventForType(eventNames().changeEvent, true, false); } -bool HTMLGenericFormElement::disabled() const +bool HTMLFormControlElement::disabled() const { return m_disabled; } -void HTMLGenericFormElement::setDisabled(bool b) +void HTMLFormControlElement::setDisabled(bool b) { setAttribute(disabledAttr, b ? "" : 0); } -void HTMLGenericFormElement::setReadOnly(bool b) +void HTMLFormControlElement::setReadOnly(bool b) { setAttribute(readonlyAttr, b ? "" : 0); } -void HTMLGenericFormElement::recalcStyle(StyleChange change) +bool HTMLFormControlElement::autofocus() const +{ + return hasAttribute(autofocusAttr); +} + +void HTMLFormControlElement::setAutofocus(bool b) +{ + setAttribute(autofocusAttr, b ? "autofocus" : 0); +} + +void HTMLFormControlElement::recalcStyle(StyleChange change) { HTMLElement::recalcStyle(change); @@ -183,7 +196,7 @@ void HTMLGenericFormElement::recalcStyle(StyleChange change) renderer()->updateFromElement(); } -bool HTMLGenericFormElement::isFocusable() const +bool HTMLFormControlElement::isFocusable() const { if (disabled() || !renderer() || (renderer()->style() && renderer()->style()->visibility() != VISIBLE) || @@ -192,7 +205,7 @@ bool HTMLGenericFormElement::isFocusable() const return true; } -bool HTMLGenericFormElement::isKeyboardFocusable(KeyboardEvent* event) const +bool HTMLFormControlElement::isKeyboardFocusable(KeyboardEvent* event) const { if (isFocusable()) if (document()->frame()) @@ -200,27 +213,41 @@ bool HTMLGenericFormElement::isKeyboardFocusable(KeyboardEvent* event) const return false; } -bool HTMLGenericFormElement::isMouseFocusable() const +bool HTMLFormControlElement::isMouseFocusable() const { +#if PLATFORM(GTK) + return HTMLElement::isMouseFocusable(); +#else return false; +#endif } -void HTMLGenericFormElement::setTabIndex(int value) +short HTMLFormControlElement::tabIndex() const { - setAttribute(tabindexAttr, String::number(value)); + // Skip the supportsFocus check in HTMLElement. + return Element::tabIndex(); +} + +bool HTMLFormControlElement::willValidate() const +{ + // FIXME: Implementation shall be completed with these checks: + // The control does not have a repetition template as an ancestor. + // The control does not have a datalist element as an ancestor. + // The control is not an output element. + return form() && name().length() && !disabled() && !isReadOnlyControl(); } -bool HTMLGenericFormElement::supportsFocus() const +bool HTMLFormControlElement::supportsFocus() const { return isFocusable() || (!disabled() && !document()->haveStylesheetsLoaded()); } -HTMLFormElement* HTMLGenericFormElement::virtualForm() const +HTMLFormElement* HTMLFormControlElement::virtualForm() const { return m_form; } -void HTMLGenericFormElement::removeFromForm() +void HTMLFormControlElement::removeFromForm() { if (!m_form) return; @@ -229,7 +256,7 @@ void HTMLGenericFormElement::removeFromForm() } HTMLFormControlElementWithState::HTMLFormControlElementWithState(const QualifiedName& tagName, Document* doc, HTMLFormElement* f) - : HTMLGenericFormElement(tagName, doc, f) + : HTMLFormControlElement(tagName, doc, f) { doc->registerFormElementWithState(this); } @@ -242,18 +269,18 @@ HTMLFormControlElementWithState::~HTMLFormControlElementWithState() void HTMLFormControlElementWithState::willMoveToNewOwnerDocument() { document()->unregisterFormElementWithState(this); - HTMLGenericFormElement::willMoveToNewOwnerDocument(); + HTMLFormControlElement::willMoveToNewOwnerDocument(); } void HTMLFormControlElementWithState::didMoveToNewOwnerDocument() { document()->registerFormElementWithState(this); - HTMLGenericFormElement::didMoveToNewOwnerDocument(); + HTMLFormControlElement::didMoveToNewOwnerDocument(); } void HTMLFormControlElementWithState::finishParsingChildren() { - HTMLGenericFormElement::finishParsingChildren(); + HTMLFormControlElement::finishParsingChildren(); Document* doc = document(); if (doc->hasStateForNewFormElements()) { String state; @@ -262,15 +289,4 @@ void HTMLFormControlElementWithState::finishParsingChildren() } } -#if USE(LOW_BANDWIDTH_DISPLAY) -bool HTMLGenericFormElement::rendererIsNeeded(RenderStyle* style) -{ - if (document()->inLowBandwidthDisplay()) { - document()->frame()->loader()->needToSwitchOutLowBandwidthDisplay(); - return false; - } - return HTMLElement::rendererIsNeeded(style); -} -#endif - } // namespace Webcore diff --git a/WebCore/html/HTMLGenericFormElement.h b/WebCore/html/HTMLFormControlElement.h index ec18aa9..0978a90 100644 --- a/WebCore/html/HTMLGenericFormElement.h +++ b/WebCore/html/HTMLFormControlElement.h @@ -21,8 +21,8 @@ * */ -#ifndef HTMLGenericFormElement_h -#define HTMLGenericFormElement_h +#ifndef HTMLFormControlElement_h +#define HTMLFormControlElement_h #include "HTMLElement.h" @@ -31,11 +31,10 @@ namespace WebCore { class FormDataList; class HTMLFormElement; -// FIXME: Rename this class to HTMLFormControlElement. -class HTMLGenericFormElement : public HTMLElement { +class HTMLFormControlElement : public HTMLElement { public: - HTMLGenericFormElement(const QualifiedName& tagName, Document*, HTMLFormElement*); - virtual ~HTMLGenericFormElement(); + HTMLFormControlElement(const QualifiedName& tagName, Document*, HTMLFormElement*); + virtual ~HTMLFormControlElement(); virtual HTMLTagStatus endTagRequirement() const { return TagStatusRequired; } virtual int tagPriority() const { return 1; } @@ -71,6 +70,10 @@ public: virtual bool isReadOnlyControl() const { return m_readOnly; } void setReadOnly(bool); + // Determines whether or not a control will be automatically focused + virtual bool autofocus() const; + void setAutofocus(bool); + virtual void recalcStyle(StyleChange); virtual const AtomicString& name() const; @@ -88,11 +91,9 @@ public: virtual bool isActivatedSubmit() const { return false; } virtual void setActivatedSubmit(bool flag) { } -#if USE(LOW_BANDWIDTH_DISPLAY) - virtual bool rendererIsNeeded(RenderStyle*); -#endif + virtual short tabIndex() const; - void setTabIndex(int); + virtual bool willValidate() const; void formDestroyed() { m_form = 0; } @@ -108,7 +109,7 @@ private: mutable bool m_valueMatchesRenderer; }; -class HTMLFormControlElementWithState : public HTMLGenericFormElement { +class HTMLFormControlElementWithState : public HTMLFormControlElement { public: HTMLFormControlElementWithState(const QualifiedName& tagName, Document*, HTMLFormElement*); virtual ~HTMLFormControlElementWithState(); diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp index 267c3bf..28ea290 100644 --- a/WebCore/html/HTMLFormElement.cpp +++ b/WebCore/html/HTMLFormElement.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, 2008 Apple Inc. All rights reserved. * (C) 2006 Alexey Proskuryakov (ap@nypop.com) * * This library is free software; you can redistribute it and/or @@ -25,11 +25,13 @@ #include "config.h" #include "HTMLFormElement.h" -#include "Base64.h" #include "CSSHelper.h" -#include "CString.h" +#include "ChromeClient.h" +#include "Document.h" #include "Event.h" #include "EventNames.h" +#include "FileList.h" +#include "FileSystem.h" #include "FormData.h" #include "FormDataList.h" #include "Frame.h" @@ -40,6 +42,7 @@ #include "HTMLInputElement.h" #include "HTMLNames.h" #include "MIMETypeRegistry.h" +#include "Page.h" #include "RenderTextControl.h" #if PLATFORM(QT) @@ -57,9 +60,10 @@ namespace WebCore { -using namespace EventNames; using namespace HTMLNames; +static const char hexDigits[17] = "0123456789ABCDEF"; + HTMLFormElement::HTMLFormElement(Document* doc) : HTMLElement(formTag, doc) , m_elementAliases(0) @@ -74,7 +78,7 @@ HTMLFormElement::HTMLFormElement(Document* doc) , m_malformed(false) #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr is removed from HTMLDocument's NameCountMap + // ensure that m_name is removed from HTMLDocument's NameCountMap , oldNameCount(0) #endif { @@ -84,27 +88,27 @@ HTMLFormElement::~HTMLFormElement() { #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr is removed from HTMLDocument's NameCountMap + // ensure that m_name is removed from HTMLDocument's NameCountMap if (oldNameCount && document()->isHTMLDocument()) { HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - doc->removeNamedItem(oldNameAttr); + doc->removeNamedItem(m_name); } #endif + if (!m_autocomplete) + document()->unregisterForDocumentActivationCallbacks(this); + delete m_elementAliases; delete collectionInfo; - + for (unsigned i = 0; i < formElements.size(); ++i) formElements[i]->formDestroyed(); for (unsigned i = 0; i < imgElements.size(); ++i) imgElements[i]->m_form = 0; } -bool HTMLFormElement::formWouldHaveSecureSubmission(const String &url) +bool HTMLFormElement::formWouldHaveSecureSubmission(const String& url) { - if (url.isNull()) { - return false; - } - return document()->completeURL(url.deprecatedString()).startsWith("https:", false); + return document()->completeURL(url).protocolIs("https"); } void HTMLFormElement::attach() @@ -114,30 +118,28 @@ void HTMLFormElement::attach() void HTMLFormElement::insertedIntoDocument() { - if (document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->addNamedItem(oldNameAttr); + if (document()->isHTMLDocument()) + static_cast<HTMLDocument*>(document())->addNamedItem(m_name); #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr is removed from HTMLDocument's NameCountMap + // ensure that m_name is removed from HTMLDocument's NameCountMap + if (document()->isHTMLDocument()) oldNameCount++; #endif - } HTMLElement::insertedIntoDocument(); } void HTMLFormElement::removedFromDocument() { - if (document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->removeNamedItem(oldNameAttr); + if (document()->isHTMLDocument()) + static_cast<HTMLDocument*>(document())->removeNamedItem(m_name); #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr is removed from HTMLDocument's NameCountMap + // ensure that m_name is removed from HTMLDocument's NameCountMap + if (document()->isHTMLDocument()) oldNameCount--; #endif - } HTMLElement::removedFromDocument(); } @@ -145,7 +147,7 @@ void HTMLFormElement::removedFromDocument() void HTMLFormElement::handleLocalEvents(Event* event, bool useCapture) { EventTargetNode* targetNode = event->target()->toNode(); - if (!useCapture && targetNode && targetNode != this && (event->type() == submitEvent || event->type() == resetEvent)) { + if (!useCapture && targetNode && targetNode != this && (event->type() == eventNames().submitEvent || event->type() == eventNames().resetEvent)) { event->stopPropagation(); return; } @@ -172,7 +174,7 @@ void HTMLFormElement::submitClick(Event* event) bool submitFound = false; for (unsigned i = 0; i < formElements.size(); ++i) { if (formElements[i]->hasLocalName(inputTag)) { - HTMLInputElement *element = static_cast<HTMLInputElement *>(formElements[i]); + HTMLInputElement* element = static_cast<HTMLInputElement*>(formElements[i]); if (element->isSuccessfulSubmitButton() && element->renderer()) { submitFound = true; element->dispatchSimulatedClick(event); @@ -184,48 +186,40 @@ void HTMLFormElement::submitClick(Event* event) prepareSubmit(event); } -static DeprecatedCString encodeCString(const CString& cstr) +static void appendString(Vector<char>& buffer, const char* string) { - DeprecatedCString e = cstr.deprecatedCString(); + buffer.append(string, strlen(string)); +} - // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1 - // same safe characters as Netscape for compatibility - static const char *safe = "-._*"; - int elen = e.length(); - DeprecatedCString encoded((elen + e.contains('\n')) * 3 + 1); - int enclen = 0; +static void appendString(Vector<char>& buffer, const CString& string) +{ + buffer.append(string.data(), string.length()); +} - for (int pos = 0; pos < elen; pos++) { - unsigned char c = e[pos]; +static void appendEncodedString(Vector<char>& buffer, const CString& string) +{ + // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1 + int length = string.length(); + for (int i = 0; i < length; i++) { + unsigned char c = string.data()[i]; + // Same safe characters as Netscape for compatibility. + static const char safe[] = "-._*"; if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || strchr(safe, c)) - encoded[enclen++] = c; + buffer.append(c); else if (c == ' ') - encoded[enclen++] = '+'; - else if (c == '\n' || (c == '\r' && e[pos + 1] != '\n')) { - encoded[enclen++] = '%'; - encoded[enclen++] = '0'; - encoded[enclen++] = 'D'; - encoded[enclen++] = '%'; - encoded[enclen++] = '0'; - encoded[enclen++] = 'A'; - } else if (c != '\r') { - encoded[enclen++] = '%'; - unsigned int h = c / 16; - h += (h > 9) ? ('A' - 10) : '0'; - encoded[enclen++] = h; - - unsigned int l = c % 16; - l += (l > 9) ? ('A' - 10) : '0'; - encoded[enclen++] = l; + buffer.append('+'); + else if (c == '\n' || (c == '\r' && (i + 1 >= length || string.data()[i + 1] != '\n'))) + appendString(buffer, "%0D%0A"); + else if (c != '\r') { + buffer.append('%'); + buffer.append(hexDigits[c >> 4]); + buffer.append(hexDigits[c & 0xF]); } } - encoded[enclen++] = '\0'; - encoded.truncate(enclen); - - return encoded; } +// FIXME: Move to platform directory? static int randomNumber() { static bool randomSeeded = false; @@ -245,22 +239,6 @@ static int randomNumber() #endif } -// Warning: this helper doesn't currently have a reliable cross-platform behavior in certain edge cases -// (see basename(3) specification for examples). -// Consider this if it ever needs to become a general purpose method. -static String pathGetFilename(String path) -{ -#if PLATFORM(QT) - return QFileInfo(path).fileName(); -#elif PLATFORM(WX) - return wxFileName(path).GetFullName(); -#elif PLATFORM(WIN_OS) - return String(PathFindFileName(path.charactersWithNullTermination())); -#else - return path.substring(path.reverseFind('/') + 1); -#endif -} - TextEncoding HTMLFormElement::dataEncoding() const { if (isMailtoForm()) @@ -269,7 +247,8 @@ TextEncoding HTMLFormElement::dataEncoding() const TextEncoding encoding; String str = m_acceptcharset; str.replace(',', ' '); - Vector<String> charsets = str.split(' '); + Vector<String> charsets; + str.split(' ', charsets); Vector<String>::const_iterator end = charsets.end(); for (Vector<String>::const_iterator it = charsets.begin(); it != end; ++it) if ((encoding = TextEncoding(*it)).isValid()) @@ -281,80 +260,89 @@ TextEncoding HTMLFormElement::dataEncoding() const PassRefPtr<FormData> HTMLFormElement::formData(const char* boundary) const { - DeprecatedCString enc_string = ""; + Vector<char> encodedData; TextEncoding encoding = dataEncoding(); - RefPtr<FormData> result = new FormData; + RefPtr<FormData> result = FormData::create(); for (unsigned i = 0; i < formElements.size(); ++i) { - HTMLGenericFormElement* current = formElements[i]; - FormDataList lst(encoding); - - if (!current->disabled() && current->appendFormData(lst, m_multipart)) { - size_t ln = lst.list().size(); - for (size_t j = 0; j < ln; ++j) { - const FormDataListItem& item = lst.list()[j]; + HTMLFormControlElement* control = formElements[i]; + FormDataList list(encoding); + + if (!control->disabled() && control->appendFormData(list, m_multipart)) { + size_t formDataListSize = list.list().size(); + ASSERT(formDataListSize % 2 == 0); + for (size_t j = 0; j < formDataListSize; j += 2) { + const FormDataList::Item& key = list.list()[j]; + const FormDataList::Item& value = list.list()[j + 1]; if (!m_multipart) { - // handle ISINDEX / <input name=isindex> special - // but only if its the first entry - if (enc_string.isEmpty() && item.m_data == "isindex") { - enc_string += encodeCString(lst.list()[j + 1].m_data); - ++j; - } else { - if (!enc_string.isEmpty()) - enc_string += '&'; - - enc_string += encodeCString(item.m_data); - enc_string += "="; - enc_string += encodeCString(lst.list()[j + 1].m_data); - ++j; + // Omit the name "isindex" if it's the first form data element. + // FIXME: Why is this a good rule? Is this obsolete now? + if (encodedData.isEmpty() && key.data() == "isindex") + appendEncodedString(encodedData, value.data()); + else { + if (!encodedData.isEmpty()) + encodedData.append('&'); + appendEncodedString(encodedData, key.data()); + encodedData.append('='); + appendEncodedString(encodedData, value.data()); } - } - else - { - DeprecatedCString hstr("--"); - hstr += boundary; - hstr += "\r\n"; - hstr += "Content-Disposition: form-data; name=\""; - hstr += item.m_data.data(); - hstr += "\""; - + } else { + Vector<char> header; + appendString(header, "--"); + appendString(header, boundary); + appendString(header, "\r\n"); + appendString(header, "Content-Disposition: form-data; name=\""); + header.append(key.data().data(), key.data().length()); + header.append('"'); + + bool shouldGenerateFile = false; // if the current type is FILE, then we also need to // include the filename - if (current->hasLocalName(inputTag) && - static_cast<HTMLInputElement*>(current)->inputType() == HTMLInputElement::FILE) { - String path = static_cast<HTMLInputElement*>(current)->value(); - String filename = pathGetFilename(path); + if (value.file()) { + const String& path = value.file()->path(); + String filename = value.file()->fileName(); + + // Let the application specify a filename if it's going to generate a replacement file for the upload. + if (!path.isEmpty()) { + if (Page* page = document()->page()) { + String generatedFilename; + shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFilename); + if (shouldGenerateFile) + filename = generatedFilename; + } + } // FIXME: This won't work if the filename includes a " mark, // or control characters like CR or LF. This also does strange // things if the filename includes characters you can't encode // in the website's character set. - hstr += "; filename=\""; - hstr += encoding.encode(reinterpret_cast<const UChar*>(filename.characters()), filename.length(), true).data(); - hstr += "\""; - - if (!static_cast<HTMLInputElement*>(current)->value().isEmpty()) { - DeprecatedString mimeType = MIMETypeRegistry::getMIMETypeForPath(path).deprecatedString(); + appendString(header, "; filename=\""); + appendString(header, encoding.encode(filename.characters(), filename.length(), QuestionMarksForUnencodables)); + header.append('"'); + + if (!filename.isEmpty()) { + // FIXME: The MIMETypeRegistry function's name makes it sound like it takes a path, + // not just a basename. But filename is not the path. But note that it's not safe to + // just use path instead since in the generated-file case it will not reflect the + // MIME type of the generated file. + String mimeType = MIMETypeRegistry::getMIMETypeForPath(filename); if (!mimeType.isEmpty()) { - hstr += "\r\nContent-Type: "; - hstr += mimeType.ascii(); + appendString(header, "\r\nContent-Type: "); + appendString(header, mimeType.latin1()); } } } - hstr += "\r\n\r\n"; + appendString(header, "\r\n\r\n"); // append body - result->appendData(hstr.data(), hstr.length()); - const FormDataListItem& item = lst.list()[j + 1]; - if (size_t dataSize = item.m_data.length()) - result->appendData(item.m_data.data(), dataSize); - else if (!item.m_path.isEmpty()) - result->appendFile(item.m_path); + result->appendData(header.data(), header.size()); + if (size_t dataSize = value.data().length()) + result->appendData(value.data().data(), dataSize); + else if (value.file() && !value.file()->path().isEmpty()) + result->appendFile(value.file()->path(), shouldGenerateFile); result->appendData("\r\n", 2); - - ++j; } } } @@ -362,12 +350,12 @@ PassRefPtr<FormData> HTMLFormElement::formData(const char* boundary) const if (m_multipart) { - enc_string = "--"; - enc_string += boundary; - enc_string += "--\r\n"; + appendString(encodedData, "--"); + appendString(encodedData, boundary); + appendString(encodedData, "--\r\n"); } - result->appendData(enc_string.data(), enc_string.length()); + result->appendData(encodedData.data(), encodedData.size()); return result; } @@ -387,7 +375,7 @@ void HTMLFormElement::parseEnctype(const String& type) bool HTMLFormElement::isMailtoForm() const { - return m_url.startsWith("mailto:", false); + return protocolIs(m_url, "mailto"); } bool HTMLFormElement::prepareSubmit(Event* event) @@ -399,7 +387,7 @@ bool HTMLFormElement::prepareSubmit(Event* event) m_insubmit = true; m_doingsubmit = false; - if (dispatchHTMLEvent(submitEvent, true, true) && !m_doingsubmit) + if (dispatchEventForType(eventNames().submitEvent, true, true) && !m_doingsubmit) m_doingsubmit = true; m_insubmit = false; @@ -467,8 +455,8 @@ static void getUniqueBoundaryString(Vector<char>& boundary) void HTMLFormElement::submit(Event* event, bool activateSubmitButton) { - FrameView *view = document()->view(); - Frame *frame = document()->frame(); + FrameView* view = document()->view(); + Frame* frame = document()->frame(); if (!view || !frame) return; @@ -479,33 +467,34 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton) m_insubmit = true; - HTMLGenericFormElement* firstSuccessfulSubmitButton = 0; + HTMLFormControlElement* firstSuccessfulSubmitButton = 0; bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button? frame->loader()->clearRecordedFormValues(); + frame->loader()->setFormAboutToBeSubmitted(this); for (unsigned i = 0; i < formElements.size(); ++i) { - HTMLGenericFormElement* current = formElements[i]; - if (current->hasLocalName(inputTag)) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(current); + HTMLFormControlElement* control = formElements[i]; + if (control->hasLocalName(inputTag)) { + HTMLInputElement* input = static_cast<HTMLInputElement*>(control); if (input->isTextField()) { - frame->loader()->recordFormValue(input->name(), input->value(), this); + frame->loader()->recordFormValue(input->name(), input->value()); if (input->isSearchField()) input->addSearchResult(); } } if (needButtonActivation) { - if (current->isActivatedSubmit()) + if (control->isActivatedSubmit()) needButtonActivation = false; - else if (firstSuccessfulSubmitButton == 0 && current->isSuccessfulSubmitButton()) - firstSuccessfulSubmitButton = current; + else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton()) + firstSuccessfulSubmitButton = control; } } if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(true); - if (!m_url) - m_url = document()->url(); + if (m_url.isEmpty()) + m_url = document()->url().string(); if (m_post) { if (m_multipart && isMailtoForm()) { @@ -519,9 +508,12 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton) String body = data->flattenToString(); if (equalIgnoringCase(enctype(), "text/plain")) { // Convention seems to be to decode, and s/&/\r\n/. Also, spaces are encoded as %20. - body = KURL::decode_string(body.replace('&', "\r\n").replace('+', ' ').deprecatedString() + "\r\n"); + body = decodeURLEscapeSequences(body.replace('&', "\r\n").replace('+', ' ') + "\r\n"); } - data = new FormData((String("body=") + encodeCString(body.utf8())).replace('+', "%20").latin1()); + Vector<char> bodyData; + appendString(bodyData, "body="); + appendEncodedString(bodyData, body.utf8()); + data = FormData::create(String(bodyData.data(), bodyData.size()).replace('+', "%20").latin1()); } frame->loader()->submitForm("POST", m_url, data, m_target, enctype(), String(), event); } else { @@ -542,7 +534,7 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton) void HTMLFormElement::reset() { - Frame *frame = document()->frame(); + Frame* frame = document()->frame(); if (m_inreset || !frame) return; @@ -550,7 +542,7 @@ void HTMLFormElement::reset() // ### DOM2 labels this event as not cancelable, however // common browsers( sick! ) allow it be cancelled. - if ( !dispatchHTMLEvent(resetEvent,true, true) ) { + if ( !dispatchEventForType(eventNames().resetEvent,true, true) ) { m_inreset = false; return; } @@ -561,7 +553,7 @@ void HTMLFormElement::reset() m_inreset = false; } -void HTMLFormElement::parseMappedAttribute(MappedAttribute *attr) +void HTMLFormElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == actionAttr) m_url = parseURL(attr->value()); @@ -580,20 +572,24 @@ void HTMLFormElement::parseMappedAttribute(MappedAttribute *attr) m_acceptcharset = attr->value(); else if (attr->name() == acceptAttr) { // ignore this one for the moment... - } else if (attr->name() == autocompleteAttr) + } else if (attr->name() == autocompleteAttr) { m_autocomplete = !equalIgnoringCase(attr->value(), "off"); - else if (attr->name() == onsubmitAttr) - setHTMLEventListener(submitEvent, attr); + if (!m_autocomplete) + document()->registerForDocumentActivationCallbacks(this); + else + document()->unregisterForDocumentActivationCallbacks(this); + } else if (attr->name() == onsubmitAttr) + setInlineEventListenerForTypeAndAttribute(eventNames().submitEvent, attr); else if (attr->name() == onresetAttr) - setHTMLEventListener(resetEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().resetEvent, attr); else if (attr->name() == nameAttr) { - String newNameAttr = attr->value(); + const AtomicString& newName = attr->value(); if (inDocument() && document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->removeNamedItem(oldNameAttr); - doc->addNamedItem(newNameAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeNamedItem(m_name); + document->addNamedItem(newName); } - oldNameAttr = newNameAttr; + m_name = newName; } else HTMLElement::parseMappedAttribute(attr); } @@ -608,7 +604,7 @@ template<class T, size_t n> static void removeFromVector(Vector<T*, n> & vec, T* } } -unsigned HTMLFormElement::formElementIndex(HTMLGenericFormElement *e) +unsigned HTMLFormElement::formElementIndex(HTMLFormControlElement* e) { // Check for the special case where this element is the very last thing in // the form's tree of children; we don't want to walk the entire tree in that @@ -616,49 +612,49 @@ unsigned HTMLFormElement::formElementIndex(HTMLGenericFormElement *e) // that says "add this form element to the end of the array". if (e->traverseNextNode(this)) { unsigned i = 0; - for (Node *node = this; node; node = node->traverseNextNode(this)) { + for (Node* node = this; node; node = node->traverseNextNode(this)) { if (node == e) return i; if (node->isHTMLElement() - && static_cast<HTMLElement *>(node)->isGenericFormElement() - && static_cast<HTMLGenericFormElement *>(node)->form() == this) + && static_cast<HTMLElement*>(node)->isGenericFormElement() + && static_cast<HTMLFormControlElement*>(node)->form() == this) ++i; } } return formElements.size(); } -void HTMLFormElement::registerFormElement(HTMLGenericFormElement* e) +void HTMLFormElement::registerFormElement(HTMLFormControlElement* e) { document()->checkedRadioButtons().removeButton(e); m_checkedRadioButtons.addButton(e); formElements.insert(formElementIndex(e), e); } -void HTMLFormElement::removeFormElement(HTMLGenericFormElement* e) +void HTMLFormElement::removeFormElement(HTMLFormControlElement* e) { m_checkedRadioButtons.removeButton(e); removeFromVector(formElements, e); } -bool HTMLFormElement::isURLAttribute(Attribute *attr) const +bool HTMLFormElement::isURLAttribute(Attribute* attr) const { return attr->name() == actionAttr; } -void HTMLFormElement::registerImgElement(HTMLImageElement *e) +void HTMLFormElement::registerImgElement(HTMLImageElement* e) { imgElements.append(e); } -void HTMLFormElement::removeImgElement(HTMLImageElement *e) +void HTMLFormElement::removeImgElement(HTMLImageElement* e) { removeFromVector(imgElements, e); } PassRefPtr<HTMLCollection> HTMLFormElement::elements() { - return new HTMLFormCollection(this); + return HTMLFormCollection::create(this); } String HTMLFormElement::name() const @@ -716,14 +712,14 @@ void HTMLFormElement::setTarget(const String &value) setAttribute(targetAttr, value); } -PassRefPtr<HTMLGenericFormElement> HTMLFormElement::elementForAlias(const AtomicString& alias) +PassRefPtr<HTMLFormControlElement> HTMLFormElement::elementForAlias(const AtomicString& alias) { if (alias.isEmpty() || !m_elementAliases) return 0; return m_elementAliases->get(alias.impl()); } -void HTMLFormElement::addElementAlias(HTMLGenericFormElement* element, const AtomicString& alias) +void HTMLFormElement::addElementAlias(HTMLFormControlElement* element, const AtomicString& alias) { if (alias.isEmpty()) return; @@ -737,7 +733,7 @@ void HTMLFormElement::getNamedElements(const AtomicString& name, Vector<RefPtr<N elements()->namedItems(name, namedItems); // see if we have seen something with this name before - RefPtr<HTMLGenericFormElement> aliasElem; + RefPtr<HTMLFormControlElement> aliasElem; if (aliasElem = elementForAlias(name)) { bool found = false; for (unsigned n = 0; n < namedItems.size(); n++) { @@ -752,10 +748,30 @@ void HTMLFormElement::getNamedElements(const AtomicString& name, Vector<RefPtr<N } // name has been accessed, remember it if (namedItems.size() && aliasElem != namedItems.first()) - addElementAlias(static_cast<HTMLGenericFormElement*>(namedItems.first().get()), name); + addElementAlias(static_cast<HTMLFormControlElement*>(namedItems.first().get()), name); +} + +void HTMLFormElement::documentDidBecomeActive() +{ + ASSERT(!m_autocomplete); + + for (unsigned i = 0; i < formElements.size(); ++i) + formElements[i]->reset(); +} + +void HTMLFormElement::willMoveToNewOwnerDocument() +{ + if (!m_autocomplete) + document()->unregisterForDocumentActivationCallbacks(this); +} + +void HTMLFormElement::didMoveToNewOwnerDocument() +{ + if(m_autocomplete) + document()->registerForDocumentActivationCallbacks(this); } -void HTMLFormElement::CheckedRadioButtons::addButton(HTMLGenericFormElement* element) +void HTMLFormElement::CheckedRadioButtons::addButton(HTMLFormControlElement* element) { // We only want to add radio buttons. if (!element->isRadioButton()) @@ -794,7 +810,7 @@ HTMLInputElement* HTMLFormElement::CheckedRadioButtons::checkedButtonForGroup(co return m_nameToCheckedRadioButtonMap->get(name.impl()); } -void HTMLFormElement::CheckedRadioButtons::removeButton(HTMLGenericFormElement* element) +void HTMLFormElement::CheckedRadioButtons::removeButton(HTMLFormControlElement* element) { if (element->name().isEmpty() || !m_nameToCheckedRadioButtonMap) return; diff --git a/WebCore/html/HTMLFormElement.h b/WebCore/html/HTMLFormElement.h index 73a4aba..c65304b 100644 --- a/WebCore/html/HTMLFormElement.h +++ b/WebCore/html/HTMLFormElement.h @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 @@ -33,7 +33,7 @@ namespace WebCore { class Event; class FormData; -class HTMLGenericFormElement; +class HTMLFormControlElement; class HTMLImageElement; class HTMLInputElement; class HTMLFormCollection; @@ -69,8 +69,8 @@ public: virtual void parseMappedAttribute(MappedAttribute*); - void registerFormElement(HTMLGenericFormElement*); - void removeFormElement(HTMLGenericFormElement*); + void registerFormElement(HTMLFormControlElement*); + void removeFormElement(HTMLFormControlElement*); void registerImgElement(HTMLImageElement*); void removeImgElement(HTMLImageElement*); @@ -79,8 +79,9 @@ public: void submit(Event*, bool activateSubmitButton = false); void reset(); + // Used to indicate a malformed state to keep from applying the bottom margin of the form. void setMalformed(bool malformed) { m_malformed = malformed; } - virtual bool isMalformed() { return m_malformed; } + bool isMalformed() const { return m_malformed; } virtual bool isURLAttribute(Attribute*) const; @@ -102,16 +103,16 @@ public: virtual String target() const; void setTarget(const String&); - PassRefPtr<HTMLGenericFormElement> elementForAlias(const AtomicString&); - void addElementAlias(HTMLGenericFormElement*, const AtomicString& alias); + PassRefPtr<HTMLFormControlElement> elementForAlias(const AtomicString&); + void addElementAlias(HTMLFormControlElement*, const AtomicString& alias); // FIXME: Change this to be private after getting rid of all the clients. - Vector<HTMLGenericFormElement*> formElements; + Vector<HTMLFormControlElement*> formElements; class CheckedRadioButtons { public: - void addButton(HTMLGenericFormElement*); - void removeButton(HTMLGenericFormElement*); + void addButton(HTMLFormControlElement*); + void removeButton(HTMLFormControlElement*); HTMLInputElement* checkedButtonForGroup(const AtomicString& name) const; private: @@ -121,16 +122,22 @@ public: CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; } + virtual void documentDidBecomeActive(); + +protected: + virtual void willMoveToNewOwnerDocument(); + virtual void didMoveToNewOwnerDocument(); + private: void parseEnctype(const String&); bool isMailtoForm() const; TextEncoding dataEncoding() const; PassRefPtr<FormData> formData(const char* boundary) const; - unsigned formElementIndex(HTMLGenericFormElement*); + unsigned formElementIndex(HTMLFormControlElement*); friend class HTMLFormCollection; - typedef HashMap<RefPtr<AtomicStringImpl>, RefPtr<HTMLGenericFormElement> > AliasMap; + typedef HashMap<RefPtr<AtomicStringImpl>, RefPtr<HTMLFormControlElement> > AliasMap; AliasMap* m_elementAliases; HTMLCollection::CollectionInfo* collectionInfo; @@ -149,10 +156,10 @@ private: bool m_doingsubmit : 1; bool m_inreset : 1; bool m_malformed : 1; - String oldNameAttr; + AtomicString m_name; #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr is removed from HTMLDocument's NameCountMap + // ensure that m_name is removed from HTMLDocument's NameCountMap int oldNameCount; #endif }; diff --git a/WebCore/html/HTMLFrameElementBase.cpp b/WebCore/html/HTMLFrameElementBase.cpp index 6438f3c..1c80155 100644 --- a/WebCore/html/HTMLFrameElementBase.cpp +++ b/WebCore/html/HTMLFrameElementBase.cpp @@ -1,11 +1,9 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Simon Hausmann (hausmann@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2006 Apple Computer, Inc. + * Copyright (C) 2004, 2006, 2008 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 @@ -22,6 +20,7 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "HTMLFrameElementBase.h" @@ -42,7 +41,6 @@ namespace WebCore { -using namespace EventNames; using namespace HTMLNames; HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document *doc) @@ -61,28 +59,25 @@ bool HTMLFrameElementBase::isURLAllowed(const AtomicString& URLString) const if (URLString.isEmpty()) return true; - KURL completeURL(document()->completeURL(URLString.deprecatedString())); - completeURL.setRef(DeprecatedString::null); + const KURL& completeURL = document()->completeURL(URLString); // Don't allow more than 200 total frames in a set. This seems // like a reasonable upper bound, and otherwise mutually recursive // frameset pages can quickly bring the program to its knees with // exponential growth in the number of frames. - - // FIXME: This limit could be higher, but WebKit has some + // FIXME: This limit could be higher, but because WebKit has some // algorithms that happen while loading which appear to be N^2 or - // worse in the number of frames - if (Frame* parentFrame = document()->frame()) + // worse in the number of frames, we'll keep it at 200 for now. + if (Frame* parentFrame = document()->frame()) { if (parentFrame->page()->frameCount() > 200) return false; + } // We allow one level of self-reference because some sites depend on that. // But we don't allow more than one. bool foundSelfReference = false; for (Frame* frame = document()->frame(); frame; frame = frame->tree()->parent()) { - KURL frameURL = frame->loader()->url(); - frameURL.setRef(DeprecatedString::null); - if (frameURL == completeURL) { + if (equalIgnoringRef(frame->loader()->url(), completeURL)) { if (foundSelfReference) return false; foundSelfReference = true; @@ -94,19 +89,19 @@ bool HTMLFrameElementBase::isURLAllowed(const AtomicString& URLString) const void HTMLFrameElementBase::openURL() { - ASSERT(!m_name.isEmpty()); + ASSERT(!m_frameName.isEmpty()); if (!isURLAllowed(m_URL)) return; if (m_URL.isEmpty()) - m_URL = "about:blank"; + m_URL = blankURL().string(); Frame* parentFrame = document()->frame(); if (!parentFrame) return; - parentFrame->loader()->requestFrame(this, m_URL, m_name); + parentFrame->loader()->requestFrame(this, m_URL, m_frameName); if (contentFrame()) contentFrame()->setInViewSourceMode(viewSourceMode()); } @@ -118,9 +113,9 @@ void HTMLFrameElementBase::parseMappedAttribute(MappedAttribute *attr) else if (attr->name() == idAttr) { // Important to call through to base for the id attribute so the hasID bit gets set. HTMLFrameOwnerElement::parseMappedAttribute(attr); - m_name = attr->value(); + m_frameName = attr->value(); } else if (attr->name() == nameAttr) { - m_name = attr->value(); + m_frameName = attr->value(); // FIXME: If we are already attached, this doesn't actually change the frame's name. // FIXME: If we are already attached, this doesn't check for frame name // conflicts and generate a unique frame name. @@ -145,24 +140,22 @@ void HTMLFrameElementBase::parseMappedAttribute(MappedAttribute *attr) if (contentFrame()) contentFrame()->setInViewSourceMode(viewSourceMode()); } else if (attr->name() == onloadAttr) { - setHTMLEventListener(loadEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().loadEvent, attr); } else if (attr->name() == onbeforeunloadAttr) { // FIXME: should <frame> elements have beforeunload handlers? - setHTMLEventListener(beforeunloadEvent, attr); - } else if (attr->name() == onunloadAttr) { - setHTMLEventListener(unloadEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().beforeunloadEvent, attr); } else HTMLFrameOwnerElement::parseMappedAttribute(attr); } void HTMLFrameElementBase::setNameAndOpenURL() { - m_name = getAttribute(nameAttr); - if (m_name.isNull()) - m_name = getAttribute(idAttr); + m_frameName = getAttribute(nameAttr); + if (m_frameName.isNull()) + m_frameName = getAttribute(idAttr); if (Frame* parentFrame = document()->frame()) - m_name = parentFrame->tree()->uniqueChildName(m_name); + m_frameName = parentFrame->tree()->uniqueChildName(m_frameName); openURL(); } @@ -203,7 +196,7 @@ void HTMLFrameElementBase::attach() renderPart->setWidget(frame->view()); } -String HTMLFrameElementBase::location() const +KURL HTMLFrameElementBase::location() const { return src(); } @@ -302,7 +295,7 @@ void HTMLFrameElementBase::setScrolling(const String &value) setAttribute(scrollingAttr, value); } -String HTMLFrameElementBase::src() const +KURL HTMLFrameElementBase::src() const { return document()->completeURL(getAttribute(srcAttr)); } diff --git a/WebCore/html/HTMLFrameElementBase.h b/WebCore/html/HTMLFrameElementBase.h index bcb63ac..4a24451 100644 --- a/WebCore/html/HTMLFrameElementBase.h +++ b/WebCore/html/HTMLFrameElementBase.h @@ -1,10 +1,8 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Simon Hausmann <hausmann@kde.org> - * Copyright (C) 2004, 2006 Apple Computer, Inc. + * Copyright (C) 2004, 2006, 2008 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 @@ -39,8 +37,9 @@ public: virtual void removedFromDocument(); virtual void attach(); + virtual bool canLazyAttach() { return false; } - String location() const; + KURL location() const; void setLocation(const String&); virtual bool isFocusable() const; @@ -74,7 +73,7 @@ public: String scrolling() const; void setScrolling(const String&); - String src() const; + KURL src() const; void setSrc(const String&); int width() const; @@ -92,7 +91,7 @@ protected: static void setNameAndOpenURLCallback(Node*); AtomicString m_URL; - AtomicString m_name; + AtomicString m_frameName; ScrollbarMode m_scrolling; diff --git a/WebCore/html/HTMLFrameSetElement.cpp b/WebCore/html/HTMLFrameSetElement.cpp index c49b0f8..75fd516 100644 --- a/WebCore/html/HTMLFrameSetElement.cpp +++ b/WebCore/html/HTMLFrameSetElement.cpp @@ -32,13 +32,13 @@ #include "EventNames.h" #include "HTMLNames.h" #include "Length.h" +#include "Length.h" #include "MouseEvent.h" #include "RenderFrameSet.h" #include "Text.h" namespace WebCore { -using namespace EventNames; using namespace HTMLNames; HTMLFrameSetElement::HTMLFrameSetElement(Document *doc) @@ -88,13 +88,13 @@ void HTMLFrameSetElement::parseMappedAttribute(MappedAttribute *attr) if (attr->name() == rowsAttr) { if (!attr->isNull()) { if (m_rows) delete [] m_rows; - m_rows = attr->value().toLengthArray(m_totalRows); + m_rows = newLengthArray(attr->value().string(), m_totalRows); setChanged(); } } else if (attr->name() == colsAttr) { if (!attr->isNull()) { delete [] m_cols; - m_cols = attr->value().toLengthArray(m_totalCols); + m_cols = newLengthArray(attr->value().string(), m_totalCols); setChanged(); } } else if (attr->name() == frameborderAttr) { @@ -122,15 +122,15 @@ void HTMLFrameSetElement::parseMappedAttribute(MappedAttribute *attr) } else if (attr->name() == bordercolorAttr) { m_borderColorSet = attr->decl(); if (!attr->decl() && !attr->isEmpty()) { - addCSSColor(attr, CSS_PROP_BORDER_COLOR, attr->value()); + addCSSColor(attr, CSSPropertyBorderColor, attr->value()); m_borderColorSet = true; } } else if (attr->name() == onloadAttr) { - document()->setHTMLWindowEventListener(loadEvent, attr); + document()->setWindowInlineEventListenerForTypeAndAttribute(eventNames().loadEvent, attr); } else if (attr->name() == onbeforeunloadAttr) { - document()->setHTMLWindowEventListener(beforeunloadEvent, attr); + document()->setWindowInlineEventListenerForTypeAndAttribute(eventNames().beforeunloadEvent, attr); } else if (attr->name() == onunloadAttr) { - document()->setHTMLWindowEventListener(unloadEvent, attr); + document()->setWindowInlineEventListenerForTypeAndAttribute(eventNames().unloadEvent, attr); } else HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLHRElement.cpp b/WebCore/html/HTMLHRElement.cpp index 9bef9bd..743b0d2 100644 --- a/WebCore/html/HTMLHRElement.cpp +++ b/WebCore/html/HTMLHRElement.cpp @@ -58,43 +58,43 @@ void HTMLHRElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == alignAttr) { if (equalIgnoringCase(attr->value(), "left")) { - addCSSProperty(attr, CSS_PROP_MARGIN_LEFT, "0"); - addCSSProperty(attr, CSS_PROP_MARGIN_RIGHT, CSS_VAL_AUTO); + addCSSProperty(attr, CSSPropertyMarginLeft, "0"); + addCSSProperty(attr, CSSPropertyMarginRight, CSSValueAuto); } else if (equalIgnoringCase(attr->value(), "right")) { - addCSSProperty(attr, CSS_PROP_MARGIN_LEFT, CSS_VAL_AUTO); - addCSSProperty(attr, CSS_PROP_MARGIN_RIGHT, "0"); + addCSSProperty(attr, CSSPropertyMarginLeft, CSSValueAuto); + addCSSProperty(attr, CSSPropertyMarginRight, "0"); } else { - addCSSProperty(attr, CSS_PROP_MARGIN_LEFT, CSS_VAL_AUTO); - addCSSProperty(attr, CSS_PROP_MARGIN_RIGHT, CSS_VAL_AUTO); + addCSSProperty(attr, CSSPropertyMarginLeft, CSSValueAuto); + addCSSProperty(attr, CSSPropertyMarginRight, CSSValueAuto); } } else if (attr->name() == widthAttr) { bool ok; int v = attr->value().toInt(&ok); if(ok && !v) - addCSSLength(attr, CSS_PROP_WIDTH, "1"); + addCSSLength(attr, CSSPropertyWidth, "1"); else - addCSSLength(attr, CSS_PROP_WIDTH, attr->value()); + addCSSLength(attr, CSSPropertyWidth, attr->value()); } else if (attr->name() == colorAttr) { - addCSSProperty(attr, CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID); - addCSSColor(attr, CSS_PROP_BORDER_COLOR, attr->value()); - addCSSColor(attr, CSS_PROP_BACKGROUND_COLOR, attr->value()); + addCSSProperty(attr, CSSPropertyBorderTopStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderRightStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderBottomStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderLeftStyle, CSSValueSolid); + addCSSColor(attr, CSSPropertyBorderColor, attr->value()); + addCSSColor(attr, CSSPropertyBackgroundColor, attr->value()); } else if (attr->name() == noshadeAttr) { - addCSSProperty(attr, CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID); - addCSSColor(attr, CSS_PROP_BORDER_COLOR, String("grey")); - addCSSColor(attr, CSS_PROP_BACKGROUND_COLOR, String("grey")); + addCSSProperty(attr, CSSPropertyBorderTopStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderRightStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderBottomStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderLeftStyle, CSSValueSolid); + addCSSColor(attr, CSSPropertyBorderColor, String("grey")); + addCSSColor(attr, CSSPropertyBackgroundColor, String("grey")); } else if (attr->name() == sizeAttr) { StringImpl* si = attr->value().impl(); int size = si->toInt(); if (size <= 1) - addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_WIDTH, String("0")); + addCSSProperty(attr, CSSPropertyBorderBottomWidth, String("0")); else - addCSSLength(attr, CSS_PROP_HEIGHT, String::number(size-2)); + addCSSLength(attr, CSSPropertyHeight, String::number(size-2)); } else HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLHtmlElement.cpp b/WebCore/html/HTMLHtmlElement.cpp index 5d8d1b6..dd8a609 100644 --- a/WebCore/html/HTMLHtmlElement.cpp +++ b/WebCore/html/HTMLHtmlElement.cpp @@ -25,6 +25,8 @@ #include "config.h" #include "HTMLHtmlElement.h" +#include "ApplicationCacheGroup.h" +#include "Document.h" #include "HTMLNames.h" namespace WebCore { @@ -58,4 +60,24 @@ bool HTMLHtmlElement::checkDTD(const Node* newChild) newChild->hasTagName(scriptTag); } +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void HTMLHtmlElement::insertedIntoDocument() +{ + HTMLElement::insertedIntoDocument(); + + if (!document()->parsing()) + return; + + if (!document()->frame()) + return; + + // Check the manifest attribute + AtomicString manifest = getAttribute(manifestAttr); + if (manifest.isNull()) + ApplicationCacheGroup::selectCacheWithoutManifestURL(document()->frame()); + else + ApplicationCacheGroup::selectCache(document()->frame(), document()->completeURL(manifest)); +} +#endif + } diff --git a/WebCore/html/HTMLHtmlElement.h b/WebCore/html/HTMLHtmlElement.h index 2e3b05a..2154d95 100644 --- a/WebCore/html/HTMLHtmlElement.h +++ b/WebCore/html/HTMLHtmlElement.h @@ -40,6 +40,10 @@ public: virtual int tagPriority() const { return 11; } virtual bool checkDTD(const Node* newChild); +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void insertedIntoDocument(); +#endif + String version() const; void setVersion(const String&); }; diff --git a/WebCore/html/HTMLIFrameElement.cpp b/WebCore/html/HTMLIFrameElement.cpp index c52587d..4a071bf 100644 --- a/WebCore/html/HTMLIFrameElement.cpp +++ b/WebCore/html/HTMLIFrameElement.cpp @@ -1,11 +1,9 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Simon Hausmann (hausmann@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2006 Apple Computer, Inc. + * Copyright (C) 2004, 2006, 2008 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 @@ -22,6 +20,7 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "HTMLIFrameElement.h" @@ -60,28 +59,28 @@ bool HTMLIFrameElement::mapToEntry(const QualifiedName& attrName, MappedAttribut return HTMLFrameElementBase::mapToEntry(attrName, result); } -void HTMLIFrameElement::parseMappedAttribute(MappedAttribute *attr) +void HTMLIFrameElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == widthAttr) - addCSSLength(attr, CSS_PROP_WIDTH, attr->value()); + addCSSLength(attr, CSSPropertyWidth, attr->value()); else if (attr->name() == heightAttr) - addCSSLength(attr, CSS_PROP_HEIGHT, attr->value()); + addCSSLength(attr, CSSPropertyHeight, attr->value()); else if (attr->name() == alignAttr) addHTMLAlignment(attr); else if (attr->name() == nameAttr) { - String newNameAttr = attr->value(); + const AtomicString& newName = attr->value(); if (inDocument() && document()->isHTMLDocument()) { - HTMLDocument* doc = static_cast<HTMLDocument* >(document()); - doc->removeDocExtraNamedItem(oldNameAttr); - doc->addDocExtraNamedItem(newNameAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeExtraNamedItem(m_name); + document->addExtraNamedItem(newName); } - oldNameAttr = newNameAttr; + m_name = newName; } else if (attr->name() == frameborderAttr) { // Frame border doesn't really match the HTML4 spec definition for iframes. It simply adds // a presentational hint that the border should be off if set to zero. if (!attr->isNull() && !attr->value().toInt()) // Add a rule that nulls out our border width. - addCSSLength(attr, CSS_PROP_BORDER_WIDTH, "0"); + addCSSLength(attr, CSSPropertyBorderWidth, "0"); } else HTMLFrameElementBase::parseMappedAttribute(attr); } @@ -98,20 +97,16 @@ RenderObject* HTMLIFrameElement::createRenderer(RenderArena* arena, RenderStyle* void HTMLIFrameElement::insertedIntoDocument() { - if (document()->isHTMLDocument()) { - HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - doc->addDocExtraNamedItem(oldNameAttr); - } + if (document()->isHTMLDocument()) + static_cast<HTMLDocument*>(document())->addExtraNamedItem(m_name); HTMLFrameElementBase::insertedIntoDocument(); } void HTMLIFrameElement::removedFromDocument() { - if (document()->isHTMLDocument()) { - HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - doc->removeDocExtraNamedItem(oldNameAttr); - } + if (document()->isHTMLDocument()) + static_cast<HTMLDocument*>(document())->removeExtraNamedItem(m_name); HTMLFrameElementBase::removedFromDocument(); } diff --git a/WebCore/html/HTMLIFrameElement.h b/WebCore/html/HTMLIFrameElement.h index c1f7ea8..adead51 100644 --- a/WebCore/html/HTMLIFrameElement.h +++ b/WebCore/html/HTMLIFrameElement.h @@ -1,10 +1,8 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Simon Hausmann <hausmann@kde.org> - * Copyright (C) 2004, 2006 Apple Computer, Inc. + * Copyright (C) 2004, 2006, 2008 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 @@ -30,10 +28,9 @@ namespace WebCore { -class HTMLIFrameElement : public HTMLFrameElementBase -{ +class HTMLIFrameElement : public HTMLFrameElementBase { public: - HTMLIFrameElement(Document* doc); + HTMLIFrameElement(Document*); virtual HTMLTagStatus endTagRequirement() const { return TagStatusRequired; } virtual int tagPriority() const { return 1; } @@ -61,7 +58,7 @@ public: void setWidth(const String&); private: - String oldNameAttr; + AtomicString m_name; }; } // namespace WebCore diff --git a/WebCore/html/HTMLImageElement.cpp b/WebCore/html/HTMLImageElement.cpp index d2c74eb..d319553 100644 --- a/WebCore/html/HTMLImageElement.cpp +++ b/WebCore/html/HTMLImageElement.cpp @@ -26,6 +26,7 @@ #include "CSSPropertyNames.h" #include "CSSValueKeywords.h" #include "EventNames.h" +#include "Frame.h" #include "HTMLDocument.h" #include "HTMLFormElement.h" #include "HTMLNames.h" @@ -35,7 +36,6 @@ using namespace std; namespace WebCore { -using namespace EventNames; using namespace HTMLNames; HTMLImageElement::HTMLImageElement(Document* doc, HTMLFormElement* f) @@ -46,7 +46,7 @@ HTMLImageElement::HTMLImageElement(Document* doc, HTMLFormElement* f) , m_compositeOperator(CompositeSourceOver) #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name and m_id are removed from HTMLDocument's NameCountMap , oldNameIdCount(0) #endif { @@ -62,7 +62,7 @@ HTMLImageElement::HTMLImageElement(const QualifiedName& tagName, Document* doc) , m_compositeOperator(CompositeSourceOver) #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name and m_id are removed from HTMLDocument's NameCountMap , oldNameIdCount(0) #endif { @@ -72,11 +72,11 @@ HTMLImageElement::~HTMLImageElement() { #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name and m_id are removed from HTMLDocument's NameCountMap if (oldNameIdCount && document()->isHTMLDocument()) { HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - doc->removeNamedItem(oldNameAttr); - doc->removeDocExtraNamedItem(oldIdAttr); + doc->removeNamedItem(m_name); + doc->removeExtraNamedItem(m_id); } #endif if (m_form) @@ -111,57 +111,57 @@ void HTMLImageElement::parseMappedAttribute(MappedAttribute* attr) } else if (attrName == srcAttr) m_imageLoader.updateFromElement(); else if (attrName == widthAttr) - addCSSLength(attr, CSS_PROP_WIDTH, attr->value()); + addCSSLength(attr, CSSPropertyWidth, attr->value()); else if (attrName == heightAttr) - addCSSLength(attr, CSS_PROP_HEIGHT, attr->value()); + addCSSLength(attr, CSSPropertyHeight, attr->value()); else if (attrName == borderAttr) { // border="noborder" -> border="0" - addCSSLength(attr, CSS_PROP_BORDER_WIDTH, attr->value().toInt() ? attr->value() : "0"); - addCSSProperty(attr, CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID); + addCSSLength(attr, CSSPropertyBorderWidth, attr->value().toInt() ? attr->value() : "0"); + addCSSProperty(attr, CSSPropertyBorderTopStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderRightStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderBottomStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderLeftStyle, CSSValueSolid); } else if (attrName == vspaceAttr) { - addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value()); + addCSSLength(attr, CSSPropertyMarginTop, attr->value()); + addCSSLength(attr, CSSPropertyMarginBottom, attr->value()); } else if (attrName == hspaceAttr) { - addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value()); + addCSSLength(attr, CSSPropertyMarginLeft, attr->value()); + addCSSLength(attr, CSSPropertyMarginRight, attr->value()); } else if (attrName == alignAttr) addHTMLAlignment(attr); else if (attrName == valignAttr) - addCSSProperty(attr, CSS_PROP_VERTICAL_ALIGN, attr->value()); + addCSSProperty(attr, CSSPropertyVerticalAlign, attr->value()); else if (attrName == usemapAttr) { - if (attr->value().domString()[0] == '#') + if (attr->value().string()[0] == '#') usemap = attr->value(); else - usemap = document()->completeURL(parseURL(attr->value())); - m_isLink = !attr->isNull(); + usemap = document()->completeURL(parseURL(attr->value())).string(); + setIsLink(!attr->isNull()); } else if (attrName == ismapAttr) ismap = true; else if (attrName == onabortAttr) - setHTMLEventListener(abortEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().abortEvent, attr); else if (attrName == onloadAttr) - setHTMLEventListener(loadEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().loadEvent, attr); else if (attrName == compositeAttr) { if (!parseCompositeOperator(attr->value(), m_compositeOperator)) m_compositeOperator = CompositeSourceOver; } else if (attrName == nameAttr) { - String newNameAttr = attr->value(); + const AtomicString& newName = attr->value(); if (inDocument() && document()->isHTMLDocument()) { - HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - doc->removeNamedItem(oldNameAttr); - doc->addNamedItem(newNameAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeNamedItem(m_name); + document->addNamedItem(newName); } - oldNameAttr = newNameAttr; + m_name = newName; } else if (attr->name() == idAttr) { - String newIdAttr = attr->value(); + const AtomicString& newId = attr->value(); if (inDocument() && document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->removeDocExtraNamedItem(oldIdAttr); - doc->addDocExtraNamedItem(newIdAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeExtraNamedItem(m_id); + document->addExtraNamedItem(newId); } - oldIdAttr = newIdAttr; + m_id = newId; // also call superclass HTMLElement::parseMappedAttribute(attr); } else @@ -194,6 +194,8 @@ void HTMLImageElement::attach() if (renderer() && renderer()->isImage()) { RenderImage* imageObj = static_cast<RenderImage*>(renderer()); + if (imageObj->hasImage()) + return; imageObj->setCachedImage(m_imageLoader.image()); // If we have no image at all because we have no src attribute, set @@ -206,13 +208,12 @@ void HTMLImageElement::attach() void HTMLImageElement::insertedIntoDocument() { if (document()->isHTMLDocument()) { - HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - - doc->addNamedItem(oldNameAttr); - doc->addDocExtraNamedItem(oldIdAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->addNamedItem(m_name); + document->addExtraNamedItem(m_id); #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name and m_id are removed from HTMLDocument's NameCountMap oldNameIdCount++; #endif } @@ -223,13 +224,12 @@ void HTMLImageElement::insertedIntoDocument() void HTMLImageElement::removedFromDocument() { if (document()->isHTMLDocument()) { - HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - - doc->removeNamedItem(oldNameAttr); - doc->removeDocExtraNamedItem(oldIdAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeNamedItem(m_name); + document->removeExtraNamedItem(m_id); #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name and m_id are removed from HTMLDocument's NameCountMap oldNameIdCount--; #endif } @@ -247,8 +247,10 @@ int HTMLImageElement::width(bool ignorePendingStylesheets) const return width; // if the image is available, use its width - if (m_imageLoader.image()) - return m_imageLoader.image()->imageSize().width(); + if (m_imageLoader.image()) { + float zoomFactor = document()->frame() ? document()->frame()->pageZoomFactor() : 1.0f; + return m_imageLoader.image()->imageSize(zoomFactor).width(); + } } if (ignorePendingStylesheets) @@ -269,8 +271,10 @@ int HTMLImageElement::height(bool ignorePendingStylesheets) const return height; // if the image is available, use its height - if (m_imageLoader.image()) - return m_imageLoader.image()->imageSize().height(); + if (m_imageLoader.image()) { + float zoomFactor = document()->frame() ? document()->frame()->pageZoomFactor() : 1.0f; + return m_imageLoader.image()->imageSize(zoomFactor).height(); + } } if (ignorePendingStylesheets) @@ -286,7 +290,7 @@ int HTMLImageElement::naturalWidth() const if (!m_imageLoader.image()) return 0; - return m_imageLoader.image()->imageSize().width(); + return m_imageLoader.image()->imageSize(1.0f).width(); } int HTMLImageElement::naturalHeight() const @@ -294,7 +298,7 @@ int HTMLImageElement::naturalHeight() const if (!m_imageLoader.image()) return 0; - return m_imageLoader.image()->imageSize().height(); + return m_imageLoader.image()->imageSize(1.0f).height(); } bool HTMLImageElement::isURLAttribute(Attribute* attr) const @@ -302,7 +306,7 @@ bool HTMLImageElement::isURLAttribute(Attribute* attr) const return attr->name() == srcAttr || attr->name() == lowsrcAttr || attr->name() == longdescAttr - || (attr->name() == usemapAttr && attr->value().domString()[0] != '#'); + || (attr->name() == usemapAttr && attr->value().string()[0] != '#'); } String HTMLImageElement::name() const @@ -371,7 +375,7 @@ void HTMLImageElement::setIsMap(bool isMap) setAttribute(ismapAttr, isMap ? "" : 0); } -String HTMLImageElement::longDesc() const +KURL HTMLImageElement::longDesc() const { return document()->completeURL(getAttribute(longdescAttr)); } @@ -381,7 +385,7 @@ void HTMLImageElement::setLongDesc(const String& value) setAttribute(longdescAttr, value); } -String HTMLImageElement::lowsrc() const +KURL HTMLImageElement::lowsrc() const { return document()->completeURL(getAttribute(lowsrcAttr)); } @@ -391,7 +395,7 @@ void HTMLImageElement::setLowsrc(const String& value) setAttribute(lowsrcAttr, value); } -String HTMLImageElement::src() const +KURL HTMLImageElement::src() const { return document()->completeURL(getAttribute(srcAttr)); } @@ -452,4 +456,10 @@ bool HTMLImageElement::complete() const return m_imageLoader.imageComplete(); } +void HTMLImageElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + urls.append(src().string()); + urls.append(useMap()); +} + } diff --git a/WebCore/html/HTMLImageElement.h b/WebCore/html/HTMLImageElement.h index 1ce3a74..848ecb1 100644 --- a/WebCore/html/HTMLImageElement.h +++ b/WebCore/html/HTMLImageElement.h @@ -1,9 +1,7 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004 Apple Computer, Inc. + * Copyright (C) 2004, 2008 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,12 +23,13 @@ #ifndef HTMLImageElement_h #define HTMLImageElement_h -#include "HTMLElement.h" #include "GraphicsTypes.h" +#include "HTMLElement.h" #include "HTMLImageLoader.h" namespace WebCore { - class HTMLFormElement; + +class HTMLFormElement; class HTMLImageElement : public HTMLElement { friend class HTMLFormElement; @@ -62,8 +61,6 @@ public: String altText() const; - String imageMap() const { return usemap; } - virtual bool isURLAttribute(Attribute*) const; CompositeOperator compositeOperator() const { return m_compositeOperator; } @@ -93,13 +90,13 @@ public: bool isMap() const; void setIsMap(bool); - String longDesc() const; + KURL longDesc() const; void setLongDesc(const String&); - String lowsrc() const; + KURL lowsrc() const; void setLowsrc(const String&); - String src() const; + KURL src() const; void setSrc(const String&); String useMap() const; @@ -116,17 +113,20 @@ public: bool complete() const; bool haveFiredLoadEvent() const { return m_imageLoader.haveFiredLoadEvent(); } -protected: + + virtual void getSubresourceAttributeStrings(Vector<String>&) const; + +private: HTMLImageLoader m_imageLoader; String usemap; bool ismap; HTMLFormElement* m_form; - String oldNameAttr; - String oldIdAttr; + AtomicString m_name; + AtomicString m_id; CompositeOperator m_compositeOperator; #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name and m_id are removed from HTMLDocument's NameCountMap int oldNameIdCount; #endif }; diff --git a/WebCore/html/HTMLImageLoader.cpp b/WebCore/html/HTMLImageLoader.cpp index f7fecb6..22e3abc 100644 --- a/WebCore/html/HTMLImageLoader.cpp +++ b/WebCore/html/HTMLImageLoader.cpp @@ -24,124 +24,42 @@ #include "CSSHelper.h" #include "CachedImage.h" -#include "DocLoader.h" -#include "Document.h" #include "Element.h" #include "EventNames.h" #include "HTMLNames.h" -#include "RenderImage.h" - -using namespace std; +#include "HTMLObjectElement.h" namespace WebCore { -using namespace EventNames; -using namespace HTMLNames; - -HTMLImageLoader::HTMLImageLoader(Element* elt) - : m_element(elt) - , m_image(0) - , m_firedLoad(true) - , m_imageComplete(true) - , m_loadManually(false) +HTMLImageLoader::HTMLImageLoader(Element* node) + : ImageLoader(node) { } HTMLImageLoader::~HTMLImageLoader() { - if (m_image) - m_image->deref(this); - m_element->document()->removeImage(this); } -void HTMLImageLoader::setImage(CachedImage *newImage) +void HTMLImageLoader::dispatchLoadEvent() { - CachedImage *oldImage = m_image; - if (newImage != oldImage) { - setLoadingImage(newImage); - m_firedLoad = true; - m_imageComplete = true; - if (newImage) - newImage->ref(this); - if (oldImage) - oldImage->deref(this); + if (!haveFiredLoadEvent() && image()) { + setHaveFiredLoadEvent(true); + element()->dispatchEventForType(image()->errorOccurred() ? eventNames().errorEvent : eventNames().loadEvent, false, false); } - - if (RenderObject* renderer = element()->renderer()) - if (renderer->isImage()) - static_cast<RenderImage*>(renderer)->resetAnimation(); } -void HTMLImageLoader::setLoadingImage(CachedImage *loadingImage) +String HTMLImageLoader::sourceURI(const AtomicString& attr) const { - m_firedLoad = false; - m_imageComplete = false; - m_image = loadingImage; + return parseURL(attr); } -void HTMLImageLoader::updateFromElement() +void HTMLImageLoader::notifyFinished(CachedResource* image) { - // If we're not making renderers for the page, then don't load images. We don't want to slow - // down the raw HTML parsing case by loading images we don't intend to display. Element* elem = element(); - Document* doc = elem->document(); - if (!doc->renderer()) - return; - - AtomicString attr = elem->getAttribute(elem->imageSourceAttributeName()); - - // Treat a lack of src or empty string for src as no image at all. - CachedImage *newImage = 0; - if (!attr.isEmpty()) { - if (m_loadManually) { - doc->docLoader()->setAutoLoadImages(false); - newImage = new CachedImage(doc->docLoader(), parseURL(attr), false /* not for cache */); - newImage->setLoading(true); - newImage->setDocLoader(doc->docLoader()); - doc->docLoader()->m_docResources.set(newImage->url(), newImage); - } else - newImage = doc->docLoader()->requestImage(parseURL(attr)); - } - - CachedImage *oldImage = m_image; - if (newImage != oldImage) { -#ifdef INSTRUMENT_LAYOUT_SCHEDULING - if (!doc->ownerElement() && newImage) - printf("Image requested at %d\n", doc->elapsedTime()); -#endif - setLoadingImage(newImage); - if (newImage) - newImage->ref(this); - if (oldImage) - oldImage->deref(this); - } - - if (RenderObject* renderer = elem->renderer()) - if (renderer->isImage()) - static_cast<RenderImage*>(renderer)->resetAnimation(); -} - -void HTMLImageLoader::dispatchLoadEvent() -{ - if (!haveFiredLoadEvent() && image()) { - setHaveFiredLoadEvent(true); - element()->dispatchHTMLEvent(image()->errorOccurred() ? errorEvent : loadEvent, false, false); - } -} + ImageLoader::notifyFinished(image); -void HTMLImageLoader::notifyFinished(CachedResource *image) -{ - m_imageComplete = true; - Element* elem = element(); - Document* doc = elem->document(); - doc->dispatchImageLoadEventSoon(this); -#ifdef INSTRUMENT_LAYOUT_SCHEDULING - if (!doc->ownerElement()) - printf("Image loaded at %d\n", doc->elapsedTime()); -#endif - if (RenderObject* renderer = elem->renderer()) - if (renderer->isImage()) - static_cast<RenderImage*>(renderer)->setCachedImage(m_image); + if (image->errorOccurred() && elem->hasTagName(HTMLNames::objectTag)) + static_cast<HTMLObjectElement*>(elem)->renderFallbackContent(); } } diff --git a/WebCore/html/HTMLImageLoader.h b/WebCore/html/HTMLImageLoader.h index b0ebd48..9e9564b 100644 --- a/WebCore/html/HTMLImageLoader.h +++ b/WebCore/html/HTMLImageLoader.h @@ -25,46 +25,21 @@ #ifndef HTMLImageLoader_h #define HTMLImageLoader_h -#include "CachedResourceClient.h" +#include "ImageLoader.h" namespace WebCore { -class Element; - -class HTMLImageLoader : public CachedResourceClient { +class HTMLImageLoader : public ImageLoader { public: HTMLImageLoader(Element*); virtual ~HTMLImageLoader(); - virtual void updateFromElement(); - virtual void dispatchLoadEvent(); + virtual String sourceURI(const AtomicString&) const; - Element* element() const { return m_element; } - bool imageComplete() const { return m_imageComplete; } - - CachedImage* image() const { return m_image; } - void setImage(CachedImage*); - - void setLoadManually(bool loadManually) { m_loadManually = loadManually; } - - // CachedResourceClient API virtual void notifyFinished(CachedResource*); - - bool haveFiredLoadEvent() const { return m_firedLoad; } -protected: - void setLoadingImage(CachedImage*); - - void setHaveFiredLoadEvent(bool firedLoad) { m_firedLoad = firedLoad; } - -private: - Element* m_element; - CachedImage* m_image; - bool m_firedLoad : 1; - bool m_imageComplete : 1; - bool m_loadManually : 1; }; -} //namespace +} #endif diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp index e9c2267..cebfb51 100644 --- a/WebCore/html/HTMLInputElement.cpp +++ b/WebCore/html/HTMLInputElement.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, 2008 Apple Inc. All rights reserved. * (C) 2006 Alexey Proskuryakov (ap@nypop.com) * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) * @@ -33,6 +33,8 @@ #include "Event.h" #include "EventHandler.h" #include "EventNames.h" +#include "File.h" +#include "FileList.h" #include "FocusController.h" #include "FormDataList.h" #include "Frame.h" @@ -46,10 +48,10 @@ #include "RenderButton.h" #include "RenderFileUploadControl.h" #include "RenderImage.h" +#include "RenderSlider.h" #include "RenderText.h" #include "RenderTextControl.h" #include "RenderTheme.h" -#include "RenderSlider.h" #include "SelectionController.h" #include "TextBreakIterator.h" #include "TextEvent.h" @@ -57,9 +59,7 @@ #include "FrameLoader.h" #endif #ifdef ANDROID // multiple additions: see below -#include "FrameAndroid.h" -#include "FrameView.h" -#include "WebCoreViewBridge.h" +#include "WebViewCore.h" #endif #include "TextIterator.h" @@ -67,7 +67,6 @@ using namespace std; namespace WebCore { -using namespace EventNames; using namespace HTMLNames; const int maxSavedResults = 256; @@ -130,10 +129,11 @@ void HTMLInputElement::init() m_haveType = false; m_activeSubmit = false; - m_autocomplete = true; + m_autocomplete = Uninitialized; m_inited = false; m_autofilled = false; - + m_placeholderShouldBeVisible = false; + xPos = 0; yPos = 0; @@ -141,15 +141,12 @@ void HTMLInputElement::init() cachedSelEnd = -1; m_maxResults = -1; - - if (form()) - m_autocomplete = form()->autoComplete(); } HTMLInputElement::~HTMLInputElement() { - if (inputType() == PASSWORD) - document()->unregisterForCacheCallbacks(this); + if (needsActivationCallback()) + document()->unregisterForDocumentActivationCallbacks(this); document()->checkedRadioButtons().removeButton(this); @@ -163,6 +160,20 @@ const AtomicString& HTMLInputElement::name() const return m_name.isNull() ? emptyAtom : m_name; } +bool HTMLInputElement::autoComplete() const +{ + if (m_autocomplete != Uninitialized) + return m_autocomplete == On; + + // Assuming we're still in a Form, respect the Form's setting + if (HTMLFormElement* form = this->form()) + return form->autoComplete(); + + // The default is true + return true; +} + + static inline HTMLFormElement::CheckedRadioButtons& checkedRadioButtons(const HTMLInputElement *element) { if (HTMLFormElement* form = element->form()) @@ -242,6 +253,7 @@ void HTMLInputElement::dispatchFocusEvent() { if (isTextField()) { setAutofilled(false); + updatePlaceholderVisibility(); if (inputType() == PASSWORD && document()->frame()) document()->setUseSecureKeyboardEntryWhenActive(true); } @@ -251,6 +263,7 @@ void HTMLInputElement::dispatchFocusEvent() void HTMLInputElement::dispatchBlurEvent() { if (isTextField() && document()->frame()) { + updatePlaceholderVisibility(); if (inputType() == PASSWORD) document()->setUseSecureKeyboardEntryWhenActive(false); document()->frame()->textFieldDidEndEditing(this); @@ -276,8 +289,7 @@ void HTMLInputElement::setInputType(const String& t) { if (document()->focusedNode() == this) { - WebCoreViewBridge* viewImpl = document()->frame()->view()->getWebCoreViewBridge(); - viewImpl->updateTextfield(this, true, String()); + android::WebViewCore::getWebViewCore(document()->view())->updateTextfield(this, true, String()); } #endif newType = PASSWORD; @@ -320,7 +332,10 @@ void HTMLInputElement::setInputType(const String& t) else { checkedRadioButtons(this).removeButton(this); - bool wasAttached = m_attached; + if (newType == FILE && !m_fileList) + m_fileList = FileList::create(); + + bool wasAttached = attached(); if (wasAttached) detach(); @@ -342,22 +357,25 @@ void HTMLInputElement::setInputType(const String& t) recheckValue(); if (wasPasswordField && !isPasswordField) - document()->unregisterForCacheCallbacks(this); + unregisterForActivationCallbackIfNeeded(); else if (!wasPasswordField && isPasswordField) - document()->registerForCacheCallbacks(this); + registerForActivationCallbackIfNeeded(); if (didRespectHeightAndWidth != willRespectHeightAndWidth) { NamedMappedAttrMap* map = mappedAttributes(); - if (MappedAttribute* height = map->getAttributeItem(heightAttr)) + if (Attribute* height = map->getAttributeItem(heightAttr)) attributeChanged(height, false); - if (MappedAttribute* width = map->getAttributeItem(widthAttr)) + if (Attribute* width = map->getAttributeItem(widthAttr)) attributeChanged(width, false); - if (MappedAttribute* align = map->getAttributeItem(alignAttr)) + if (Attribute* align = map->getAttributeItem(alignAttr)) attributeChanged(align, false); } - if (wasAttached) + if (wasAttached) { attach(); + if (document()->focusedNode() == this) + updateFocusAppearance(true); + } checkedRadioButtons(this).addButton(this); } @@ -428,6 +446,9 @@ const AtomicString& HTMLInputElement::type() const bool HTMLInputElement::saveState(String& result) const { + if (!autoComplete()) + return false; + switch (inputType()) { case BUTTON: case FILE: @@ -602,7 +623,17 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr) m_name = attr->value(); checkedRadioButtons(this).addButton(this); } else if (attr->name() == autocompleteAttr) { - m_autocomplete = !equalIgnoringCase(attr->value(), "off"); + if (equalIgnoringCase(attr->value(), "off")) { + m_autocomplete = Off; + registerForActivationCallbackIfNeeded(); + } else { + if (m_autocomplete == Off) + unregisterForActivationCallbackIfNeeded(); + if (attr->isEmpty()) + m_autocomplete = Uninitialized; + else + m_autocomplete = On; + } } else if (attr->name() == typeAttr) { setInputType(attr->value()); } else if (attr->name() == valueAttr) { @@ -639,35 +670,35 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr) attr->name() == accesskeyAttr) { // FIXME: ignore for the moment } else if (attr->name() == vspaceAttr) { - addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value()); + addCSSLength(attr, CSSPropertyMarginTop, attr->value()); + addCSSLength(attr, CSSPropertyMarginBottom, attr->value()); } else if (attr->name() == hspaceAttr) { - addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value()); + addCSSLength(attr, CSSPropertyMarginLeft, attr->value()); + addCSSLength(attr, CSSPropertyMarginRight, attr->value()); } else if (attr->name() == alignAttr) { if (inputType() == IMAGE) addHTMLAlignment(attr); } else if (attr->name() == widthAttr) { if (respectHeightAndWidthAttrs()) - addCSSLength(attr, CSS_PROP_WIDTH, attr->value()); + addCSSLength(attr, CSSPropertyWidth, attr->value()); } else if (attr->name() == heightAttr) { if (respectHeightAndWidthAttrs()) - addCSSLength(attr, CSS_PROP_HEIGHT, attr->value()); + addCSSLength(attr, CSSPropertyHeight, attr->value()); } else if (attr->name() == onfocusAttr) { - setHTMLEventListener(focusEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().focusEvent, attr); } else if (attr->name() == onblurAttr) { - setHTMLEventListener(blurEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().blurEvent, attr); } else if (attr->name() == onselectAttr) { - setHTMLEventListener(selectEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().selectEvent, attr); } else if (attr->name() == onchangeAttr) { - setHTMLEventListener(changeEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().changeEvent, attr); } else if (attr->name() == oninputAttr) { - setHTMLEventListener(inputEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().inputEvent, attr); } // Search field and slider attributes all just cause updateFromElement to be called through style // recalcing. else if (attr->name() == onsearchAttr) { - setHTMLEventListener(searchEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().searchEvent, attr); } else if (attr->name() == resultsAttr) { int oldResults = m_maxResults; m_maxResults = !attr->isNull() ? min(attr->value().toInt(), maxSavedResults) : -1; @@ -678,14 +709,16 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr) attach(); } setChanged(); - } else if (attr->name() == autosaveAttr || + } else if (attr->name() == placeholderAttr) + updatePlaceholderVisibility(true); + else if (attr->name() == autosaveAttr || attr->name() == incrementalAttr || - attr->name() == placeholderAttr || attr->name() == minAttr || attr->name() == maxAttr || - attr->name() == precisionAttr) { + attr->name() == multipleAttr || + attr->name() == precisionAttr) setChanged(); - } else + else HTMLFormControlElementWithState::parseMappedAttribute(attr); } @@ -860,20 +893,23 @@ bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart) } break; - case FILE: + case FILE: { // Can't submit file on GET. if (!multipart) return false; // If no filename at all is entered, return successful but empty. // Null would be more logical, but Netscape posts an empty file. Argh. - if (value().isEmpty()) { - encoding.appendData(name(), String("")); + unsigned numFiles = m_fileList->length(); + if (!numFiles) { + encoding.appendFile(name(), File::create("")); return true; } - encoding.appendFile(name(), value()); + for (unsigned i = 0; i < numFiles; ++i) + encoding.appendFile(name(), m_fileList->item(i)); return true; + } } return false; } @@ -939,17 +975,22 @@ void HTMLInputElement::copyNonAttributeProperties(const Element *source) String HTMLInputElement::value() const { - String value = m_value; + // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control + // but we don't want to break existing websites, who may be relying on being able to get the file name as a value. + if (inputType() == FILE) { + if (!m_fileList->isEmpty()) + return m_fileList->item(0)->fileName(); + return String(); + } - // It's important *not* to fall back to the value attribute for file inputs, - // because that would allow a malicious web page to upload files by setting the - // value attribute in markup. - if (value.isNull() && inputType() != FILE) + String value = m_value; + if (value.isNull()) { value = constrainValue(getAttribute(valueAttr)); - // If no attribute exists, then just use "on" or "" based off the checked() state of the control. - if (value.isNull() && (inputType() == CHECKBOX || inputType() == RADIO)) - return checked() ? "on" : ""; + // If no attribute exists, then just use "on" or "" based off the checked() state of the control. + if (value.isNull() && (inputType() == CHECKBOX || inputType() == RADIO)) + return checked() ? "on" : ""; + } return value; } @@ -985,14 +1026,23 @@ String HTMLInputElement::valueWithDefault() const void HTMLInputElement::setValue(const String& value) { // For security reasons, we don't allow setting the filename, but we do allow clearing it. + // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control + // but we don't want to break existing websites, who may be relying on this method to clear things. if (inputType() == FILE && !value.isEmpty()) return; + if (isTextField()) + updatePlaceholderVisibility(); + setValueMatchesRenderer(false); if (storesValueSeparateFromAttribute()) { - m_value = constrainValue(value); - if (isTextField() && inDocument()) - document()->updateRendering(); + if (inputType() == FILE) + m_fileList->clear(); + else { + m_value = constrainValue(value); + if (isTextField() && inDocument()) + document()->updateRendering(); + } if (renderer()) renderer()->updateFromElement(); setChanged(); @@ -1007,8 +1057,7 @@ void HTMLInputElement::setValue(const String& value) #else { // Make sure our UI side textfield changes to match the RenderTextControl - WebCoreViewBridge* viewImpl = document()->frame()->view()->getWebCoreViewBridge(); - viewImpl->updateTextfield(this, false, value); + android::WebViewCore::getWebViewCore(document()->view())->updateTextfield(this, false, value); setSelectionRange(max, max); } #endif @@ -1024,6 +1073,12 @@ void HTMLInputElement::setValueFromRenderer(const String& value) // Renderer and our event handler are responsible for constraining values. ASSERT(value == constrainValue(value) || constrainValue(value).isEmpty()); + // File upload controls will always use setFileListFromRenderer. + ASSERT (inputType() != FILE); + + if (isTextField()) + updatePlaceholderVisibility(); + // Workaround for bug where trailing \n is included in the result of textContent. // The assert macro above may also be simplified to: value == constrainValue(value) // http://bugs.webkit.org/show_bug.cgi?id=9661 @@ -1035,7 +1090,17 @@ void HTMLInputElement::setValueFromRenderer(const String& value) setValueMatchesRenderer(); // Fire the "input" DOM event. - dispatchHTMLEvent(inputEvent, true, false); + dispatchEventForType(eventNames().inputEvent, true, false); +} + +void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths) +{ + m_fileList->clear(); + int size = paths.size(); + for (int i = 0; i < size; i++) + m_fileList->append(File::create(paths[i])); + + setValueMatchesRenderer(); } bool HTMLInputElement::storesValueSeparateFromAttribute() const @@ -1066,7 +1131,7 @@ void* HTMLInputElement::preDispatchEventHandler(Event *evt) // This result gives us enough info to perform the "undo" in postDispatch of the action we take here. void* result = 0; if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent() - && evt->type() == clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { + && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { if (inputType() == CHECKBOX) { // As a way to store the state, we return 0 if we were unchecked, 1 if we were checked, and 2 for // indeterminate. @@ -1104,7 +1169,7 @@ void* HTMLInputElement::preDispatchEventHandler(Event *evt) void HTMLInputElement::postDispatchEventHandler(Event *evt, void* data) { if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent() - && evt->type() == clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { + && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { if (inputType() == CHECKBOX) { // Reverse the checking we did in preDispatch. if (evt->defaultPrevented() || evt->defaultHandled()) { @@ -1139,10 +1204,10 @@ void HTMLInputElement::defaultEventHandler(Event* evt) { bool clickDefaultFormButton = false; - if (isTextField() && evt->type() == textInputEvent && evt->isTextEvent() && static_cast<TextEvent*>(evt)->data() == "\n") + if (isTextField() && evt->type() == eventNames().textInputEvent && evt->isTextEvent() && static_cast<TextEvent*>(evt)->data() == "\n") clickDefaultFormButton = true; - if (inputType() == IMAGE && evt->isMouseEvent() && evt->type() == clickEvent) { + if (inputType() == IMAGE && evt->isMouseEvent() && evt->type() == eventNames().clickEvent) { // record the mouse position for when we get the DOMActivate event MouseEvent* me = static_cast<MouseEvent*>(evt); // FIXME: We could just call offsetX() and offsetY() on the event, @@ -1159,14 +1224,14 @@ void HTMLInputElement::defaultEventHandler(Event* evt) } } - if (isTextField() && evt->type() == keydownEvent && evt->isKeyboardEvent() && focused() && document()->frame() + 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() == clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { + && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { evt->setDefaultHandled(); return; } @@ -1182,7 +1247,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt) // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element // must dispatch a DOMActivate event - a click event will not do the job. - if (evt->type() == DOMActivateEvent && !disabled()) { + if (evt->type() == eventNames().DOMActivateEvent && !disabled()) { if (inputType() == IMAGE || inputType() == SUBMIT || inputType() == RESET) { if (!form()) return; @@ -1206,7 +1271,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt) // Use key press event here since sending simulated mouse events // on key down blocks the proper sending of the key press event. - if (evt->type() == keypressEvent && evt->isKeyboardEvent()) { + if (evt->type() == eventNames().keypressEvent && evt->isKeyboardEvent()) { bool clickElement = false; int charCode = static_cast<KeyboardEvent*>(evt)->charCode(); @@ -1263,7 +1328,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt) } } - if (evt->type() == keydownEvent && evt->isKeyboardEvent()) { + if (evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent()) { String key = static_cast<KeyboardEvent*>(evt)->keyIdentifier(); if (key == "U+0020") { @@ -1322,7 +1387,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt) #endif } - if (evt->type() == keyupEvent && evt->isKeyboardEvent()) { + if (evt->type() == eventNames().keyupEvent && evt->isKeyboardEvent()) { bool clickElement = false; String key = static_cast<KeyboardEvent*>(evt)->keyIdentifier(); @@ -1388,7 +1453,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt) // Make sure that the text to be inserted will not violate the maxLength. int oldLen = numGraphemeClusters(value().impl()); ASSERT(oldLen <= maxLength()); - int selectionLen = numGraphemeClusters(plainText(document()->frame()->selectionController()->selection().toRange().get()).impl()); + int selectionLen = numGraphemeClusters(plainText(document()->frame()->selection()->selection().toRange().get()).impl()); ASSERT(oldLen >= selectionLen); int maxNewLen = maxLength() - (oldLen - selectionLen); @@ -1397,12 +1462,12 @@ void HTMLInputElement::defaultEventHandler(Event* evt) textEvent->setText(constrainValue(textEvent->text(), maxNewLen)); } - if (isTextField() && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == blurEvent || evt->type() == focusEvent)) + if (isTextField() && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == eventNames().blurEvent || evt->type() == eventNames().focusEvent)) static_cast<RenderTextControl*>(renderer())->forwardEvent(evt); if (inputType() == RANGE && renderer()) { RenderSlider* slider = static_cast<RenderSlider*>(renderer()); - if (evt->isMouseEvent() && evt->type() == mousedownEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { + 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()); @@ -1494,7 +1559,7 @@ void HTMLInputElement::setSize(unsigned _size) setAttribute(sizeAttr, String::number(_size)); } -String HTMLInputElement::src() const +KURL HTMLInputElement::src() const { return document()->completeURL(getAttribute(srcAttr)); } @@ -1514,6 +1579,13 @@ void HTMLInputElement::setUseMap(const String &value) setAttribute(usemapAttr, value); } +FileList* HTMLInputElement::files() +{ + if (inputType() != FILE) + return 0; + return m_fileList.get(); +} + String HTMLInputElement::constrainValue(const String& proposedValue) const { return constrainValue(proposedValue, m_maxLen); @@ -1527,10 +1599,45 @@ void HTMLInputElement::recheckValue() setValue(newValue); } +bool HTMLInputElement::needsActivationCallback() +{ + return inputType() == PASSWORD || m_autocomplete == Off; +} + +void HTMLInputElement::registerForActivationCallbackIfNeeded() +{ + if (needsActivationCallback()) + document()->registerForDocumentActivationCallbacks(this); +} + +void HTMLInputElement::unregisterForActivationCallbackIfNeeded() +{ + if (!needsActivationCallback()) + document()->unregisterForDocumentActivationCallbacks(this); +} + +void HTMLInputElement::updatePlaceholderVisibility(bool placeholderValueChanged) +{ + ASSERT(isTextField()); + + bool oldPlaceholderShouldBeVisible = m_placeholderShouldBeVisible; + + m_placeholderShouldBeVisible = value().isEmpty() + && document()->focusedNode() != this + && !getAttribute(placeholderAttr).isEmpty(); + + if ((oldPlaceholderShouldBeVisible != m_placeholderShouldBeVisible || placeholderValueChanged) && renderer()) + static_cast<RenderTextControl*>(renderer())->updatePlaceholderVisibility(); +} + String HTMLInputElement::constrainValue(const String& proposedValue, int maxLen) const { + String string = proposedValue; if (isTextField()) { - StringImpl* s = proposedValue.impl(); + string.replace("\r\n", " "); + string.replace('\r', ' '); + string.replace('\n', ' '); + StringImpl* s = string.impl(); int newLen = numCharactersInGraphemeClusters(s, maxLen); for (int i = 0; i < newLen; ++i) { const UChar current = (*s)[i]; @@ -1539,10 +1646,10 @@ String HTMLInputElement::constrainValue(const String& proposedValue, int maxLen) break; } } - if (newLen < static_cast<int>(proposedValue.length())) - return proposedValue.substring(0, newLen); + if (newLen < static_cast<int>(string.length())) + return string.substring(0, newLen); } - return proposedValue; + return string; } void HTMLInputElement::addSearchResult() @@ -1557,7 +1664,7 @@ void HTMLInputElement::onSearch() ASSERT(isSearchField()); if (renderer()) static_cast<RenderTextControl*>(renderer())->stopSearchEventTimer(); - dispatchHTMLEvent(searchEvent, true, false); + dispatchEventForType(eventNames().searchEvent, true, false); } Selection HTMLInputElement::selection() const @@ -1567,16 +1674,17 @@ Selection HTMLInputElement::selection() const return static_cast<RenderTextControl*>(renderer())->selection(cachedSelStart, cachedSelEnd); } -void HTMLInputElement::didRestoreFromCache() +void HTMLInputElement::documentDidBecomeActive() { - ASSERT(inputType() == PASSWORD); + ASSERT(needsActivationCallback()); reset(); } void HTMLInputElement::willMoveToNewOwnerDocument() { - if (inputType() == PASSWORD) - document()->unregisterForCacheCallbacks(this); + // Always unregister for cache callbacks when leaving a document, even if we would otherwise like to be registered + if (needsActivationCallback()) + document()->unregisterForDocumentActivationCallbacks(this); document()->checkedRadioButtons().removeButton(this); @@ -1585,10 +1693,20 @@ void HTMLInputElement::willMoveToNewOwnerDocument() void HTMLInputElement::didMoveToNewOwnerDocument() { - if (inputType() == PASSWORD) - document()->registerForCacheCallbacks(this); + registerForActivationCallbackIfNeeded(); HTMLFormControlElementWithState::didMoveToNewOwnerDocument(); } +void HTMLInputElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + urls.append(src().string()); +} + +bool HTMLInputElement::willValidate() const +{ + // FIXME: This shall check for new WF2 input types too + return HTMLFormControlElementWithState::willValidate() && inputType() != HIDDEN && + inputType() != BUTTON && inputType() != RESET; +} } // namespace diff --git a/WebCore/html/HTMLInputElement.h b/WebCore/html/HTMLInputElement.h index 410f2e1..7f090a8 100644 --- a/WebCore/html/HTMLInputElement.h +++ b/WebCore/html/HTMLInputElement.h @@ -24,12 +24,14 @@ #ifndef HTMLInputElement_h #define HTMLInputElement_h -#include "HTMLGenericFormElement.h" +#include "HTMLFormControlElement.h" #include <wtf/OwnPtr.h> namespace WebCore { +class FileList; class HTMLImageLoader; +class KURL; class Selection; class HTMLInputElement : public HTMLFormControlElementWithState { @@ -49,6 +51,12 @@ public: SEARCH, RANGE }; + + enum AutoCompleteSetting { + Uninitialized, + On, + Off + }; HTMLInputElement(Document*, HTMLFormElement* = 0); HTMLInputElement(const QualifiedName& tagName, Document*, HTMLFormElement* = 0); @@ -68,7 +76,7 @@ public: virtual const AtomicString& name() const; - bool autoComplete() const { return m_autocomplete; } + bool autoComplete() const; // isChecked is used by the rendering tree/CSS while checked() is used by JS to determine checked state virtual bool isChecked() const { return checked() && (inputType() == CHECKBOX || inputType() == RADIO); } @@ -76,11 +84,14 @@ public: bool readOnly() const { return isReadOnlyControl(); } + virtual bool isTextControl() const { return isTextField(); } + bool isTextButton() const { return m_type == SUBMIT || m_type == RESET || m_type == BUTTON; } virtual bool isRadioButton() const { return m_type == RADIO; } bool isTextField() const { return m_type == TEXT || m_type == PASSWORD || m_type == SEARCH || m_type == ISINDEX; } bool isSearchField() const { return m_type == SEARCH; } virtual bool isInputTypeHidden() const { return m_type == HIDDEN; } + virtual bool isPasswordField() const { return m_type == PASSWORD; } bool checked() const { return m_checked; } void setChecked(bool, bool sendChangeEvent = false); @@ -97,6 +108,7 @@ public: String valueWithDefault() const; void setValueFromRenderer(const String&); + void setFileListFromRenderer(const Vector<String>&); virtual bool saveState(String& value) const; virtual void restoreState(const String&); @@ -166,7 +178,7 @@ public: void setSize(unsigned); - String src() const; + KURL src() const; void setSrc(const String&); void setMaxLength(int); @@ -176,7 +188,9 @@ public: bool autofilled() const { return m_autofilled; } void setAutofilled(bool b = true) { m_autofilled = b; } - + + FileList* files(); + void cacheSelection(int s, int e) { cachedSelStart = s; cachedSelEnd = e; }; void addSearchResult(); void onSearch(); @@ -185,7 +199,13 @@ public: String constrainValue(const String& proposedValue) const; - virtual void didRestoreFromCache(); + virtual void documentDidBecomeActive(); + + virtual void getSubresourceAttributeStrings(Vector<String>&) const; + + virtual bool willValidate() const; + + bool placeholderShouldBeVisible() const { return m_placeholderShouldBeVisible; } protected: virtual void willMoveToNewOwnerDocument(); @@ -198,7 +218,13 @@ private: bool storesValueSeparateFromAttribute() const; String constrainValue(const String& proposedValue, int maxLen) const; void recheckValue(); + + bool needsActivationCallback(); + void registerForActivationCallbackIfNeeded(); + void unregisterForActivationCallbackIfNeeded(); + void updatePlaceholderVisibility(bool placeholderValueChanged = false); + String m_value; String m_originalValue; int xPos; @@ -210,6 +236,8 @@ private: OwnPtr<HTMLImageLoader> m_imageLoader; + RefPtr<FileList> m_fileList; + unsigned m_type : 4; // InputType bool m_checked : 1; bool m_defaultChecked : 1; @@ -217,9 +245,10 @@ private: bool m_indeterminate : 1; bool m_haveType : 1; bool m_activeSubmit : 1; - bool m_autocomplete : 1; + unsigned m_autocomplete : 2; // AutoCompleteSetting bool m_autofilled : 1; bool m_inited : 1; + bool m_placeholderShouldBeVisible : 1; int cachedSelStart; int cachedSelEnd; diff --git a/WebCore/html/HTMLInputElement.idl b/WebCore/html/HTMLInputElement.idl index 29522be..a9b6d2c 100644 --- a/WebCore/html/HTMLInputElement.idl +++ b/WebCore/html/HTMLInputElement.idl @@ -21,7 +21,7 @@ module html { interface [ - LegacyParent=JSHTMLInputElementBase, + CustomGetOwnPropertySlot, GenerateConstructor, InterfaceUUID=8f388ea3-1c31-4cca-8edd-449d14e222e1, ImplementationUUID=aeb56b87-a90e-4d9d-a4d5-7eec3687c338 @@ -35,6 +35,7 @@ module html { attribute [ConvertNullToNullString] DOMString alt; attribute boolean checked; attribute boolean disabled; + attribute boolean autofocus; attribute long maxLength; attribute [ConvertNullToNullString] DOMString name; attribute boolean readOnly; @@ -45,33 +46,31 @@ module html { attribute unsigned long size; // Changed string -> long as part of DOM level 2 #endif attribute [ConvertNullToNullString] DOMString src; - attribute long tabIndex; attribute [ConvertNullToNullString] DOMString type; // readonly dropped as part of DOM level 2 attribute [ConvertNullToNullString] DOMString useMap; attribute [ConvertNullToNullString] DOMString value; - - void blur(); - void focus(); + readonly attribute boolean willValidate; void select(); void click(); // WinIE extension: attribute boolean indeterminate; - + // WinIE & FireFox extension: - - // Handled by JSHTMLInputElementBase to allow hiding based on input type -#if !defined(LANGUAGE_JAVASCRIPT) - attribute long selectionStart; - attribute long selectionEnd; + + attribute [CustomGetter] long selectionStart; + attribute [CustomGetter] long selectionEnd; void setSelectionRange(in long start, in long end); -#endif #if defined(LANGUAGE_OBJECTIVE_C) // Objective-C extension: readonly attribute DOMString altDisplayString; readonly attribute URL absoluteImageURL; #endif + +#if !defined(LANGUAGE_COM) + readonly attribute FileList files; +#endif }; } diff --git a/WebCore/html/HTMLIsIndexElement.cpp b/WebCore/html/HTMLIsIndexElement.cpp index fe2acbd..2abc23f 100644 --- a/WebCore/html/HTMLIsIndexElement.cpp +++ b/WebCore/html/HTMLIsIndexElement.cpp @@ -45,7 +45,7 @@ void HTMLIsIndexElement::parseMappedAttribute(MappedAttribute* attr) else // don't call HTMLInputElement::parseMappedAttribute here, as it would // accept attributes this element does not support - HTMLGenericFormElement::parseMappedAttribute(attr); + HTMLFormControlElement::parseMappedAttribute(attr); } String HTMLIsIndexElement::prompt() const diff --git a/WebCore/html/HTMLKeygenElement.cpp b/WebCore/html/HTMLKeygenElement.cpp index 509d415..b918d78 100644 --- a/WebCore/html/HTMLKeygenElement.cpp +++ b/WebCore/html/HTMLKeygenElement.cpp @@ -31,7 +31,6 @@ #include "FormDataList.h" #include "HTMLNames.h" #include "HTMLOptionElement.h" -#include "KURL.h" #include "SSLKeyGenerator.h" #include "Text.h" @@ -44,7 +43,8 @@ using namespace HTMLNames; HTMLKeygenElement::HTMLKeygenElement(Document* doc, HTMLFormElement* f) : HTMLSelectElement(keygenTag, doc, f) { - Vector<String> keys = supportedKeySizes(); + Vector<String> keys; + getSupportedKeySizes(keys); Vector<String>::const_iterator end = keys.end(); for (Vector<String>::const_iterator it = keys.begin(); it != end; ++it) { @@ -68,7 +68,7 @@ void HTMLKeygenElement::parseMappedAttribute(MappedAttribute* attr) m_keyType = attr->value(); else // skip HTMLSelectElement parsing! - HTMLGenericFormElement::parseMappedAttribute(attr); + HTMLFormControlElement::parseMappedAttribute(attr); } bool HTMLKeygenElement::appendFormData(FormDataList& encoded_values, bool) diff --git a/WebCore/html/HTMLLIElement.cpp b/WebCore/html/HTMLLIElement.cpp index e5a0d76..6cb9304 100644 --- a/WebCore/html/HTMLLIElement.cpp +++ b/WebCore/html/HTMLLIElement.cpp @@ -60,17 +60,17 @@ void HTMLLIElement::parseMappedAttribute(MappedAttribute* attr) } } else if (attr->name() == typeAttr) { if (attr->value() == "a") - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_LOWER_ALPHA); + addCSSProperty(attr, CSSPropertyListStyleType, CSSValueLowerAlpha); else if (attr->value() == "A") - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_UPPER_ALPHA); + addCSSProperty(attr, CSSPropertyListStyleType, CSSValueUpperAlpha); else if (attr->value() == "i") - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_LOWER_ROMAN); + addCSSProperty(attr, CSSPropertyListStyleType, CSSValueLowerRoman); else if (attr->value() == "I") - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_UPPER_ROMAN); + addCSSProperty(attr, CSSPropertyListStyleType, CSSValueUpperRoman); else if (attr->value() == "1") - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_DECIMAL); + addCSSProperty(attr, CSSPropertyListStyleType, CSSValueDecimal); else - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, attr->value()); + addCSSProperty(attr, CSSPropertyListStyleType, attr->value()); } else HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLLabelElement.cpp b/WebCore/html/HTMLLabelElement.cpp index b445888..6d97bc1 100644 --- a/WebCore/html/HTMLLabelElement.cpp +++ b/WebCore/html/HTMLLabelElement.cpp @@ -34,7 +34,6 @@ namespace WebCore { using namespace HTMLNames; -using namespace EventNames; HTMLLabelElement::HTMLLabelElement(Document *doc) : HTMLElement(labelTag, doc) @@ -103,7 +102,7 @@ void HTMLLabelElement::defaultEventHandler(Event* evt) { static bool processingClick = false; - if (evt->type() == clickEvent && !processingClick) { + if (evt->type() == eventNames().clickEvent && !processingClick) { RefPtr<HTMLElement> control = correspondingControl(); // If we can't find a control or if the control received the click diff --git a/WebCore/html/HTMLLabelElement.idl b/WebCore/html/HTMLLabelElement.idl index c40aad9..85b7ef3 100644 --- a/WebCore/html/HTMLLabelElement.idl +++ b/WebCore/html/HTMLLabelElement.idl @@ -28,8 +28,6 @@ module html { readonly attribute HTMLFormElement form; attribute [ConvertNullToNullString] DOMString accessKey; attribute [ConvertNullToNullString] DOMString htmlFor; - - void focus(); }; } diff --git a/WebCore/html/HTMLLegendElement.cpp b/WebCore/html/HTMLLegendElement.cpp index 7f47861..573f06f 100644 --- a/WebCore/html/HTMLLegendElement.cpp +++ b/WebCore/html/HTMLLegendElement.cpp @@ -35,7 +35,7 @@ namespace WebCore { using namespace HTMLNames; HTMLLegendElement::HTMLLegendElement(Document *doc, HTMLFormElement *f) -: HTMLGenericFormElement(legendTag, doc, f) + : HTMLFormControlElement(legendTag, doc, f) { } @@ -45,7 +45,7 @@ HTMLLegendElement::~HTMLLegendElement() bool HTMLLegendElement::isFocusable() const { - return false; + return HTMLElement::isFocusable(); } RenderObject* HTMLLegendElement::createRenderer(RenderArena* arena, RenderStyle* style) @@ -107,6 +107,9 @@ Element *HTMLLegendElement::formElement() void HTMLLegendElement::focus(bool) { + if (isFocusable()) + Element::focus(); + // to match other browsers, never restore previous selection if (Element *element = formElement()) element->focus(false); diff --git a/WebCore/html/HTMLLegendElement.h b/WebCore/html/HTMLLegendElement.h index f48ea02..0873f34 100644 --- a/WebCore/html/HTMLLegendElement.h +++ b/WebCore/html/HTMLLegendElement.h @@ -26,11 +26,11 @@ #ifndef HTMLLegendElement_h #define HTMLLegendElement_h -#include "HTMLGenericFormElement.h" +#include "HTMLFormControlElement.h" namespace WebCore { -class HTMLLegendElement : public HTMLGenericFormElement { +class HTMLLegendElement : public HTMLFormControlElement { public: HTMLLegendElement(Document*, HTMLFormElement* = 0); virtual ~HTMLLegendElement(); diff --git a/WebCore/html/HTMLLegendElement.idl b/WebCore/html/HTMLLegendElement.idl index 8a78d77..da00cc1 100644 --- a/WebCore/html/HTMLLegendElement.idl +++ b/WebCore/html/HTMLLegendElement.idl @@ -28,8 +28,6 @@ module html { readonly attribute HTMLFormElement form; attribute [ConvertNullToNullString] DOMString accessKey; attribute [ConvertNullToNullString] DOMString align; - - void focus(); }; } diff --git a/WebCore/html/HTMLLinkElement.cpp b/WebCore/html/HTMLLinkElement.cpp index b002a0c..6cbcd80 100644 --- a/WebCore/html/HTMLLinkElement.cpp +++ b/WebCore/html/HTMLLinkElement.cpp @@ -1,10 +1,8 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003 Apple Computer, Inc. + * Copyright (C) 2003, 2008 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 @@ -21,19 +19,24 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "HTMLLinkElement.h" #include "CSSHelper.h" #include "CachedCSSStyleSheet.h" +#include "DNS.h" #include "DocLoader.h" #include "Document.h" #include "Frame.h" #include "FrameLoader.h" +#include "FrameLoaderClient.h" #include "FrameTree.h" #include "HTMLNames.h" #include "MediaList.h" #include "MediaQueryEvaluator.h" +#include "Page.h" +#include "Settings.h" namespace WebCore { @@ -47,13 +50,15 @@ HTMLLinkElement::HTMLLinkElement(Document *doc) , m_alternate(false) , m_isStyleSheet(false) , m_isIcon(false) + , m_isDNSPrefetch(false) + , m_createdByParser(false) { } HTMLLinkElement::~HTMLLinkElement() { if (m_cachedSheet) { - m_cachedSheet->deref(this); + m_cachedSheet->removeClient(this); if (m_loading && !isDisabled() && !isAlternate()) document()->removePendingSheet(); } @@ -105,20 +110,16 @@ StyleSheet* HTMLLinkElement::sheet() const void HTMLLinkElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == relAttr) { -#ifdef ANDROID_PRELOAD_CHANGES - tokenizeRelAttribute(attr->value(), m_isStyleSheet, m_alternate, m_isIcon); -#else - tokenizeRelAttribute(attr->value()); -#endif + tokenizeRelAttribute(attr->value(), m_isStyleSheet, m_alternate, m_isIcon, m_isDNSPrefetch); process(); } else if (attr->name() == hrefAttr) { - m_url = document()->completeURL(parseURL(attr->value())); + m_url = document()->completeURL(parseURL(attr->value())).string(); process(); } else if (attr->name() == typeAttr) { m_type = attr->value(); process(); } else if (attr->name() == mediaAttr) { - m_media = attr->value().domString().lower(); + m_media = attr->value().string().lower(); process(); } else if (attr->name() == disabledAttr) { setDisabledState(!attr->isNull()); @@ -129,62 +130,38 @@ void HTMLLinkElement::parseMappedAttribute(MappedAttribute *attr) } } -#ifdef ANDROID_PRELOAD_CHANGES -void HTMLLinkElement::tokenizeRelAttribute(const AtomicString& relStr, bool& styleSheet, bool& alternate, bool& icon) +void HTMLLinkElement::tokenizeRelAttribute(const AtomicString& rel, bool& styleSheet, bool& alternate, bool& icon, bool& dnsPrefetch) { styleSheet = false; icon = false; alternate = false; - String rel = relStr.domString().lower(); - if (rel == "stylesheet") + dnsPrefetch = false; + if (equalIgnoringCase(rel, "stylesheet")) styleSheet = true; - else if (rel == "icon" || rel == "shortcut icon") + else if (equalIgnoringCase(rel, "icon") || equalIgnoringCase(rel, "shortcut icon")) icon = true; - else if (rel == "alternate stylesheet" || rel == "stylesheet alternate") { + else if (equalIgnoringCase(rel, "dns-prefetch")) + dnsPrefetch = true; + else if (equalIgnoringCase(rel, "alternate stylesheet") || equalIgnoringCase(rel, "stylesheet alternate")) { styleSheet = true; alternate = true; } else { // Tokenize the rel attribute and set bits based on specific keywords that we find. - rel.replace('\n', ' '); - Vector<String> list = rel.split(' '); + String relString = rel.string(); + relString.replace('\n', ' '); + Vector<String> list; + relString.split(' ', list); Vector<String>::const_iterator end = list.end(); for (Vector<String>::const_iterator it = list.begin(); it != end; ++it) { - if (*it == "stylesheet") + if (equalIgnoringCase(*it, "stylesheet")) styleSheet = true; - else if (*it == "alternate") + else if (equalIgnoringCase(*it, "alternate")) alternate = true; - else if (*it == "icon") + else if (equalIgnoringCase(*it, "icon")) icon = true; } } } -#else -void HTMLLinkElement::tokenizeRelAttribute(const AtomicString& relStr) -{ - m_isStyleSheet = m_isIcon = m_alternate = false; - String rel = relStr.domString().lower(); - if (rel == "stylesheet") - m_isStyleSheet = true; - else if (rel == "icon" || rel == "shortcut icon") - m_isIcon = true; - else if (rel == "alternate stylesheet" || rel == "stylesheet alternate") - m_isStyleSheet = m_alternate = true; - else { - // Tokenize the rel attribute and set bits based on specific keywords that we find. - rel.replace('\n', ' '); - Vector<String> list = rel.split(' '); - Vector<String>::const_iterator end = list.end(); - for (Vector<String>::const_iterator it = list.begin(); it != end; ++it) { - if (*it == "stylesheet") - m_isStyleSheet = true; - else if (*it == "alternate") - m_alternate = true; - else if (*it == "icon") - m_isIcon = true; - } - } -} -#endif void HTMLLinkElement::process() { @@ -198,16 +175,19 @@ void HTMLLinkElement::process() if (m_isIcon && !m_url.isEmpty()) document()->setIconURL(m_url, type); + if (m_isDNSPrefetch && !m_url.isEmpty()) + prefetchDNS(KURL(m_url).host()); + // Stylesheet // This was buggy and would incorrectly match <link rel="alternate">, which has a different specified meaning. -dwh - if (m_disabledState != 2 && (type.contains("text/css") || m_isStyleSheet) && document()->frame()) { + if (m_disabledState != 2 && m_isStyleSheet && document()->frame()) { // no need to load style sheets which aren't for the screen output // ### there may be in some situations e.g. for an editor or script to manipulate // also, don't load style sheets for standalone documents MediaQueryEvaluator allEval(true); MediaQueryEvaluator screenEval("screen", true); MediaQueryEvaluator printEval("print", true); - RefPtr<MediaList> media = new MediaList((CSSStyleSheet*)0, m_media, true); + RefPtr<MediaList> media = MediaList::createAllowingDescriptionSyntax(m_media); if (allEval.eval(media.get()) || screenEval.eval(media.get()) || printEval.eval(media.get())) { // Add ourselves as a pending sheet, but only if we aren't an alternate @@ -222,12 +202,12 @@ void HTMLLinkElement::process() if (m_cachedSheet) { if (m_loading) document()->removePendingSheet(); - m_cachedSheet->deref(this); + m_cachedSheet->removeClient(this); } m_loading = true; m_cachedSheet = document()->docLoader()->requestCSSStyleSheet(m_url, chset); if (m_cachedSheet) - m_cachedSheet->ref(this); + m_cachedSheet->addClient(this); else if (!isAlternate()) { // request may have been denied if stylesheet is local and document is remote. m_loading = false; document()->removePendingSheet(); @@ -243,22 +223,43 @@ void HTMLLinkElement::process() void HTMLLinkElement::insertedIntoDocument() { HTMLElement::insertedIntoDocument(); + document()->addStyleSheetCandidateNode(this, m_createdByParser); process(); } void HTMLLinkElement::removedFromDocument() { HTMLElement::removedFromDocument(); - process(); + + // FIXME: It's terrible to do a synchronous update of the style selector just because a <style> or <link> element got removed. + if (document()->renderer()) { + document()->removeStyleSheetCandidateNode(this); + document()->updateStyleSelector(); + } +} + +void HTMLLinkElement::finishParsingChildren() +{ + m_createdByParser = false; + HTMLElement::finishParsingChildren(); } -void HTMLLinkElement::setCSSStyleSheet(const String& url, const String& charset, const String& sheetStr) +void HTMLLinkElement::setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet* sheet) { - m_sheet = new CSSStyleSheet(this, url, charset); - m_sheet->parseString(sheetStr, !document()->inCompatMode()); + m_sheet = CSSStyleSheet::create(this, url, charset); + + bool strictParsing = !document()->inCompatMode(); + bool enforceMIMEType = strictParsing; + + // Check to see if we should enforce the MIME type of the CSS resource in strict mode. + // Running in iWeb 2 is one example of where we don't want to - <rdar://problem/6099748> + if (enforceMIMEType && document()->page() && !document()->page()->settings()->enforceCSSMIMETypeInStrictMode()) + enforceMIMEType = false; + + m_sheet->parseString(sheet->sheetText(enforceMIMEType), strictParsing); m_sheet->setTitle(title()); - RefPtr<MediaList> media = new MediaList((CSSStyleSheet*)0, m_media, true); + RefPtr<MediaList> media = MediaList::createAllowingDescriptionSyntax(m_media); m_sheet->setMedia(media.get()); m_loading = false; @@ -308,7 +309,7 @@ void HTMLLinkElement::setCharset(const String& value) setAttribute(charsetAttr, value); } -String HTMLLinkElement::href() const +KURL HTMLLinkElement::href() const { return document()->completeURL(getAttribute(hrefAttr)); } @@ -378,4 +379,28 @@ void HTMLLinkElement::setType(const String& value) setAttribute(typeAttr, value); } +void HTMLLinkElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + if (m_isIcon) { + urls.append(href().string()); + return; + } + + if (!m_isStyleSheet) + return; + + // Append the URL of this link element. + urls.append(href().string()); + + // Walk the URLs linked by the linked-to stylesheet. + HashSet<String> styleURLs; + StyleSheet* styleSheet = const_cast<HTMLLinkElement*>(this)->sheet(); + if (styleSheet) + styleSheet->addSubresourceURLStrings(styleURLs, href()); + + HashSet<String>::iterator end = styleURLs.end(); + for (HashSet<String>::iterator i = styleURLs.begin(); i != end; ++i) + urls.append(*i); +} + } diff --git a/WebCore/html/HTMLLinkElement.h b/WebCore/html/HTMLLinkElement.h index b9c31e6..2fcaaa8 100644 --- a/WebCore/html/HTMLLinkElement.h +++ b/WebCore/html/HTMLLinkElement.h @@ -1,9 +1,7 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2003 Apple Computer, Inc. + * Copyright (C) 2003, 2008 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 @@ -21,19 +19,21 @@ * Boston, MA 02110-1301, USA. * */ + #ifndef HTMLLinkElement_h #define HTMLLinkElement_h -#include "HTMLElement.h" -#include "CachedResourceClient.h" #include "CSSStyleSheet.h" +#include "CachedResourceClient.h" +#include "CachedResourceHandle.h" +#include "HTMLElement.h" namespace WebCore { class CachedCSSStyleSheet; +class KURL; -class HTMLLinkElement : public HTMLElement, public CachedResourceClient -{ +class HTMLLinkElement : public HTMLElement, public CachedResourceClient { public: HTMLLinkElement(Document*); ~HTMLLinkElement(); @@ -47,7 +47,7 @@ public: String charset() const; void setCharset(const String&); - String href() const; + KURL href() const; void setHref(const String&); String hreflang() const; @@ -79,42 +79,40 @@ public: virtual void removedFromDocument(); // from CachedResourceClient - virtual void setCSSStyleSheet(const String &url, const String& charset, const String &sheet); + virtual void setCSSStyleSheet(const String &url, const String& charset, const CachedCSSStyleSheet* sheet); bool isLoading() const; virtual bool sheetLoaded(); bool isAlternate() const { return m_disabledState == 0 && m_alternate; } bool isDisabled() const { return m_disabledState == 2; } bool isEnabledViaScript() const { return m_disabledState == 1; } - + bool isIcon() const { return m_isIcon; } + int disabledState() { return m_disabledState; } void setDisabledState(bool _disabled); virtual bool isURLAttribute(Attribute*) const; -#ifdef ANDROID_PRELOAD_CHANGES - static void tokenizeRelAttribute(const AtomicString& value, bool& stylesheet, bool& alternate, bool& icon); -#else - void tokenizeRelAttribute(const AtomicString& rel); -#endif + + static void tokenizeRelAttribute(const AtomicString& value, bool& stylesheet, bool& alternate, bool& icon, bool& dnsPrefetch); + + virtual void getSubresourceAttributeStrings(Vector<String>&) const; + + void setCreatedByParser(bool createdByParser) { m_createdByParser = createdByParser; } + virtual void finishParsingChildren(); protected: - CachedCSSStyleSheet* m_cachedSheet; + CachedResourceHandle<CachedCSSStyleSheet> m_cachedSheet; RefPtr<CSSStyleSheet> m_sheet; String m_url; String m_type; String m_media; int m_disabledState; // 0=unset(default), 1=enabled via script, 2=disabled -#ifdef ANDROID_PRELOAD_CHANGES bool m_loading; bool m_alternate; bool m_isStyleSheet; bool m_isIcon; -#else - bool m_loading : 1; - bool m_alternate : 1; - bool m_isStyleSheet : 1; - bool m_isIcon : 1; -#endif + bool m_isDNSPrefetch; + bool m_createdByParser; }; } //namespace diff --git a/WebCore/html/HTMLMapElement.cpp b/WebCore/html/HTMLMapElement.cpp index 2fce481..891f560 100644 --- a/WebCore/html/HTMLMapElement.cpp +++ b/WebCore/html/HTMLMapElement.cpp @@ -80,14 +80,14 @@ void HTMLMapElement::parseMappedAttribute(MappedAttribute* attr) if (attrName == idAttr) { // Call base class so that hasID bit gets set. HTMLElement::parseMappedAttribute(attr); - if (doc->htmlMode() != Document::XHtml) + if (doc->isHTMLDocument()) return; } doc->removeImageMap(this); String mapName = attr->value(); if (mapName[0] == '#') mapName = mapName.substring(1); - m_name = doc->htmlMode() == Document::XHtml ? mapName : mapName.lower(); + m_name = doc->isHTMLDocument() ? mapName.lower() : mapName; doc->addImageMap(this); } else HTMLElement::parseMappedAttribute(attr); @@ -95,7 +95,7 @@ void HTMLMapElement::parseMappedAttribute(MappedAttribute* attr) PassRefPtr<HTMLCollection> HTMLMapElement::areas() { - return new HTMLCollection(this, HTMLCollection::MapAreas); + return HTMLCollection::create(this, HTMLCollection::MapAreas); } String HTMLMapElement::name() const diff --git a/WebCore/html/HTMLMarqueeElement.cpp b/WebCore/html/HTMLMarqueeElement.cpp index 9fe1f4d..0fd8805 100644 --- a/WebCore/html/HTMLMarqueeElement.cpp +++ b/WebCore/html/HTMLMarqueeElement.cpp @@ -28,6 +28,7 @@ #include "CSSValueKeywords.h" #include "HTMLNames.h" #include "RenderLayer.h" +#include "RenderMarquee.h" namespace WebCore { @@ -65,44 +66,44 @@ void HTMLMarqueeElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == widthAttr) { if (!attr->value().isEmpty()) - addCSSLength(attr, CSS_PROP_WIDTH, attr->value()); + addCSSLength(attr, CSSPropertyWidth, attr->value()); } else if (attr->name() == heightAttr) { if (!attr->value().isEmpty()) - addCSSLength(attr, CSS_PROP_HEIGHT, attr->value()); + addCSSLength(attr, CSSPropertyHeight, attr->value()); } else if (attr->name() == bgcolorAttr) { if (!attr->value().isEmpty()) - addCSSColor(attr, CSS_PROP_BACKGROUND_COLOR, attr->value()); + addCSSColor(attr, CSSPropertyBackgroundColor, attr->value()); } else if (attr->name() == vspaceAttr) { if (!attr->value().isEmpty()) { - addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value()); + addCSSLength(attr, CSSPropertyMarginTop, attr->value()); + addCSSLength(attr, CSSPropertyMarginBottom, attr->value()); } } else if (attr->name() == hspaceAttr) { if (!attr->value().isEmpty()) { - addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value()); + addCSSLength(attr, CSSPropertyMarginLeft, attr->value()); + addCSSLength(attr, CSSPropertyMarginRight, attr->value()); } } else if (attr->name() == scrollamountAttr) { if (!attr->value().isEmpty()) - addCSSLength(attr, CSS_PROP__WEBKIT_MARQUEE_INCREMENT, attr->value()); + addCSSLength(attr, CSSPropertyWebkitMarqueeIncrement, attr->value()); } else if (attr->name() == scrolldelayAttr) { if (!attr->value().isEmpty()) - addCSSLength(attr, CSS_PROP__WEBKIT_MARQUEE_SPEED, attr->value()); + addCSSLength(attr, CSSPropertyWebkitMarqueeSpeed, attr->value()); } else if (attr->name() == loopAttr) { if (!attr->value().isEmpty()) { if (attr->value() == "-1" || equalIgnoringCase(attr->value(), "infinite")) - addCSSProperty(attr, CSS_PROP__WEBKIT_MARQUEE_REPETITION, CSS_VAL_INFINITE); + addCSSProperty(attr, CSSPropertyWebkitMarqueeRepetition, CSSValueInfinite); else - addCSSLength(attr, CSS_PROP__WEBKIT_MARQUEE_REPETITION, attr->value()); + addCSSLength(attr, CSSPropertyWebkitMarqueeRepetition, attr->value()); } } else if (attr->name() == behaviorAttr) { if (!attr->value().isEmpty()) - addCSSProperty(attr, CSS_PROP__WEBKIT_MARQUEE_STYLE, attr->value()); + addCSSProperty(attr, CSSPropertyWebkitMarqueeStyle, attr->value()); } else if (attr->name() == directionAttr) { if (!attr->value().isEmpty()) - addCSSProperty(attr, CSS_PROP__WEBKIT_MARQUEE_DIRECTION, attr->value()); + addCSSProperty(attr, CSSPropertyWebkitMarqueeDirection, attr->value()); } else if (attr->name() == truespeedAttr) - m_minimumDelay = !attr->isNull() ? 0 : defaultMinimumDelay; + m_minimumDelay = !attr->isEmpty() ? 0 : defaultMinimumDelay; else HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLMediaElement.cpp b/WebCore/html/HTMLMediaElement.cpp index cccf0fd..f86c44d 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 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -53,7 +53,6 @@ using namespace std; namespace WebCore { -using namespace EventNames; using namespace HTMLNames; HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* doc) @@ -68,7 +67,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* doc) , m_loadedFirstFrame(false) , m_autoplaying(true) , m_currentLoop(0) - , m_volume(0.5f) + , m_volume(1.0f) , m_muted(false) , m_paused(true) , m_seeking(false) @@ -80,15 +79,15 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* doc) , m_loadNestingLevel(0) , m_terminateLoadBelowNestingLevel(0) , m_pausedInternal(false) - , m_inPageCache(false) + , m_inActiveDocument(true) , m_player(0) { - document()->registerForCacheCallbacks(this); + document()->registerForDocumentActivationCallbacks(this); } HTMLMediaElement::~HTMLMediaElement() { - document()->unregisterForCacheCallbacks(this); + document()->unregisterForDocumentActivationCallbacks(this); } bool HTMLMediaElement::checkDTD(const Node* newChild) @@ -152,6 +151,14 @@ void HTMLMediaElement::attach() renderer()->updateFromElement(); } +void HTMLMediaElement::recalcStyle(StyleChange change) +{ + HTMLElement::recalcStyle(change); + + if (renderer()) + renderer()->updateFromElement(); +} + void HTMLMediaElement::scheduleLoad() { m_loadTimer.startOneShot(0); @@ -186,7 +193,7 @@ void HTMLMediaElement::asyncEventTimerFired(Timer<HTMLMediaElement>*) m_asyncEventsToDispatch.swap(asyncEventsToDispatch); unsigned count = asyncEventsToDispatch.size(); for (unsigned n = 0; n < count; ++n) - dispatchHTMLEvent(asyncEventsToDispatch[n], false, true); + dispatchEventForType(asyncEventsToDispatch[n], false, true); } String serializeTimeOffset(float time) @@ -197,12 +204,16 @@ String serializeTimeOffset(float time) return timeString; } -float parseTimeOffset(String timeString, bool* ok = 0) +float parseTimeOffset(const String& timeString, bool* ok = 0) { - if (timeString.endsWith("s")) - timeString = timeString.left(timeString.length() - 1); + const UChar* characters = timeString.characters(); + unsigned length = timeString.length(); + + if (length && characters[length - 1] == 's') + length--; + // FIXME parse time offset values (format not specified yet) - float val = (float)timeString.toDouble(ok); + float val = charactersToFloat(characters, length, ok); return val; } @@ -226,7 +237,7 @@ PassRefPtr<MediaError> HTMLMediaElement::error() const return m_error; } -String HTMLMediaElement::src() const +KURL HTMLMediaElement::src() const { return document()->completeURL(getAttribute(srcAttr)); } @@ -273,8 +284,8 @@ void HTMLMediaElement::load(ExceptionCode& ec) // 2 if (m_begun) { m_begun = false; - m_error = new MediaError(MediaError::MEDIA_ERR_ABORTED); - initAndDispatchProgressEvent(abortEvent); + m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED); + initAndDispatchProgressEvent(eventNames().abortEvent); if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) goto end; } @@ -298,7 +309,7 @@ void HTMLMediaElement::load(ExceptionCode& ec) m_player->seek(0); } m_currentLoop = 0; - dispatchHTMLEvent(emptiedEvent, false, true); + dispatchEventForType(eventNames().emptiedEvent, false, true); if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) goto end; } @@ -318,7 +329,7 @@ void HTMLMediaElement::load(ExceptionCode& ec) // 9 m_begun = true; - dispatchProgressEvent(beginEvent, false, 0, 0); // progress event draft calls this loadstart + dispatchProgressEvent(eventNames().loadstartEvent, false, 0, 0); if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) goto end; @@ -359,12 +370,12 @@ void HTMLMediaElement::mediaPlayerNetworkStateChanged(MediaPlayer*) //delete m_player; //m_player = 0; // FIXME better error handling - m_error = new MediaError(MediaError::MEDIA_ERR_NETWORK); + m_error = MediaError::create(MediaError::MEDIA_ERR_NETWORK); m_begun = false; m_progressEventTimer.stop(); m_bufferingRate = 0; - initAndDispatchProgressEvent(errorEvent); + initAndDispatchProgressEvent(eventNames().errorEvent); if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) return; @@ -373,7 +384,7 @@ void HTMLMediaElement::mediaPlayerNetworkStateChanged(MediaPlayer*) if (isVideo()) static_cast<HTMLVideoElement*>(this)->updatePosterImage(); - dispatchHTMLEvent(emptiedEvent, false, true); + dispatchEventForType(eventNames().emptiedEvent, false, true); return; } @@ -384,11 +395,11 @@ void HTMLMediaElement::mediaPlayerNetworkStateChanged(MediaPlayer*) m_player->seek(effectiveStart()); m_networkState = LOADED_METADATA; - dispatchHTMLEvent(durationchangeEvent, false, true); + dispatchEventForType(eventNames().durationchangeEvent, false, true); if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) return; - dispatchHTMLEvent(loadedmetadataEvent, false, true); + dispatchEventForType(eventNames().loadedmetadataEvent, false, true); if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) return; } @@ -410,11 +421,11 @@ void HTMLMediaElement::mediaPlayerNetworkStateChanged(MediaPlayer*) static_cast<RenderVideo*>(renderer())->videoSizeChanged(); } - dispatchHTMLEvent(loadedfirstframeEvent, false, true); + dispatchEventForType(eventNames().loadedfirstframeEvent, false, true); if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) return; - dispatchHTMLEvent(canshowcurrentframeEvent, false, true); + dispatchEventForType(eventNames().canshowcurrentframeEvent, false, true); if (m_loadNestingLevel < m_terminateLoadBelowNestingLevel) return; } @@ -425,7 +436,7 @@ void HTMLMediaElement::mediaPlayerNetworkStateChanged(MediaPlayer*) m_networkState = LOADED; m_progressEventTimer.stop(); m_bufferingRate = 0; - initAndDispatchProgressEvent(loadEvent); + initAndDispatchProgressEvent(eventNames().loadEvent); } } @@ -451,25 +462,25 @@ void HTMLMediaElement::setReadyState(ReadyState state) return; if (state == DATA_UNAVAILABLE) { - dispatchHTMLEvent(dataunavailableEvent, false, true); + dispatchEventForType(eventNames().dataunavailableEvent, false, true); if (wasActivelyPlaying) { - dispatchHTMLEvent(timeupdateEvent, false, true); - dispatchHTMLEvent(waitingEvent, false, true); + dispatchEventForType(eventNames().timeupdateEvent, false, true); + dispatchEventForType(eventNames().waitingEvent, false, true); } } else if (state == CAN_SHOW_CURRENT_FRAME) { if (m_loadedFirstFrame) - dispatchHTMLEvent(canshowcurrentframeEvent, false, true); + dispatchEventForType(eventNames().canshowcurrentframeEvent, false, true); if (wasActivelyPlaying) { - dispatchHTMLEvent(timeupdateEvent, false, true); - dispatchHTMLEvent(waitingEvent, false, true); + dispatchEventForType(eventNames().timeupdateEvent, false, true); + dispatchEventForType(eventNames().waitingEvent, false, true); } } else if (state == CAN_PLAY) { - dispatchHTMLEvent(canplayEvent, false, true); + dispatchEventForType(eventNames().canplayEvent, false, true); } else if (state == CAN_PLAY_THROUGH) { - dispatchHTMLEvent(canplaythroughEvent, false, true); + dispatchEventForType(eventNames().canplaythroughEvent, false, true); if (m_autoplaying && m_paused && autoplay()) { m_paused = false; - dispatchHTMLEvent(playEvent, false, true); + dispatchEventForType(eventNames().playEvent, false, true); } } updatePlayState(); @@ -487,11 +498,11 @@ void HTMLMediaElement::progressEventTimerFired(Timer<HTMLMediaElement>*) if (progress == m_previousProgress) { if (timedelta > 3.0 && !m_sentStalledEvent) { m_bufferingRate = 0; - initAndDispatchProgressEvent(stalledEvent); + initAndDispatchProgressEvent(eventNames().stalledEvent); m_sentStalledEvent = true; } } else { - initAndDispatchProgressEvent(progressEvent); + initAndDispatchProgressEvent(eventNames().progressEvent); m_previousProgress = progress; m_previousProgressTime = time; m_sentStalledEvent = false; @@ -537,7 +548,7 @@ void HTMLMediaElement::seek(float time, ExceptionCode& ec) m_seeking = true; // 9 - dispatchHTMLEvent(timeupdateEvent, false, true); + dispatchEventForType(eventNames().timeupdateEvent, false, true); // 10 // As soon as the user agent has established whether or not the media data for the new playback position is available, @@ -596,7 +607,7 @@ void HTMLMediaElement::setDefaultPlaybackRate(float rate, ExceptionCode& ec) } if (m_defaultPlaybackRate != rate) { m_defaultPlaybackRate = rate; - dispatchEventAsync(ratechangeEvent); + dispatchEventAsync(eventNames().ratechangeEvent); } } @@ -613,7 +624,7 @@ void HTMLMediaElement::setPlaybackRate(float rate, ExceptionCode& ec) } if (m_player && m_player->rate() != rate) { m_player->setRate(rate); - dispatchEventAsync(ratechangeEvent); + dispatchEventAsync(eventNames().ratechangeEvent); } } @@ -650,7 +661,7 @@ void HTMLMediaElement::play(ExceptionCode& ec) if (m_paused) { m_paused = false; - dispatchEventAsync(playEvent); + dispatchEventAsync(eventNames().playEvent); } m_autoplaying = false; @@ -670,8 +681,8 @@ void HTMLMediaElement::pause(ExceptionCode& ec) if (!m_paused) { m_paused = true; - dispatchEventAsync(timeupdateEvent); - dispatchEventAsync(pauseEvent); + dispatchEventAsync(eventNames().timeupdateEvent); + dispatchEventAsync(eventNames().pauseEvent); } m_autoplaying = false; @@ -681,9 +692,9 @@ void HTMLMediaElement::pause(ExceptionCode& ec) unsigned HTMLMediaElement::playCount() const { - String val = getAttribute(playcountAttr); - int count = val.toInt(); - return max(count, 1); + bool ok; + unsigned count = getAttribute(playcountAttr).string().toUInt(&ok); + return (count > 0 && ok) ? count : 1; } void HTMLMediaElement::setPlayCount(unsigned count, ExceptionCode& ec) @@ -720,7 +731,7 @@ void HTMLMediaElement::setEnd(float time) float HTMLMediaElement::loopStart() const { - return getTimeOffsetAttribute(loopstartAttr, 0); + return getTimeOffsetAttribute(loopstartAttr, start()); } void HTMLMediaElement::setLoopStart(float time) @@ -731,7 +742,7 @@ void HTMLMediaElement::setLoopStart(float time) float HTMLMediaElement::loopEnd() const { - return getTimeOffsetAttribute(loopendAttr, std::numeric_limits<float>::infinity()); + return getTimeOffsetAttribute(loopendAttr, end()); } void HTMLMediaElement::setLoopEnd(float time) @@ -775,7 +786,7 @@ void HTMLMediaElement::setVolume(float vol, ExceptionCode& ec) if (m_volume != vol) { m_volume = vol; updateVolume(); - dispatchEventAsync(volumechangeEvent); + dispatchEventAsync(eventNames().volumechangeEvent); } } @@ -789,7 +800,7 @@ void HTMLMediaElement::setMuted(bool muted) if (m_muted != muted) { m_muted = muted; updateVolume(); - dispatchEventAsync(volumechangeEvent); + dispatchEventAsync(eventNames().volumechangeEvent); } } @@ -809,23 +820,29 @@ String HTMLMediaElement::pickMedia() if (!source->hasAttribute(srcAttr)) continue; if (source->hasAttribute(mediaAttr)) { - MediaQueryEvaluator screenEval("screen", document()->page(), renderer() ? renderer()->style() : 0); - RefPtr<MediaList> media = new MediaList((CSSStyleSheet*)0, source->media(), true); + 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(); + 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(); + mediaSrc = source->src().string(); break; } } } if (!mediaSrc.isEmpty()) - mediaSrc = document()->completeURL(mediaSrc); + mediaSrc = document()->completeURL(mediaSrc).string(); return mediaSrc; } @@ -872,12 +889,12 @@ void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*) ExceptionCode ec; seek(effectiveLoopStart(), ec); m_currentLoop++; - dispatchHTMLEvent(timeupdateEvent, false, true); + dispatchEventForType(eventNames().timeupdateEvent, false, true); } if (m_currentLoop == playCount() - 1 && currentTime() >= effectiveEnd()) { - dispatchHTMLEvent(timeupdateEvent, false, true); - dispatchHTMLEvent(endedEvent, false, true); + dispatchEventForType(eventNames().timeupdateEvent, false, true); + dispatchEventForType(eventNames().endedEvent, false, true); } updatePlayState(); @@ -893,22 +910,22 @@ PassRefPtr<TimeRanges> HTMLMediaElement::buffered() const { // FIXME real ranges support if (!m_player || !m_player->maxTimeBuffered()) - return new TimeRanges; - return new TimeRanges(0, m_player->maxTimeBuffered()); + return TimeRanges::create(); + return TimeRanges::create(0, m_player->maxTimeBuffered()); } PassRefPtr<TimeRanges> HTMLMediaElement::played() const { // FIXME track played - return new TimeRanges; + return TimeRanges::create(); } PassRefPtr<TimeRanges> HTMLMediaElement::seekable() const { // FIXME real ranges support if (!m_player || !m_player->maxTimeSeekable()) - return new TimeRanges; - return new TimeRanges(0, m_player->maxTimeSeekable()); + return TimeRanges::create(); + return TimeRanges::create(0, m_player->maxTimeSeekable()); } float HTMLMediaElement::effectiveStart() const @@ -988,8 +1005,8 @@ void HTMLMediaElement::setPausedInternal(bool b) m_pausedInternal = b; updatePlayState(); } - -void HTMLMediaElement::willSaveToCache() + +void HTMLMediaElement::documentWillBecomeInactive() { // 3.14.9.4. Loading the media resource // 14 @@ -998,26 +1015,26 @@ void HTMLMediaElement::willSaveToCache() m_player.clear(); m_progressEventTimer.stop(); - m_error = new MediaError(MediaError::MEDIA_ERR_ABORTED); + m_error = MediaError::create(MediaError::MEDIA_ERR_ABORTED); m_begun = false; - initAndDispatchProgressEvent(abortEvent); + initAndDispatchProgressEvent(eventNames().abortEvent); if (m_networkState >= LOADING) { m_networkState = EMPTY; - dispatchHTMLEvent(emptiedEvent, false, true); + m_readyState = DATA_UNAVAILABLE; + dispatchEventForType(eventNames().emptiedEvent, false, true); } } - m_inPageCache = true; + m_inActiveDocument = false; // Stop the playback without generating events setPausedInternal(true); - if (m_player) - m_player->setVisible(false); + if (renderer()) renderer()->updateFromElement(); } -void HTMLMediaElement::didRestoreFromCache() +void HTMLMediaElement::documentDidBecomeActive() { - m_inPageCache = false; + m_inActiveDocument = true; setPausedInternal(false); if (m_error && m_error->code() == MediaError::MEDIA_ERR_ABORTED) { @@ -1035,6 +1052,8 @@ void HTMLMediaElement::defaultEventHandler(Event* event) { if (renderer() && renderer()->isMedia()) static_cast<RenderMedia*>(renderer())->forwardEvent(event); + if (event->defaultHandled()) + return; HTMLElement::defaultEventHandler(event); } diff --git a/WebCore/html/HTMLMediaElement.h b/WebCore/html/HTMLMediaElement.h index 91520b0..27fac2f 100644 --- a/WebCore/html/HTMLMediaElement.h +++ b/WebCore/html/HTMLMediaElement.h @@ -37,6 +37,7 @@ namespace WebCore { class MediaError; class TimeRanges; +class KURL; class HTMLMediaElement : public HTMLElement, public MediaPlayerClient { public: @@ -52,6 +53,7 @@ public: virtual void insertedIntoDocument(); virtual void removedFromDocument(); virtual void attach(); + virtual void recalcStyle(StyleChange); MediaPlayer* player() const { return m_player.get(); } @@ -64,14 +66,14 @@ public: // Pauses playback without changing any states or generating events void setPausedInternal(bool); - bool inPageCache() const { return m_inPageCache; } + bool inActiveDocument() const { return m_inActiveDocument; } // DOM API // error state PassRefPtr<MediaError> error() const; // network state - String src() const; + KURL src() const; void setSrc(const String&); String currentSrc() const; @@ -131,8 +133,8 @@ protected: float getTimeOffsetAttribute(const QualifiedName&, float valueOnError) const; void setTimeOffsetAttribute(const QualifiedName&, float value); - virtual void willSaveToCache(); - virtual void didRestoreFromCache(); + virtual void documentWillBecomeInactive(); + virtual void documentDidBecomeActive(); void initAndDispatchProgressEvent(const AtomicString& eventName); void dispatchEventAsync(const AtomicString& eventName); @@ -198,7 +200,7 @@ protected: unsigned m_terminateLoadBelowNestingLevel; bool m_pausedInternal; - bool m_inPageCache; + bool m_inActiveDocument; OwnPtr<MediaPlayer> m_player; }; diff --git a/WebCore/html/HTMLNameCollection.h b/WebCore/html/HTMLNameCollection.h index 916cced..9add926 100644 --- a/WebCore/html/HTMLNameCollection.h +++ b/WebCore/html/HTMLNameCollection.h @@ -32,9 +32,14 @@ class Document; class HTMLNameCollection : public HTMLCollection { public: - HTMLNameCollection(PassRefPtr<Document>, Type, const String& name); + static PassRefPtr<HTMLNameCollection> create(PassRefPtr<Document> document, Type type, const String& name) + { + return adoptRef(new HTMLNameCollection(document, type, name)); + } private: + HTMLNameCollection(PassRefPtr<Document>, Type, const String& name); + virtual Element* itemAfter(Element*) const; String m_name; diff --git a/WebCore/html/HTMLOListElement.cpp b/WebCore/html/HTMLOListElement.cpp index 8da6930..a37d4ef 100644 --- a/WebCore/html/HTMLOListElement.cpp +++ b/WebCore/html/HTMLOListElement.cpp @@ -52,15 +52,15 @@ void HTMLOListElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == typeAttr) { if (attr->value() == "a") - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_LOWER_ALPHA); + addCSSProperty(attr, CSSPropertyListStyleType, CSSValueLowerAlpha); else if (attr->value() == "A") - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_UPPER_ALPHA); + addCSSProperty(attr, CSSPropertyListStyleType, CSSValueUpperAlpha); else if (attr->value() == "i") - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_LOWER_ROMAN); + addCSSProperty(attr, CSSPropertyListStyleType, CSSValueLowerRoman); else if (attr->value() == "I") - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_UPPER_ROMAN); + addCSSProperty(attr, CSSPropertyListStyleType, CSSValueUpperRoman); else if (attr->value() == "1") - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_DECIMAL); + addCSSProperty(attr, CSSPropertyListStyleType, CSSValueDecimal); } else if (attr->name() == startAttr) { int s = !attr->isNull() ? attr->value().toInt() : 1; if (s != m_start) { diff --git a/WebCore/html/HTMLObjectElement.cpp b/WebCore/html/HTMLObjectElement.cpp index 810496c..694f2d3 100644 --- a/WebCore/html/HTMLObjectElement.cpp +++ b/WebCore/html/HTMLObjectElement.cpp @@ -2,8 +2,8 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Stefan Schimanski (1Stein@gmx.de) - * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2007 Trolltech ASA + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -28,30 +28,27 @@ #include "EventNames.h" #include "ExceptionCode.h" #include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "FrameView.h" #include "HTMLDocument.h" #include "HTMLFormElement.h" #include "HTMLImageLoader.h" #include "HTMLNames.h" -#include "Image.h" #include "MIMETypeRegistry.h" #include "RenderImage.h" #include "RenderPartObject.h" #include "RenderWidget.h" +#include "ScriptController.h" #include "Text.h" + namespace WebCore { -using namespace EventNames; using namespace HTMLNames; HTMLObjectElement::HTMLObjectElement(Document* doc, bool createdByParser) - : HTMLPlugInElement(objectTag, doc) + : HTMLPlugInImageElement(objectTag, doc) + , m_docNamedItem(true) , m_needWidgetUpdate(!createdByParser) , m_useFallbackContent(false) - , m_docNamedItem(true) { } @@ -59,40 +56,24 @@ HTMLObjectElement::~HTMLObjectElement() { #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name and m_id are removed from HTMLDocument's NameCountMap if (oldNameIdCount && document()->isHTMLDocument()) { HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - doc->removeNamedItem(oldNameAttr); - doc->removeDocExtraNamedItem(oldIdAttr); + doc->removeNamedItem(m_name); + doc->removeExtraNamedItem(m_id); } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) - // m_instance should have been cleaned up in detach(). - ASSERT(!m_instance); -#endif } -#if USE(JAVASCRIPTCORE_BINDINGS) -KJS::Bindings::Instance *HTMLObjectElement::getInstance() const +RenderWidget* HTMLObjectElement::renderWidgetForJSBindings() const { - Frame* frame = document()->frame(); - if (!frame) - return 0; - - if (m_instance) - return m_instance.get(); - RenderWidget* renderWidget = (renderer() && renderer()->isWidget()) ? static_cast<RenderWidget*>(renderer()) : 0; if (renderWidget && !renderWidget->widget()) { document()->updateLayoutIgnorePendingStylesheets(); renderWidget = (renderer() && renderer()->isWidget()) ? static_cast<RenderWidget*>(renderer()) : 0; - } - if (renderWidget && renderWidget->widget()) - m_instance = frame->createScriptInstanceForWidget(renderWidget->widget()); - - return m_instance.get(); + } + return renderWidget; } -#endif void HTMLObjectElement::parseMappedAttribute(MappedAttribute *attr) { @@ -121,25 +102,23 @@ void HTMLObjectElement::parseMappedAttribute(MappedAttribute *attr) if (renderer()) m_needWidgetUpdate = true; } else if (attr->name() == onloadAttr) { - setHTMLEventListener(loadEvent, attr); - } else if (attr->name() == onunloadAttr) { - setHTMLEventListener(unloadEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().loadEvent, attr); } else if (attr->name() == nameAttr) { - String newNameAttr = attr->value(); - if (isDocNamedItem() && inDocument() && document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->removeNamedItem(oldNameAttr); - doc->addNamedItem(newNameAttr); - } - oldNameAttr = newNameAttr; + const AtomicString& newName = attr->value(); + if (isDocNamedItem() && inDocument() && document()->isHTMLDocument()) { + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeNamedItem(m_name); + document->addNamedItem(newName); + } + m_name = newName; } else if (attr->name() == idAttr) { - String newIdAttr = attr->value(); + const AtomicString& newId = attr->value(); if (isDocNamedItem() && inDocument() && document()->isHTMLDocument()) { - HTMLDocument* doc = static_cast<HTMLDocument*>(document()); - doc->removeDocExtraNamedItem(oldIdAttr); - doc->addDocExtraNamedItem(newIdAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeExtraNamedItem(m_id); + document->addExtraNamedItem(newId); } - oldIdAttr = newIdAttr; + m_id = newId; // also call superclass HTMLPlugInElement::parseMappedAttribute(attr); } else @@ -180,15 +159,18 @@ void HTMLObjectElement::attach() if (!m_imageLoader) m_imageLoader.set(new HTMLImageLoader(this)); m_imageLoader->updateFromElement(); - if (renderer()) { - RenderImage* imageObj = static_cast<RenderImage*>(renderer()); - imageObj->setCachedImage(m_imageLoader->image()); - } + // updateForElement() may have changed us to use fallback content and called detach() and attach(). + if (m_useFallbackContent) + return; + + if (renderer()) + static_cast<RenderImage*>(renderer())->setCachedImage(m_imageLoader->image()); } } void HTMLObjectElement::updateWidget() { + document()->updateRendering(); if (m_needWidgetUpdate && renderer() && !m_useFallbackContent && !isImageType()) static_cast<RenderPartObject*>(renderer())->updateWidget(true); } @@ -205,26 +187,21 @@ void HTMLObjectElement::finishParsingChildren() void HTMLObjectElement::detach() { - if (attached() && renderer() && !m_useFallbackContent) { + if (attached() && renderer() && !m_useFallbackContent) // Update the widget the next time we attach (detaching destroys the plugin). m_needWidgetUpdate = true; - } - -#if USE(JAVASCRIPTCORE_BINDINGS) - m_instance = 0; -#endif HTMLPlugInElement::detach(); } void HTMLObjectElement::insertedIntoDocument() { if (isDocNamedItem() && document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->addNamedItem(oldNameAttr); - doc->addDocExtraNamedItem(oldIdAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->addNamedItem(m_name); + document->addExtraNamedItem(m_id); #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name and m_id are removed from HTMLDocument's NameCountMap oldNameIdCount++; #endif } @@ -235,12 +212,12 @@ void HTMLObjectElement::insertedIntoDocument() void HTMLObjectElement::removedFromDocument() { if (isDocNamedItem() && document()->isHTMLDocument()) { - HTMLDocument *doc = static_cast<HTMLDocument *>(document()); - doc->removeNamedItem(oldNameAttr); - doc->removeDocExtraNamedItem(oldIdAttr); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); + document->removeNamedItem(m_name); + document->removeExtraNamedItem(m_id); #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name and m_id are removed from HTMLDocument's NameCountMap oldNameIdCount--; #endif } @@ -257,19 +234,19 @@ void HTMLObjectElement::recalcStyle(StyleChange ch) HTMLPlugInElement::recalcStyle(ch); } -void HTMLObjectElement::childrenChanged(bool changedByParser) +void HTMLObjectElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { updateDocNamedItem(); if (inDocument() && !m_useFallbackContent) { m_needWidgetUpdate = true; setChanged(); } - HTMLPlugInElement::childrenChanged(changedByParser); + HTMLPlugInElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); } bool HTMLObjectElement::isURLAttribute(Attribute *attr) const { - return (attr->name() == dataAttr || (attr->name() == usemapAttr && attr->value().domString()[0] != '#')); + return (attr->name() == dataAttr || (attr->name() == usemapAttr && attr->value().string()[0] != '#')); } const QualifiedName& HTMLObjectElement::imageSourceAttributeName() const @@ -277,34 +254,23 @@ const QualifiedName& HTMLObjectElement::imageSourceAttributeName() const return dataAttr; } -bool HTMLObjectElement::isImageType() -{ - if (m_serviceType.isEmpty() && m_url.startsWith("data:")) { - // Extract the MIME type from the data URL. - int index = m_url.find(';'); - if (index == -1) - index = m_url.find(','); - if (index != -1) { - int len = index - 5; - if (len > 0) - m_serviceType = m_url.substring(5, len); - else - m_serviceType = "text/plain"; // Data URLs with no MIME type are considered text/plain. - } - } - if (Frame* frame = document()->frame()) { - KURL completedURL(frame->loader()->completeURL(m_url)); - return frame->loader()->client()->objectContentType(completedURL, m_serviceType) == ObjectContentImage; - } - - return Image::supportsType(m_serviceType); -} - void HTMLObjectElement::renderFallbackContent() { if (m_useFallbackContent) return; + // Before we give up and use fallback content, check to see if this is a MIME type issue. + if (m_imageLoader && m_imageLoader->image()) { + m_serviceType = m_imageLoader->image()->response().mimeType(); + if (!isImageType()) { + // If we don't think we have an image type anymore, then ditch the image loader. + m_imageLoader.clear(); + detach(); + attach(); + return; + } + } + // Mark ourselves as using the fallback content. m_useFallbackContent = true; @@ -335,13 +301,13 @@ void HTMLObjectElement::updateDocNamedItem() child = child->nextSibling(); } if (isNamedItem != wasNamedItem && document()->isHTMLDocument()) { - HTMLDocument* doc = static_cast<HTMLDocument*>(document()); + HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); if (isNamedItem) { - doc->addNamedItem(oldNameAttr); - doc->addDocExtraNamedItem(oldIdAttr); + document->addNamedItem(m_name); + document->addExtraNamedItem(m_id); } else { - doc->removeNamedItem(oldNameAttr); - doc->removeDocExtraNamedItem(oldIdAttr); + document->removeNamedItem(m_name); + document->removeExtraNamedItem(m_id); } } m_docNamedItem = isNamedItem; @@ -397,7 +363,7 @@ void HTMLObjectElement::setCodeType(const String& value) setAttribute(codetypeAttr, value); } -String HTMLObjectElement::data() const +KURL HTMLObjectElement::data() const { return document()->completeURL(getAttribute(dataAttr)); } @@ -437,11 +403,6 @@ void HTMLObjectElement::setStandby(const String& value) setAttribute(standbyAttr, value); } -void HTMLObjectElement::setTabIndex(int tabIndex) -{ - setAttribute(tabindexAttr, String::number(tabIndex)); -} - String HTMLObjectElement::type() const { return getAttribute(typeAttr); @@ -481,9 +442,7 @@ bool HTMLObjectElement::containsJavaApplet() const while (child) { if (child->isElementNode()) { Element* e = static_cast<Element*>(child); - if (e->hasTagName(paramTag) && - e->getAttribute(nameAttr).domString().lower() == "type" && - MIMETypeRegistry::isJavaAppletMIMEType(e->getAttribute(valueAttr).domString())) + if (e->hasTagName(paramTag) && equalIgnoringCase(e->getAttribute(nameAttr), "type") && MIMETypeRegistry::isJavaAppletMIMEType(e->getAttribute(valueAttr).string())) return true; else if (e->hasTagName(objectTag) && static_cast<HTMLObjectElement*>(e)->containsJavaApplet()) return true; @@ -496,4 +455,11 @@ bool HTMLObjectElement::containsJavaApplet() const return false; } +void HTMLObjectElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + urls.append(data().string()); + if (useMap().startsWith("#")) + urls.append(useMap()); +} + } diff --git a/WebCore/html/HTMLObjectElement.h b/WebCore/html/HTMLObjectElement.h index 0a87b9f..859c73f 100644 --- a/WebCore/html/HTMLObjectElement.h +++ b/WebCore/html/HTMLObjectElement.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2006, 2007, 2008 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 @@ -23,14 +23,13 @@ #ifndef HTMLObjectElement_h #define HTMLObjectElement_h -#include "HTMLPlugInElement.h" -#include <wtf/OwnPtr.h> +#include "HTMLPlugInImageElement.h" namespace WebCore { -class HTMLImageLoader; +class KURL; -class HTMLObjectElement : public HTMLPlugInElement { +class HTMLObjectElement : public HTMLPlugInImageElement { public: HTMLObjectElement(Document*, bool createdByParser); ~HTMLObjectElement(); @@ -40,6 +39,7 @@ public: virtual void parseMappedAttribute(MappedAttribute*); virtual void attach(); + virtual bool canLazyAttach() { return false; } virtual bool rendererIsNeeded(RenderStyle*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); virtual void finishParsingChildren(); @@ -48,7 +48,7 @@ public: virtual void removedFromDocument(); virtual void recalcStyle(StyleChange); - virtual void childrenChanged(bool changedByParser = false); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); virtual bool isURLAttribute(Attribute*) const; virtual const QualifiedName& imageSourceAttributeName() const; @@ -56,13 +56,9 @@ public: virtual void updateWidget(); void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; } - bool isImageType(); - void renderFallbackContent(); -#if USE(JAVASCRIPTCORE_BINDINGS) - virtual KJS::Bindings::Instance* getInstance() const; -#endif + virtual RenderWidget* renderWidgetForJSBindings() const; String archive() const; void setArchive(const String&); @@ -79,7 +75,7 @@ public: String codeType() const; void setCodeType(const String&); - String data() const; + KURL data() const; void setData(const String&); bool declare() const; @@ -91,8 +87,6 @@ public: String standby() const; void setStandby(const String&); - void setTabIndex(int); - String type() const; void setType(const String&); @@ -104,19 +98,20 @@ public: bool isDocNamedItem() const { return m_docNamedItem; } + const String& classId() const { return m_classId; } + bool containsJavaApplet() const; - String m_serviceType; - String m_url; - String m_classId; - bool m_needWidgetUpdate : 1; - bool m_useFallbackContent : 1; - OwnPtr<HTMLImageLoader> m_imageLoader; + virtual void getSubresourceAttributeStrings(Vector<String>&) const; private: void updateDocNamedItem(); - String oldIdAttr; - bool m_docNamedItem; + + AtomicString m_id; + String m_classId; + bool m_docNamedItem : 1; + bool m_needWidgetUpdate : 1; + bool m_useFallbackContent : 1; }; } diff --git a/WebCore/html/HTMLObjectElement.idl b/WebCore/html/HTMLObjectElement.idl index a6fe7ac..c225238 100644 --- a/WebCore/html/HTMLObjectElement.idl +++ b/WebCore/html/HTMLObjectElement.idl @@ -42,7 +42,6 @@ module html { attribute long hspace; attribute [ConvertNullToNullString] DOMString name; attribute [ConvertNullToNullString] DOMString standby; - attribute long tabIndex; attribute [ConvertNullToNullString] DOMString type; attribute [ConvertNullToNullString] DOMString useMap; attribute long vspace; diff --git a/WebCore/html/HTMLOptGroupElement.cpp b/WebCore/html/HTMLOptGroupElement.cpp index d317fc5..0465fb4 100644 --- a/WebCore/html/HTMLOptGroupElement.cpp +++ b/WebCore/html/HTMLOptGroupElement.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, 2008 Apple Inc. All rights reserved. * (C) 2006 Alexey Proskuryakov (ap@nypop.com) * * This library is free software; you can redistribute it and/or @@ -30,20 +30,21 @@ #include "HTMLNames.h" #include "HTMLSelectElement.h" #include "RenderMenuList.h" +#include "NodeRenderStyle.h" namespace WebCore { using namespace HTMLNames; HTMLOptGroupElement::HTMLOptGroupElement(Document* doc, HTMLFormElement* f) - : HTMLGenericFormElement(optgroupTag, doc, f) + : HTMLFormControlElement(optgroupTag, doc, f) , m_style(0) { } bool HTMLOptGroupElement::isFocusable() const { - return false; + return HTMLElement::isFocusable(); } const AtomicString& HTMLOptGroupElement::type() const @@ -52,17 +53,17 @@ const AtomicString& HTMLOptGroupElement::type() const return optgroup; } -bool HTMLOptGroupElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec) +bool HTMLOptGroupElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach) { - bool result = HTMLGenericFormElement::insertBefore(newChild, refChild, ec); + bool result = HTMLFormControlElement::insertBefore(newChild, refChild, ec, shouldLazyAttach); if (result) recalcSelectOptions(); return result; } -bool HTMLOptGroupElement::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec) +bool HTMLOptGroupElement::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach) { - bool result = HTMLGenericFormElement::replaceChild(newChild, oldChild, ec); + bool result = HTMLFormControlElement::replaceChild(newChild, oldChild, ec, shouldLazyAttach); if (result) recalcSelectOptions(); return result; @@ -70,15 +71,15 @@ bool HTMLOptGroupElement::replaceChild(PassRefPtr<Node> newChild, Node* oldChild bool HTMLOptGroupElement::removeChild(Node* oldChild, ExceptionCode& ec) { - bool result = HTMLGenericFormElement::removeChild(oldChild, ec); + bool result = HTMLFormControlElement::removeChild(oldChild, ec); if (result) recalcSelectOptions(); return result; } -bool HTMLOptGroupElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec) +bool HTMLOptGroupElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach) { - bool result = HTMLGenericFormElement::appendChild(newChild, ec); + bool result = HTMLFormControlElement::appendChild(newChild, ec, shouldLazyAttach); if (result) recalcSelectOptions(); return result; @@ -86,21 +87,21 @@ bool HTMLOptGroupElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& bool HTMLOptGroupElement::removeChildren() { - bool result = HTMLGenericFormElement::removeChildren(); + bool result = HTMLFormControlElement::removeChildren(); if (result) recalcSelectOptions(); return result; } -void HTMLOptGroupElement::childrenChanged(bool changedByParser) +void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { recalcSelectOptions(); - HTMLGenericFormElement::childrenChanged(changedByParser); + HTMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); } void HTMLOptGroupElement::parseMappedAttribute(MappedAttribute* attr) { - HTMLGenericFormElement::parseMappedAttribute(attr); + HTMLFormControlElement::parseMappedAttribute(attr); recalcSelectOptions(); } @@ -131,36 +132,30 @@ bool HTMLOptGroupElement::checkDTD(const Node* newChild) void HTMLOptGroupElement::attach() { - if (parentNode()->renderStyle()) { - RenderStyle* style = styleForRenderer(0); - setRenderStyle(style); - style->deref(document()->renderArena()); - } - HTMLGenericFormElement::attach(); + if (parentNode()->renderStyle()) + setRenderStyle(styleForRenderer()); + HTMLFormControlElement::attach(); } void HTMLOptGroupElement::detach() { - if (m_style) { - m_style->deref(document()->renderArena()); - m_style = 0; - } - HTMLGenericFormElement::detach(); + m_style.clear(); + HTMLFormControlElement::detach(); } -void HTMLOptGroupElement::setRenderStyle(RenderStyle* newStyle) +void HTMLOptGroupElement::setRenderStyle(PassRefPtr<RenderStyle> newStyle) { - RenderStyle* oldStyle = m_style; m_style = newStyle; - if (newStyle) - newStyle->ref(); - if (oldStyle) - oldStyle->deref(document()->renderArena()); +} + +RenderStyle* HTMLOptGroupElement::nonRendererRenderStyle() const +{ + return m_style.get(); } String HTMLOptGroupElement::groupLabelText() const { - DeprecatedString itemText = getAttribute(labelAttr).deprecatedString(); + String itemText = getAttribute(labelAttr); itemText.replace('\\', document()->backslashAsCurrencySymbol()); // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior. @@ -170,5 +165,25 @@ String HTMLOptGroupElement::groupLabelText() const return itemText; } - + +HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const +{ + Node* select = parentNode(); + while (select && !select->hasTagName(selectTag)) + select = select->parentNode(); + + if (!select) + return 0; + + return static_cast<HTMLSelectElement*>(select); +} + +void HTMLOptGroupElement::accessKeyAction(bool sendToAnyElement) +{ + HTMLSelectElement* select = ownerSelectElement(); + // send to the parent to bring focus to the list box + if (select && !select->focused()) + select->accessKeyAction(false); +} + } // namespace diff --git a/WebCore/html/HTMLOptGroupElement.h b/WebCore/html/HTMLOptGroupElement.h index 6127b19..85e789b 100644 --- a/WebCore/html/HTMLOptGroupElement.h +++ b/WebCore/html/HTMLOptGroupElement.h @@ -24,11 +24,13 @@ #ifndef HTMLOptGroupElement_h #define HTMLOptGroupElement_h -#include "HTMLGenericFormElement.h" +#include "HTMLFormControlElement.h" namespace WebCore { + +class HTMLSelectElement; -class HTMLOptGroupElement : public HTMLGenericFormElement { +class HTMLOptGroupElement : public HTMLFormControlElement { public: HTMLOptGroupElement(Document*, HTMLFormElement* = 0); @@ -39,25 +41,28 @@ public: virtual bool rendererIsNeeded(RenderStyle*) { return false; } virtual void attach(); virtual void detach(); - virtual RenderStyle* renderStyle() const { return m_style; } - virtual void setRenderStyle(RenderStyle*); + virtual void setRenderStyle(PassRefPtr<RenderStyle>); - virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&); - virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&); + 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&); + virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&, bool shouldLazyAttach = false); virtual bool removeChildren(); - virtual void childrenChanged(bool changedByParser = false); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); String label() const; void setLabel(const String&); String groupLabelText() const; + HTMLSelectElement* ownerSelectElement() const; + virtual void accessKeyAction(bool sendToAnyElement); private: + virtual RenderStyle* nonRendererRenderStyle() const; + void recalcSelectOptions(); - RenderStyle* m_style; + RefPtr<RenderStyle> m_style; }; } //namespace diff --git a/WebCore/html/HTMLOptionElement.cpp b/WebCore/html/HTMLOptionElement.cpp index db4f020..887a4e5 100644 --- a/WebCore/html/HTMLOptionElement.cpp +++ b/WebCore/html/HTMLOptionElement.cpp @@ -29,21 +29,20 @@ #include "CSSStyleSelector.h" #include "Document.h" -#include "EventNames.h" #include "ExceptionCode.h" #include "HTMLNames.h" #include "HTMLSelectElement.h" #include "RenderMenuList.h" #include "Text.h" +#include "NodeRenderStyle.h" #include <wtf/Vector.h> namespace WebCore { using namespace HTMLNames; -using namespace EventNames; HTMLOptionElement::HTMLOptionElement(Document* doc, HTMLFormElement* f) - : HTMLGenericFormElement(optionTag, doc, f) + : HTMLFormControlElement(optionTag, doc, f) , m_selected(false) , m_style(0) { @@ -56,26 +55,20 @@ bool HTMLOptionElement::checkDTD(const Node* newChild) void HTMLOptionElement::attach() { - if (parentNode()->renderStyle()) { - RenderStyle* style = styleForRenderer(0); - setRenderStyle(style); - style->deref(document()->renderArena()); - } - HTMLGenericFormElement::attach(); + if (parentNode()->renderStyle()) + setRenderStyle(styleForRenderer()); + HTMLFormControlElement::attach(); } void HTMLOptionElement::detach() { - if (m_style) { - m_style->deref(document()->renderArena()); - m_style = 0; - } - HTMLGenericFormElement::detach(); + m_style.clear(); + HTMLFormControlElement::detach(); } bool HTMLOptionElement::isFocusable() const { - return false; + return HTMLElement::isFocusable(); } const AtomicString& HTMLOptionElement::type() const @@ -127,11 +120,18 @@ void HTMLOptionElement::setText(const String &text, ExceptionCode& ec) appendChild(new Text(document(), text), ec); } +void HTMLOptionElement::accessKeyAction(bool sendToAnyElement) +{ + HTMLSelectElement* select = ownerSelectElement(); + if (select) + select->accessKeySetSelectedIndex(index()); +} + int HTMLOptionElement::index() const { // Let's do this dynamically. Might be a bit slow, but we're sure // we won't forget to update a member variable in some cases... - HTMLSelectElement *select = getSelect(); + HTMLSelectElement* select = ownerSelectElement(); if (select) { const Vector<HTMLElement*>& items = select->listItems(); int l = items.size(); @@ -154,7 +154,7 @@ void HTMLOptionElement::parseMappedAttribute(MappedAttribute *attr) else if (attr->name() == valueAttr) m_value = attr->value(); else - HTMLGenericFormElement::parseMappedAttribute(attr); + HTMLFormControlElement::parseMappedAttribute(attr); } String HTMLOptionElement::value() const @@ -174,7 +174,7 @@ void HTMLOptionElement::setSelected(bool selected) { if (m_selected == selected) return; - if (HTMLSelectElement* select = getSelect()) + if (HTMLSelectElement* select = ownerSelectElement()) select->setSelectedIndex(selected ? index() : -1, false); m_selected = selected; } @@ -187,19 +187,23 @@ void HTMLOptionElement::setSelectedState(bool selected) setChanged(); } -void HTMLOptionElement::childrenChanged(bool changedByParser) +void HTMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { - HTMLSelectElement *select = getSelect(); + HTMLSelectElement* select = ownerSelectElement(); if (select) select->childrenChanged(changedByParser); - HTMLGenericFormElement::childrenChanged(changedByParser); + HTMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); } -HTMLSelectElement* HTMLOptionElement::getSelect() const +HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const { Node* select = parentNode(); while (select && !select->hasTagName(selectTag)) select = select->parentNode(); + + if (!select) + return 0; + return static_cast<HTMLSelectElement*>(select); } @@ -223,14 +227,14 @@ void HTMLOptionElement::setLabel(const String& value) setAttribute(labelAttr, value); } -void HTMLOptionElement::setRenderStyle(RenderStyle* newStyle) +void HTMLOptionElement::setRenderStyle(PassRefPtr<RenderStyle> newStyle) { - RenderStyle* oldStyle = m_style; m_style = newStyle; - if (newStyle) - newStyle->ref(); - if (oldStyle) - oldStyle->deref(document()->renderArena()); +} + +RenderStyle* HTMLOptionElement::nonRendererRenderStyle() const +{ + return m_style.get(); } String HTMLOptionElement::optionText() @@ -243,16 +247,16 @@ String HTMLOptionElement::optionText() bool HTMLOptionElement::disabled() const { - return HTMLGenericFormElement::disabled() || (parentNode() && static_cast<HTMLGenericFormElement*>(parentNode())->disabled()); + return HTMLFormControlElement::disabled() || (parentNode() && static_cast<HTMLFormControlElement*>(parentNode())->disabled()); } void HTMLOptionElement::insertedIntoDocument() { HTMLSelectElement* select; - if (selected() && (select = getSelect())) + if (selected() && (select = ownerSelectElement())) select->scrollToSelection(); - HTMLGenericFormElement::insertedIntoDocument(); + HTMLFormControlElement::insertedIntoDocument(); } } // namespace diff --git a/WebCore/html/HTMLOptionElement.h b/WebCore/html/HTMLOptionElement.h index 635a7b3..58426eb 100644 --- a/WebCore/html/HTMLOptionElement.h +++ b/WebCore/html/HTMLOptionElement.h @@ -25,7 +25,7 @@ #ifndef HTMLOptionElement_h #define HTMLOptionElement_h -#include "HTMLGenericFormElement.h" +#include "HTMLFormControlElement.h" namespace WebCore { @@ -33,8 +33,7 @@ class HTMLSelectElement; class HTMLFormElement; class MappedAttribute; -class HTMLOptionElement : public HTMLGenericFormElement -{ +class HTMLOptionElement : public HTMLFormControlElement { friend class HTMLSelectElement; friend class RenderMenuList; @@ -48,8 +47,7 @@ public: virtual bool rendererIsNeeded(RenderStyle*) { return false; } virtual void attach(); virtual void detach(); - virtual RenderStyle* renderStyle() const { return m_style; } - virtual void setRenderStyle(RenderStyle*); + virtual void setRenderStyle(PassRefPtr<RenderStyle>); virtual const AtomicString& type() const; @@ -66,9 +64,9 @@ public: void setSelected(bool); void setSelectedState(bool); - HTMLSelectElement* getSelect() const; + HTMLSelectElement* ownerSelectElement() const; - virtual void childrenChanged(bool changedByParser = false); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); bool defaultSelected() const; void setDefaultSelected(bool); @@ -81,11 +79,14 @@ public: virtual bool disabled() const; virtual void insertedIntoDocument(); - + virtual void accessKeyAction(bool); + private: + virtual RenderStyle* nonRendererRenderStyle() const; + String m_value; bool m_selected; - RenderStyle* m_style; + RefPtr<RenderStyle> m_style; }; } //namespace diff --git a/WebCore/html/HTMLOptionElement.idl b/WebCore/html/HTMLOptionElement.idl index 1f17033..34fa999 100644 --- a/WebCore/html/HTMLOptionElement.idl +++ b/WebCore/html/HTMLOptionElement.idl @@ -21,6 +21,7 @@ module html { interface [ + GenerateConstructor, GenerateNativeConverter, InterfaceUUID=74a7b64a-cf18-4da9-b3aa-e1f4d245d607, ImplementationUUID=166915d5-2c93-404b-b076-af3fa5ccbd83 diff --git a/WebCore/html/HTMLOptionsCollection.cpp b/WebCore/html/HTMLOptionsCollection.cpp index d5a1a7f..0b88183 100644 --- a/WebCore/html/HTMLOptionsCollection.cpp +++ b/WebCore/html/HTMLOptionsCollection.cpp @@ -34,6 +34,11 @@ HTMLOptionsCollection::HTMLOptionsCollection(PassRefPtr<HTMLSelectElement> selec { } +PassRefPtr<HTMLOptionsCollection> HTMLOptionsCollection::create(PassRefPtr<HTMLSelectElement> select) +{ + return adoptRef(new HTMLOptionsCollection(select)); +} + void HTMLOptionsCollection::add(PassRefPtr<HTMLOptionElement> element, ExceptionCode &ec) { add(element, length(), ec); diff --git a/WebCore/html/HTMLOptionsCollection.h b/WebCore/html/HTMLOptionsCollection.h index 9fb5bbf..a82749b 100644 --- a/WebCore/html/HTMLOptionsCollection.h +++ b/WebCore/html/HTMLOptionsCollection.h @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 @@ -35,7 +35,7 @@ typedef int ExceptionCode; class HTMLOptionsCollection : public HTMLCollection { public: - HTMLOptionsCollection(PassRefPtr<HTMLSelectElement>); + static PassRefPtr<HTMLOptionsCollection> create(PassRefPtr<HTMLSelectElement>); void add(PassRefPtr<HTMLOptionElement>, ExceptionCode&); void add(PassRefPtr<HTMLOptionElement>, int index, ExceptionCode&); @@ -45,6 +45,9 @@ public: void setSelectedIndex(int); void setLength(unsigned, ExceptionCode&); + +private: + HTMLOptionsCollection(PassRefPtr<HTMLSelectElement>); }; } //namespace diff --git a/WebCore/html/HTMLParagraphElement.cpp b/WebCore/html/HTMLParagraphElement.cpp index 4cee789..1b5f054 100644 --- a/WebCore/html/HTMLParagraphElement.cpp +++ b/WebCore/html/HTMLParagraphElement.cpp @@ -57,13 +57,13 @@ void HTMLParagraphElement::parseMappedAttribute(MappedAttribute *attr) if (attr->name() == alignAttr) { String v = attr->value(); if (equalIgnoringCase(attr->value(), "middle") || equalIgnoringCase(attr->value(), "center")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__WEBKIT_CENTER); + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitCenter); else if (equalIgnoringCase(attr->value(), "left")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__WEBKIT_LEFT); + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitLeft); else if (equalIgnoringCase(attr->value(), "right")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__WEBKIT_RIGHT); + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitRight); else - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, v); + addCSSProperty(attr, CSSPropertyTextAlign, v); } else HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLParagraphElement.h b/WebCore/html/HTMLParagraphElement.h index a6be6b4..9b5b4fa 100644 --- a/WebCore/html/HTMLParagraphElement.h +++ b/WebCore/html/HTMLParagraphElement.h @@ -32,7 +32,7 @@ class HTMLParagraphElement : public HTMLElement { public: HTMLParagraphElement(Document*); - virtual HTMLTagStatus endTagRequirement() const { return TagStatusOptional; } + virtual HTMLTagStatus endTagRequirement() const { return TagStatusRequired; } virtual int tagPriority() const { return 3; } virtual bool checkDTD(const Node* newChild); diff --git a/WebCore/html/HTMLParamElement.cpp b/WebCore/html/HTMLParamElement.cpp index d1e2616..0c9d593 100644 --- a/WebCore/html/HTMLParamElement.cpp +++ b/WebCore/html/HTMLParamElement.cpp @@ -1,10 +1,8 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Stefan Schimanski (1Stein@gmx.de) - * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * Copyright (C) 2004, 2005, 2006, 2008 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 @@ -21,6 +19,7 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "HTMLParamElement.h" @@ -31,7 +30,7 @@ namespace WebCore { using namespace HTMLNames; -HTMLParamElement::HTMLParamElement(Document *doc) +HTMLParamElement::HTMLParamElement(Document* doc) : HTMLElement(paramTag, doc) { } @@ -40,12 +39,12 @@ HTMLParamElement::~HTMLParamElement() { } -void HTMLParamElement::parseMappedAttribute(MappedAttribute *attr) +void HTMLParamElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == idAttr) { // Must call base class so that hasID bit gets set. HTMLElement::parseMappedAttribute(attr); - if (document()->htmlMode() != Document::XHtml) + if (document()->isHTMLDocument()) return; m_name = attr->value(); } else if (attr->name() == nameAttr) { @@ -56,20 +55,20 @@ void HTMLParamElement::parseMappedAttribute(MappedAttribute *attr) HTMLElement::parseMappedAttribute(attr); } -bool HTMLParamElement::isURLAttribute(Attribute *attr) const +bool HTMLParamElement::isURLAttribute(Attribute* attr) const { if (attr->name() == valueAttr) { - Attribute *attr = attributes()->getAttributeItem(nameAttr); + Attribute* attr = attributes()->getAttributeItem(nameAttr); if (attr) { - String value = attr->value().domString().lower(); - if (value == "src" || value == "movie" || value == "data") + const AtomicString& value = attr->value(); + if (equalIgnoringCase(value, "data") || equalIgnoringCase(value, "movie") || equalIgnoringCase(value, "src")) return true; } } return false; } -void HTMLParamElement::setName(const String &value) +void HTMLParamElement::setName(const String& value) { setAttribute(nameAttr, value); } @@ -79,12 +78,12 @@ String HTMLParamElement::type() const return getAttribute(typeAttr); } -void HTMLParamElement::setType(const String &value) +void HTMLParamElement::setType(const String& value) { setAttribute(typeAttr, value); } -void HTMLParamElement::setValue(const String &value) +void HTMLParamElement::setValue(const String& value) { setAttribute(valueAttr, value); } @@ -94,9 +93,19 @@ String HTMLParamElement::valueType() const return getAttribute(valuetypeAttr); } -void HTMLParamElement::setValueType(const String &value) +void HTMLParamElement::setValueType(const String& value) { setAttribute(valuetypeAttr, value); } +void HTMLParamElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + if (!equalIgnoringCase(name(), "data") && + !equalIgnoringCase(name(), "movie") && + !equalIgnoringCase(name(), "src")) + return; + + urls.append(value()); +} + } diff --git a/WebCore/html/HTMLParamElement.h b/WebCore/html/HTMLParamElement.h index 3bc1fa1..5e31aed 100644 --- a/WebCore/html/HTMLParamElement.h +++ b/WebCore/html/HTMLParamElement.h @@ -55,6 +55,8 @@ public: String valueType() const; void setValueType(const String&); + virtual void getSubresourceAttributeStrings(Vector<String>&) const; + protected: AtomicString m_name; AtomicString m_value; diff --git a/WebCore/html/HTMLParser.cpp b/WebCore/html/HTMLParser.cpp index 8102680..ba2220c 100644 --- a/WebCore/html/HTMLParser.cpp +++ b/WebCore/html/HTMLParser.cpp @@ -28,7 +28,10 @@ #include "CSSPropertyNames.h" #include "CSSValueKeywords.h" #include "Comment.h" +#include "Console.h" +#include "DOMWindow.h" #include "DocumentFragment.h" +#include "DocumentType.h" #include "Frame.h" #include "HTMLBodyElement.h" #include "HTMLDocument.h" @@ -47,7 +50,6 @@ #include "HTMLTableSectionElement.h" #include "HTMLTokenizer.h" #include "LocalizedStrings.h" -#include "Page.h" #include "Settings.h" #include "Text.h" @@ -114,6 +116,7 @@ HTMLParser::HTMLParser(HTMLDocument* doc, bool reportErrors) , current(doc) , didRefCurrent(false) , blockStack(0) + , m_hasPElementInScope(NotInScope) , head(0) , inBody(false) , haveContent(false) @@ -130,6 +133,7 @@ HTMLParser::HTMLParser(DocumentFragment* frag) , current(frag) , didRefCurrent(true) , blockStack(0) + , m_hasPElementInScope(NotInScope) , head(0) , inBody(true) , haveContent(false) @@ -207,10 +211,11 @@ PassRefPtr<Node> HTMLParser::parseToken(Token* t) return 0; } - // ignore spaces, if we're not inside a paragraph or other inline code - if (t->tagName == textAtom && t->text) { - if (inBody && !skipMode() && current->localName() != styleTag && current->localName() != titleTag && - current->localName() != scriptTag && !t->text->containsOnlyWhitespace()) + // 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; RefPtr<Node> n; @@ -271,6 +276,16 @@ PassRefPtr<Node> HTMLParser::parseToken(Token* t) return n; } +void HTMLParser::parseDoctypeToken(DoctypeToken* t) +{ + // Ignore any doctype after the first. Ignore doctypes in fragments. + if (document->doctype() || m_isParsingFragment || current != 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))); +} + static bool isTableSection(Node* n) { return n->hasTagName(tbodyTag) || n->hasTagName(tfootTag) || n->hasTagName(theadTag); @@ -287,6 +302,11 @@ static bool isTableRelated(Node* n) return n->hasTagName(tableTag) || isTablePart(n); } +static bool isScopingTag(const AtomicString& tagName) +{ + return tagName == appletTag || tagName == captionTag || tagName == tdTag || tagName == thTag || tagName == buttonTag || tagName == marqueeTag || tagName == objectTag || tagName == tableTag || tagName == htmlTag; +} + bool HTMLParser::insertNode(Node* n, bool flat) { RefPtr<Node> protectNode(n); @@ -318,6 +338,7 @@ bool HTMLParser::insertNode(Node* n, bool flat) // 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); newNode->ref(); current = newNode; @@ -374,7 +395,7 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName, } } else if (h->hasLocalName(htmlTag)) { if (!current->isDocumentNode() ) { - if (document->documentElement()->hasTagName(htmlTag)) { + if (document->documentElement() && 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 @@ -406,6 +427,7 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName, reportError(MisplacedHeadContentError, &localName, ¤t->localName()); pushBlock(localName, tagPriority); + newNode->beginParsingChildren(); setCurrent(newNode); if (!n->attached() && !m_isParsingFragment) n->attach(); @@ -456,7 +478,7 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName, // 2. Next we examine our currently active element to do some further error handling. if (current->isHTMLElement()) { HTMLElement* h = static_cast<HTMLElement*>(current); - const AtomicString& currentTagName = current->localName(); + const AtomicString& currentTagName = h->localName(); if (h->hasLocalName(htmlTag)) { HTMLElement* elt = n->isHTMLElement() ? static_cast<HTMLElement*>(n) : 0; if (elt && (elt->hasLocalName(scriptTag) || elt->hasLocalName(styleTag) || @@ -498,8 +520,8 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName, } else reportError(MisplacedFramesetContentError, &localName); } - } else if (h->hasLocalName(addressTag) || h->hasLocalName(dlTag) || h->hasLocalName(dtTag) - || h->hasLocalName(fontTag) || h->hasLocalName(styleTag) || h->hasLocalName(titleTag)) { + } else if (h->hasLocalName(addressTag) || h->hasLocalName(fontTag) + || h->hasLocalName(styleTag) || h->hasLocalName(titleTag)) { reportError(MisplacedContentRetryError, &localName, ¤tTagName); popBlock(currentTagName); handled = true; @@ -549,6 +571,7 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName, !flat && static_cast<HTMLElement*>(n)->endTagRequirement() != TagStatusForbidden) { pushBlock(localName, tagPriority); + n->beginParsingChildren(); setCurrent(n); inStrayTableContent++; blockStack->strayTableContent = true; @@ -591,6 +614,12 @@ bool HTMLParser::handleError(Node* n, bool flat, const AtomicString& localName, // IE treats a nested select as </select>. Let's do the same popBlock(localName); } + } else if (h->hasLocalName(selectTag)) { + if (localName == inputTag || localName == textareaTag) { + reportError(MisplacedContentRetryError, &localName, ¤tTagName); + popBlock(currentTagName); + handled = true; + } } else if (h->hasLocalName(colgroupTag)) { popBlock(currentTagName); handled = true; @@ -677,13 +706,6 @@ bool HTMLParser::framesetCreateErrorCheck(Token* t, RefPtr<Node>& result) return true; } -bool HTMLParser::iframeCreateErrorCheck(Token* t, RefPtr<Node>& result) -{ - // a bit of a special case, since the frame is inlined - setSkipMode(iframeTag); - return true; -} - bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result) { // Only create a new form if we're not already inside one. @@ -691,6 +713,7 @@ bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result) if (!m_currentFormElement) { m_currentFormElement = new HTMLFormElement(document); result = m_currentFormElement; + pCloserCreateErrorCheck(t, result); } return false; } @@ -714,6 +737,7 @@ bool HTMLParser::selectCreateErrorCheck(Token* t, RefPtr<Node>& result) bool HTMLParser::ddCreateErrorCheck(Token* t, RefPtr<Node>& result) { + pCloserCreateErrorCheck(t, result); popBlock(dtTag); popBlock(ddTag); return true; @@ -721,6 +745,7 @@ bool HTMLParser::ddCreateErrorCheck(Token* t, RefPtr<Node>& result) bool HTMLParser::dtCreateErrorCheck(Token* t, RefPtr<Node>& result) { + pCloserCreateErrorCheck(t, result); popBlock(ddTag); popBlock(dtTag); return true; @@ -732,6 +757,13 @@ bool HTMLParser::nestedCreateErrorCheck(Token* t, RefPtr<Node>& result) return true; } +bool HTMLParser::nestedPCloserCreateErrorCheck(Token* t, RefPtr<Node>& result) +{ + pCloserCreateErrorCheck(t, result); + popBlock(t->tagName); + return true; +} + bool HTMLParser::nestedStyleCreateErrorCheck(Token* t, RefPtr<Node>& result) { return allowNestedRedundantTag(t->tagName); @@ -774,6 +806,22 @@ bool HTMLParser::noscriptCreateErrorCheck(Token* t, RefPtr<Node>& result) return true; } +bool HTMLParser::pCloserCreateErrorCheck(Token* t, RefPtr<Node>& result) +{ + if (hasPElementInScope()) + popBlock(pTag); + return true; +} + +bool HTMLParser::pCloserStrictCreateErrorCheck(Token* t, RefPtr<Node>& result) +{ + if (document->inCompatMode()) + return true; + if (hasPElementInScope()) + popBlock(pTag); + return true; +} + bool HTMLParser::mapCreateErrorCheck(Token* t, RefPtr<Node>& result) { m_currentMapElement = new HTMLMapElement(document); @@ -787,29 +835,49 @@ PassRefPtr<Node> HTMLParser::getNode(Token* t) static FunctionMap gFunctionMap; if (gFunctionMap.isEmpty()) { gFunctionMap.set(aTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck); + gFunctionMap.set(addressTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(bTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(bigTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); + gFunctionMap.set(blockquoteTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(bodyTag.localName().impl(), &HTMLParser::bodyCreateErrorCheck); gFunctionMap.set(buttonTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck); + gFunctionMap.set(centerTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(commentAtom.impl(), &HTMLParser::commentCreateErrorCheck); gFunctionMap.set(ddTag.localName().impl(), &HTMLParser::ddCreateErrorCheck); + gFunctionMap.set(dirTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); + gFunctionMap.set(divTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); + gFunctionMap.set(dlTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(dtTag.localName().impl(), &HTMLParser::dtCreateErrorCheck); gFunctionMap.set(formTag.localName().impl(), &HTMLParser::formCreateErrorCheck); + gFunctionMap.set(fieldsetTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(framesetTag.localName().impl(), &HTMLParser::framesetCreateErrorCheck); + gFunctionMap.set(h1Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); + gFunctionMap.set(h2Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); + gFunctionMap.set(h3Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); + gFunctionMap.set(h4Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); + gFunctionMap.set(h5Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); + gFunctionMap.set(h6Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(headTag.localName().impl(), &HTMLParser::headCreateErrorCheck); + gFunctionMap.set(hrTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(iTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); - gFunctionMap.set(iframeTag.localName().impl(), &HTMLParser::iframeCreateErrorCheck); gFunctionMap.set(isindexTag.localName().impl(), &HTMLParser::isindexCreateErrorCheck); - gFunctionMap.set(liTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck); + gFunctionMap.set(liTag.localName().impl(), &HTMLParser::nestedPCloserCreateErrorCheck); + gFunctionMap.set(listingTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(mapTag.localName().impl(), &HTMLParser::mapCreateErrorCheck); + gFunctionMap.set(menuTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(nobrTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck); gFunctionMap.set(noembedTag.localName().impl(), &HTMLParser::noembedCreateErrorCheck); gFunctionMap.set(noframesTag.localName().impl(), &HTMLParser::noframesCreateErrorCheck); gFunctionMap.set(noscriptTag.localName().impl(), &HTMLParser::noscriptCreateErrorCheck); + gFunctionMap.set(olTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); + gFunctionMap.set(pTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); + gFunctionMap.set(plaintextTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); + gFunctionMap.set(preTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(sTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(selectTag.localName().impl(), &HTMLParser::selectCreateErrorCheck); gFunctionMap.set(smallTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(strikeTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); + gFunctionMap.set(tableTag.localName().impl(), &HTMLParser::pCloserStrictCreateErrorCheck); gFunctionMap.set(tbodyTag.localName().impl(), &HTMLParser::tableSectionCreateErrorCheck); gFunctionMap.set(tdTag.localName().impl(), &HTMLParser::tableCellCreateErrorCheck); gFunctionMap.set(textAtom.impl(), &HTMLParser::textCreateErrorCheck); @@ -819,6 +887,7 @@ PassRefPtr<Node> HTMLParser::getNode(Token* t) gFunctionMap.set(trTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck); gFunctionMap.set(ttTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(uTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); + gFunctionMap.set(ulTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); } bool proceed = true; @@ -1011,6 +1080,8 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem) if (!parentElem->childAllowed(blockElem)) return; + m_hasPElementInScope = Unknown; + if (maxElem->node->parentNode() != elem->node) { // Walk the stack and remove any elements that aren't residual style tags. These // are basically just being closed up. Example: @@ -1089,7 +1160,6 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem) blockElem->parentNode()->removeChild(blockElem, ec); Node* newNodePtr = 0; - ASSERT(finished || blockElem->firstChild()); if (blockElem->firstChild()) { // Step 2: Clone |residualElem|. RefPtr<Node> newNode = residualElem->cloneNode(false); // Shallow clone. We don't pick up the same kids. @@ -1109,7 +1179,8 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem) // Step 4: Place |newNode| under |blockElem|. |blockElem| is still out of the document, so no // attachment can occur yet. blockElem->appendChild(newNode.release(), ec); - } + } else + finished = true; // Step 5: Reparent |blockElem|. Now the full attachment of the fixed up tree takes place. if (isBlockStillInTree) @@ -1157,10 +1228,11 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem) HTMLStackElem* curr = blockStack; HTMLStackElem* residualStyleStack = 0; unsigned stackDepth = 1; + unsigned redundantStyleCount = 0; while (curr && curr != maxElem) { // We will actually schedule this tag for reopening // after we complete the close of this entire block. - if (isResidualStyleTag(curr->tagName) && stackDepth++ < cResidualStyleMaxDepth) + if (isResidualStyleTag(curr->tagName) && stackDepth++ < cResidualStyleMaxDepth) { // We've overloaded the use of stack elements and are just reusing the // struct with a slightly different meaning to the variables. Instead of chaining // from innermost to outermost, we build up a list of all the tags we need to reopen @@ -1169,8 +1241,16 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem) // We also set curr->node to be the actual element that corresponds to the ID stored in // curr->id rather than the node that you should pop to when the element gets pulled off // the stack. - moveOneBlockToStack(residualStyleStack); - else + if (residualStyleStack && curr->tagName == residualStyleStack->tagName && curr->node->attributes()->mapsEquivalent(residualStyleStack->node->attributes())) + redundantStyleCount++; + else + redundantStyleCount = 0; + + if (redundantStyleCount < cMaxRedundantTagDepth) + moveOneBlockToStack(residualStyleStack); + else + popOneBlock(); + } else popOneBlock(); curr = blockStack; @@ -1200,6 +1280,7 @@ void HTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTab // Now push a new stack element for this node we just created. pushBlock(elem->tagName, elem->level); + newNode->beginParsingChildren(); // Set our strayTableContent boolean if needed, so that the reopened tag also knows // that it is inside a malformed table. @@ -1223,9 +1304,12 @@ void HTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, Node* malformedTab void HTMLParser::pushBlock(const AtomicString& tagName, int level) { - current->beginParsingChildren(); blockStack = new HTMLStackElem(tagName, level, current, didRefCurrent, blockStack); didRefCurrent = false; + if (tagName == pTag) + m_hasPElementInScope = InScope; + else if (isScopingTag(tagName)) + m_hasPElementInScope = NotInScope; } void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors) @@ -1260,6 +1344,7 @@ void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors) elem = blockStack; unsigned stackDepth = 1; + unsigned redundantStyleCount = 0; while (elem) { if (elem->tagName == tagName) { int strayTable = inStrayTableContent; @@ -1286,7 +1371,7 @@ void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors) // Schedule this tag for reopening // after we complete the close of this entire block. - if (isAffectedByStyle && isResidualStyleTag(elem->tagName) && stackDepth++ < cResidualStyleMaxDepth) + if (isAffectedByStyle && isResidualStyleTag(elem->tagName) && stackDepth++ < cResidualStyleMaxDepth) { // We've overloaded the use of stack elements and are just reusing the // struct with a slightly different meaning to the variables. Instead of chaining // from innermost to outermost, we build up a list of all the tags we need to reopen @@ -1295,8 +1380,16 @@ void HTMLParser::popBlock(const AtomicString& tagName, bool reportErrors) // We also set elem->node to be the actual element that corresponds to the ID stored in // elem->id rather than the node that you should pop to when the element gets pulled off // the stack. - moveOneBlockToStack(residualStyleStack); - else + if (residualStyleStack && elem->tagName == residualStyleStack->tagName && elem->node->attributes()->mapsEquivalent(residualStyleStack->node->attributes())) + redundantStyleCount++; + else + redundantStyleCount = 0; + + if (redundantStyleCount < cMaxRedundantTagDepth) + moveOneBlockToStack(residualStyleStack); + else + popOneBlock(); + } else popOneBlock(); elem = blockStack; } @@ -1321,6 +1414,11 @@ inline HTMLStackElem* HTMLParser::popOneBlockCommon() if (elem->strayTableContent) inStrayTableContent--; + if (elem->tagName == pTag) + m_hasPElementInScope = NotInScope; + else if (isScopingTag(elem->tagName)) + m_hasPElementInScope = Unknown; + return elem; } @@ -1358,6 +1456,21 @@ void HTMLParser::moveOneBlockToStack(HTMLStackElem*& head) head = elem; } +void HTMLParser::checkIfHasPElementInScope() +{ + m_hasPElementInScope = NotInScope; + HTMLStackElem* elem = blockStack; + while (elem) { + const AtomicString& tagName = elem->tagName; + if (tagName == pTag) { + m_hasPElementInScope = InScope; + return; + } else if (isScopingTag(tagName)) + return; + elem = elem->next; + } +} + void HTMLParser::popInlineBlocks() { while (blockStack && isInline(current)) @@ -1402,7 +1515,7 @@ PassRefPtr<Node> HTMLParser::handleIsindex(Token* t) String text = searchableIndexIntroduction(); if (attrs) { if (Attribute* a = attrs->getAttributeItem(promptAttr)) - text = a->value().domString() + " "; + text = a->value().string() + " "; t->attrs = 0; } @@ -1448,10 +1561,6 @@ void HTMLParser::reportErrorToConsole(HTMLParserErrorCode errorCode, const Atomi if (!frame) return; - Page* page = frame->page(); - if (!page) - return; - HTMLTokenizer* htmlTokenizer = static_cast<HTMLTokenizer*>(document->tokenizer()); int lineNumber = htmlTokenizer->lineNumber() + 1; @@ -1485,7 +1594,9 @@ void HTMLParser::reportErrorToConsole(HTMLParserErrorCode errorCode, const Atomi message.replace("%tag1", tag1); message.replace("%tag2", tag2); - page->chrome()->addMessageToConsole(HTMLMessageSource, isWarning(errorCode) ? WarningMessageLevel: ErrorMessageLevel, message, lineNumber, document->url()); + frame->domWindow()->console()->addMessage(HTMLMessageSource, + isWarning(errorCode) ? WarningMessageLevel : ErrorMessageLevel, + message, lineNumber, document->url().string()); } } diff --git a/WebCore/html/HTMLParser.h b/WebCore/html/HTMLParser.h index 0c51a3f..3a5b437 100644 --- a/WebCore/html/HTMLParser.h +++ b/WebCore/html/HTMLParser.h @@ -31,6 +31,7 @@ namespace WebCore { +class DoctypeToken; class Document; class DocumentFragment; class HTMLDocument; @@ -57,6 +58,9 @@ public: */ PassRefPtr<Node> parseToken(Token*); + // Parses a doctype token. + void parseDoctypeToken(DoctypeToken*); + /** * tokenizer says it's not going to be sending us any more tokens */ @@ -88,11 +92,14 @@ private: bool isindexCreateErrorCheck(Token*, RefPtr<Node>&); bool mapCreateErrorCheck(Token*, RefPtr<Node>&); bool nestedCreateErrorCheck(Token*, RefPtr<Node>&); + bool nestedPCloserCreateErrorCheck(Token*, RefPtr<Node>&); bool nestedStyleCreateErrorCheck(Token*, RefPtr<Node>&); bool noembedCreateErrorCheck(Token*, RefPtr<Node>&); bool noframesCreateErrorCheck(Token*, RefPtr<Node>&); bool nolayerCreateErrorCheck(Token*, RefPtr<Node>&); bool noscriptCreateErrorCheck(Token*, RefPtr<Node>&); + bool pCloserCreateErrorCheck(Token*, RefPtr<Node>&); + bool pCloserStrictCreateErrorCheck(Token*, RefPtr<Node>&); bool selectCreateErrorCheck(Token*, RefPtr<Node>&); bool tableCellCreateErrorCheck(Token*, RefPtr<Node>&); bool tableSectionCreateErrorCheck(Token*, RefPtr<Node>&); @@ -130,6 +137,14 @@ private: void startBody(); // inserts the isindex element PassRefPtr<Node> handleIsindex(Token*); + void checkIfHasPElementInScope(); + bool hasPElementInScope() + { + if (m_hasPElementInScope == Unknown) + checkIfHasPElementInScope(); + return m_hasPElementInScope == InScope; + } + void reportError(HTMLParserErrorCode errorCode, const AtomicString* tagName1 = 0, const AtomicString* tagName2 = 0, bool closeTags = false) { if (!m_reportErrors) return; reportErrorToConsole(errorCode, tagName1, tagName2, closeTags); } @@ -144,6 +159,9 @@ private: HTMLStackElem* blockStack; + 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> diff --git a/WebCore/html/HTMLPlugInElement.cpp b/WebCore/html/HTMLPlugInElement.cpp index 223591a..5f585e7 100644 --- a/WebCore/html/HTMLPlugInElement.cpp +++ b/WebCore/html/HTMLPlugInElement.cpp @@ -34,19 +34,18 @@ #include "RenderWidget.h" #include "Settings.h" #include "Widget.h" -#include "kjs_dom.h" -#include "kjs_proxy.h" +#include "ScriptController.h" -#if USE(NPOBJECT) -#include <bindings/NP_jsobject.h> -#include <bindings/npruntime_impl.h> -#include <bindings/runtime_root.h> +#if USE(JSC) +#include "runtime.h" #endif -using KJS::ExecState; -using KJS::JSLock; -using KJS::JSValue; -using KJS::Bindings::RootObject; +#if ENABLE(NETSCAPE_PLUGIN_API) +#include "JSNode.h" +#include "NP_jsobject.h" +#include "npruntime_impl.h" +#include "runtime_root.h" +#endif namespace WebCore { @@ -54,12 +53,12 @@ using namespace HTMLNames; HTMLPlugInElement::HTMLPlugInElement(const QualifiedName& tagName, Document* doc) : HTMLFrameOwnerElement(tagName, doc) -#if USE(NPOBJECT) +#if ENABLE(NETSCAPE_PLUGIN_API) , m_NPObject(0) #endif #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 -// ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap +// ensure that m_name is removed from HTMLDocument's NameCountMap , oldNameIdCount(0) #endif { @@ -67,7 +66,11 @@ HTMLPlugInElement::HTMLPlugInElement(const QualifiedName& tagName, Document* doc HTMLPlugInElement::~HTMLPlugInElement() { -#if USE(NPOBJECT) +#if USE(JSC) + ASSERT(!m_instance); // cleared in detach() +#endif + +#if ENABLE(NETSCAPE_PLUGIN_API) if (m_NPObject) { _NPN_ReleaseObject(m_NPObject); m_NPObject = 0; @@ -75,6 +78,32 @@ HTMLPlugInElement::~HTMLPlugInElement() #endif } +#if USE(JSC) +void HTMLPlugInElement::detach() +{ + m_instance.clear(); + HTMLFrameOwnerElement::detach(); +} + +JSC::Bindings::Instance* HTMLPlugInElement::getInstance() const +{ + Frame* frame = document()->frame(); + if (!frame) + return 0; + + // If the host dynamically turns off JavaScript (or Java) we will still return + // the cached allocated Bindings::Instance. Not supporting this edge-case is OK. + if (m_instance) + return m_instance.get(); + + RenderWidget* renderWidget = renderWidgetForJSBindings(); + if (renderWidget && renderWidget->widget()) + m_instance = frame->script()->createScriptInstanceForWidget(renderWidget->widget()); + + return m_instance.get(); +} +#endif + String HTMLPlugInElement::align() const { return getAttribute(alignAttr); @@ -136,20 +165,20 @@ bool HTMLPlugInElement::mapToEntry(const QualifiedName& attrName, MappedAttribut void HTMLPlugInElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == widthAttr) - addCSSLength(attr, CSS_PROP_WIDTH, attr->value()); + addCSSLength(attr, CSSPropertyWidth, attr->value()); else if (attr->name() == heightAttr) - addCSSLength(attr, CSS_PROP_HEIGHT, attr->value()); + addCSSLength(attr, CSSPropertyHeight, attr->value()); else if (attr->name() == vspaceAttr) { - addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value()); + addCSSLength(attr, CSSPropertyMarginTop, attr->value()); + addCSSLength(attr, CSSPropertyMarginBottom, attr->value()); } else if (attr->name() == hspaceAttr) { - addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value()); + addCSSLength(attr, CSSPropertyMarginLeft, attr->value()); + addCSSLength(attr, CSSPropertyMarginRight, attr->value()); } else if (attr->name() == alignAttr) addHTMLAlignment(attr); else HTMLFrameOwnerElement::parseMappedAttribute(attr); -} +} bool HTMLPlugInElement::checkDTD(const Node* newChild) { @@ -166,48 +195,17 @@ void HTMLPlugInElement::defaultEventHandler(Event* event) widget->handleEvent(event); } -#if USE(NPOBJECT) - -NPObject* HTMLPlugInElement::createNPObject() -{ - Frame* frame = document()->frame(); - if (!frame) { - // This shouldn't ever happen, but might as well check anyway. - ASSERT_NOT_REACHED(); - return _NPN_CreateNoScriptObject(); - } - - Settings* settings = frame->settings(); - if (!settings) { - // This shouldn't ever happen, but might as well check anyway. - ASSERT_NOT_REACHED(); - return _NPN_CreateNoScriptObject(); - } - - // Can't create NPObjects when JavaScript is disabled - if (!frame->scriptProxy()->isEnabled()) - return _NPN_CreateNoScriptObject(); - - // Create a JSObject bound to this element - JSLock lock; - ExecState *exec = frame->scriptProxy()->globalObject()->globalExec(); - JSValue* jsElementValue = toJS(exec, this); - if (!jsElementValue || !jsElementValue->isObject()) - return _NPN_CreateNoScriptObject(); - - // Wrap the JSObject in an NPObject - RootObject* rootObject = frame->bindingRootObject(); - return _NPN_CreateScriptObject(0, jsElementValue->getObject(), rootObject); -} +#if ENABLE(NETSCAPE_PLUGIN_API) NPObject* HTMLPlugInElement::getNPObject() { + ASSERT(document()->frame()); if (!m_NPObject) - m_NPObject = createNPObject(); + m_NPObject = document()->frame()->script()->createScriptObjectForPluginElement(this); return m_NPObject; } -#endif /* USE(NPOBJECT) */ +#endif /* ENABLE(NETSCAPE_PLUGIN_API) */ void HTMLPlugInElement::updateWidgetCallback(Node* n) { diff --git a/WebCore/html/HTMLPlugInElement.h b/WebCore/html/HTMLPlugInElement.h index 5fad211..2b8c8ca 100644 --- a/WebCore/html/HTMLPlugInElement.h +++ b/WebCore/html/HTMLPlugInElement.h @@ -1,9 +1,7 @@ /* - * This file is part of the DOM implementation for KDE. - * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2006 Apple Computer, Inc. + * Copyright (C) 2004, 2006, 2007, 2008 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,16 +25,22 @@ #include "HTMLFrameOwnerElement.h" -#if USE(JAVASCRIPTCORE_BINDINGS) -#include <bindings/runtime.h> +#if USE(JSC) +namespace JSC { + namespace Bindings { + class Instance; + } +} #endif -#if USE(NPOBJECT) -#include <bindings/npruntime_internal.h> +#if ENABLE(NETSCAPE_PLUGIN_API) +struct NPObject; #endif namespace WebCore { +class RenderWidget; + class HTMLPlugInElement : public HTMLFrameOwnerElement { public: HTMLPlugInElement(const QualifiedName& tagName, Document*); @@ -62,32 +66,31 @@ public: String width() const; void setWidth(const String&); -#if USE(JAVASCRIPTCORE_BINDINGS) - virtual KJS::Bindings::Instance* getInstance() const = 0; -#endif -#if USE(NPOBJECT) - virtual NPObject* getNPObject(); + virtual void defaultEventHandler(Event*); + + virtual RenderWidget* renderWidgetForJSBindings() const = 0; +#if USE(JSC) + virtual void detach(); + JSC::Bindings::Instance* getInstance() const; #endif - virtual void defaultEventHandler(Event*); -private: -#if USE(NPOBJECT) - NPObject* createNPObject(); +#if ENABLE(NETSCAPE_PLUGIN_API) + virtual NPObject* getNPObject(); #endif protected: static void updateWidgetCallback(Node*); - String oldNameAttr; -#if USE(JAVASCRIPTCORE_BINDINGS) - mutable RefPtr<KJS::Bindings::Instance> m_instance; + AtomicString m_name; +#if USE(JSC) + mutable RefPtr<JSC::Bindings::Instance> m_instance; #endif -#if USE(NPOBJECT) +#if ENABLE(NETSCAPE_PLUGIN_API) NPObject* m_NPObject; #endif #ifdef ANDROID_FIX // addressing webkit bug, http://bugs.webkit.org/show_bug.cgi?id=16512 - // ensure the oldNameAttr and oldIdAttr are removed from HTMLDocument's NameCountMap + // ensure that m_name is removed from HTMLDocument's NameCountMap int oldNameIdCount; #endif }; diff --git a/WebCore/html/HTMLPlugInImageElement.cpp b/WebCore/html/HTMLPlugInImageElement.cpp new file mode 100644 index 0000000..6dcd5fb --- /dev/null +++ b/WebCore/html/HTMLPlugInImageElement.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 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 + * 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 "HTMLPlugInImageElement.h" + +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameLoaderClient.h" +#include "HTMLImageLoader.h" +#include "Image.h" + +namespace WebCore { + +HTMLPlugInImageElement::HTMLPlugInImageElement(const QualifiedName& tagName, Document* document) + : HTMLPlugInElement(tagName, document) +{ +} + +HTMLPlugInImageElement::~HTMLPlugInImageElement() +{ +} + +bool HTMLPlugInImageElement::isImageType() +{ + if (m_serviceType.isEmpty() && protocolIs(m_url, "data")) + m_serviceType = mimeTypeFromDataURL(m_url); + + if (Frame* frame = document()->frame()) { + KURL completedURL = frame->loader()->completeURL(m_url); + return frame->loader()->client()->objectContentType(completedURL, m_serviceType) == ObjectContentImage; + } + + return Image::supportsType(m_serviceType); +} + +} // namespace WebCore diff --git a/WebCore/html/HTMLPlugInImageElement.h b/WebCore/html/HTMLPlugInImageElement.h new file mode 100644 index 0000000..ec3b258 --- /dev/null +++ b/WebCore/html/HTMLPlugInImageElement.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 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 + * 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 HTMLPlugInImageElement_h +#define HTMLPlugInImageElement_h + +#include "HTMLPlugInElement.h" +#include <wtf/OwnPtr.h> + +namespace WebCore { + +class HTMLImageLoader; + +class HTMLPlugInImageElement : public HTMLPlugInElement { +public: + HTMLPlugInImageElement(const QualifiedName& tagName, Document*); + virtual ~HTMLPlugInImageElement(); + + bool isImageType(); + + const String& serviceType() const { return m_serviceType; } + const String& url() const { return m_url; } + +protected: + OwnPtr<HTMLImageLoader> m_imageLoader; + String m_serviceType; + String m_url; +}; + +} // namespace WebCore + +#endif // HTMLPlugInImageElement_h diff --git a/WebCore/html/HTMLPreElement.cpp b/WebCore/html/HTMLPreElement.cpp index 5597e7f..23ecaaa 100644 --- a/WebCore/html/HTMLPreElement.cpp +++ b/WebCore/html/HTMLPreElement.cpp @@ -55,7 +55,7 @@ void HTMLPreElement::parseMappedAttribute(MappedAttribute *attr) // property. } else if (attr->name() == wrapAttr) { if (!attr->value().isNull()) - addCSSProperty(attr, CSS_PROP_WHITE_SPACE, CSS_VAL_PRE_WRAP); + addCSSProperty(attr, CSSPropertyWhiteSpace, CSSValuePreWrap); } else return HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLScriptElement.cpp b/WebCore/html/HTMLScriptElement.cpp index 9857c1f..ce334d7 100644 --- a/WebCore/html/HTMLScriptElement.cpp +++ b/WebCore/html/HTMLScriptElement.cpp @@ -1,10 +1,8 @@ -/** - * This file is part of the DOM implementation for KDE. - * +/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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 @@ -21,253 +19,98 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "HTMLScriptElement.h" -#include "CachedScript.h" -#include "DocLoader.h" #include "Document.h" #include "EventNames.h" -#include "Frame.h" -#include "FrameLoader.h" #include "HTMLNames.h" -#include "kjs_proxy.h" -#include "MIMETypeRegistry.h" #include "Text.h" namespace WebCore { using namespace HTMLNames; -using namespace EventNames; -HTMLScriptElement::HTMLScriptElement(Document *doc) +HTMLScriptElement::HTMLScriptElement(Document* doc) : HTMLElement(scriptTag, doc) - , m_cachedScript(0) - , m_createdByParser(false) - , m_evaluated(false) + , m_data(this, this) { } HTMLScriptElement::~HTMLScriptElement() { - if (m_cachedScript) - m_cachedScript->deref(this); } -bool HTMLScriptElement::isURLAttribute(Attribute *attr) const +bool HTMLScriptElement::isURLAttribute(Attribute* attr) const +{ + return attr->name() == sourceAttributeValue(); +} + +void HTMLScriptElement::setCreatedByParser(bool createdByParser) { - return attr->name() == srcAttr; + m_data.setCreatedByParser(createdByParser); } -void HTMLScriptElement::childrenChanged(bool changedByParser) +bool HTMLScriptElement::shouldExecuteAsJavaScript() const { - // If a node is inserted as a child of the script element - // and the script element has been inserted in the document - // we evaluate the script. - if (!m_createdByParser && inDocument() && firstChild()) - evaluateScript(document()->url(), text()); - HTMLElement::childrenChanged(changedByParser); + return m_data.shouldExecuteAsJavaScript(); } -void HTMLScriptElement::parseMappedAttribute(MappedAttribute *attr) +void HTMLScriptElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) +{ + ScriptElement::childrenChanged(m_data); + HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); +} + +void HTMLScriptElement::parseMappedAttribute(MappedAttribute* attr) { const QualifiedName& attrName = attr->name(); - if (attrName == srcAttr) { - if (m_evaluated || m_cachedScript || m_createdByParser || !inDocument()) - return; - - // FIXME: Evaluate scripts in viewless documents. - // See http://bugs.webkit.org/show_bug.cgi?id=5727 - if (!document()->frame()) - return; - - const AtomicString& url = attr->value(); - if (!url.isEmpty()) { - m_cachedScript = document()->docLoader()->requestScript(url, getAttribute(charsetAttr)); - if (m_cachedScript) - m_cachedScript->ref(this); - else - dispatchHTMLEvent(errorEvent, true, false); - } - } else if (attrName == onloadAttr) - setHTMLEventListener(loadEvent, attr); + + if (attrName == srcAttr) + handleSourceAttribute(m_data, attr->value()); + else if (attrName == onloadAttr) + setInlineEventListenerForTypeAndAttribute(eventNames().loadEvent, attr); else HTMLElement::parseMappedAttribute(attr); } void HTMLScriptElement::finishParsingChildren() { - // The parser just reached </script>. If we have no src and no text, - // allow dynamic loading later. - if (getAttribute(srcAttr).isEmpty() && text().isEmpty()) - setCreatedByParser(false); + ScriptElement::finishParsingChildren(m_data, sourceAttributeValue()); HTMLElement::finishParsingChildren(); } void HTMLScriptElement::insertedIntoDocument() { HTMLElement::insertedIntoDocument(); - - ASSERT(!m_cachedScript); - - if (m_createdByParser) - return; - - // FIXME: Eventually we'd like to evaluate scripts which are inserted into a - // viewless document but this'll do for now. - // See http://bugs.webkit.org/show_bug.cgi?id=5727 - if (!document()->frame()) - return; - - const AtomicString& url = getAttribute(srcAttr); - if (!url.isEmpty()) { - String scriptSrcCharset = getAttribute(charsetAttr).domString().stripWhiteSpace(); - if (scriptSrcCharset.isEmpty()) { - if (Frame* frame = document()->frame()) - scriptSrcCharset = frame->loader()->encoding(); - } - m_cachedScript = document()->docLoader()->requestScript(url, scriptSrcCharset); - if (m_cachedScript) - m_cachedScript->ref(this); - else - dispatchHTMLEvent(errorEvent, true, false); - return; - } - - // If there's an empty script node, we shouldn't evaluate the script - // because if a script is inserted afterwards (by setting text or innerText) - // it should be evaluated, and evaluateScript only evaluates a script once. - String scriptString = text(); - if (!scriptString.isEmpty()) - evaluateScript(document()->url(), scriptString); + ScriptElement::insertedIntoDocument(m_data, sourceAttributeValue()); } void HTMLScriptElement::removedFromDocument() { HTMLElement::removedFromDocument(); - - if (m_cachedScript) { - m_cachedScript->deref(this); - m_cachedScript = 0; - } -} - -void HTMLScriptElement::notifyFinished(CachedResource* o) -{ - CachedScript *cs = static_cast<CachedScript *>(o); - - ASSERT(cs == m_cachedScript); - - // Evaluating the script could lead to a garbage collection which - // can delete the script element so we need to protect it. - RefPtr<HTMLScriptElement> protect(this); - - if (cs->errorOccurred()) - dispatchHTMLEvent(errorEvent, true, false); - else { - evaluateScript(cs->url(), cs->script()); - dispatchHTMLEvent(loadEvent, false, false); - } - - // script evaluation may have dereffed it already - if (m_cachedScript) { - m_cachedScript->deref(this); - m_cachedScript = 0; - } -} - -bool HTMLScriptElement::shouldExecuteAsJavaScript() -{ - /* - Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only javascript1.1 - javascript1.3. - Mozilla 1.8 and WinIE 7 both accept javascript and livescript. - WinIE 7 accepts ecmascript and jscript, but Mozilla 1.8 doesn't. - Neither Mozilla 1.8 nor WinIE 7 accept leading or trailing whitespace. - We want to accept all the values that either of these browsers accept, but not other values. - */ - static const AtomicString validLanguages[] = { - "javascript", - "javascript1.0", - "javascript1.1", - "javascript1.2", - "javascript1.3", - "javascript1.4", - "javascript1.5", - "javascript1.6", - "javascript1.7", - "livescript", - "ecmascript", - "jscript" - }; - static const unsigned validLanguagesCount = sizeof(validLanguages) / sizeof(validLanguages[0]); - - const AtomicString& type = getAttribute(typeAttr); - if (!type.isEmpty()) { - String lowerType = type.domString().stripWhiteSpace().lower(); - if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(lowerType)) - return true; - - return false; - } - - const AtomicString& language = getAttribute(languageAttr); - if (!language.isEmpty()) { - String lowerLanguage = language.domString().lower(); - for (unsigned i = 0; i < validLanguagesCount; ++i) - if (lowerLanguage == validLanguages[i]) - return true; - - return false; - } - - // No type or language is specified, so we assume the script to be JavaScript - return true; -} - -void HTMLScriptElement::evaluateScript(const String& url, const String& script) -{ - if (m_evaluated) - return; - - if (!shouldExecuteAsJavaScript()) - return; - - Frame* frame = document()->frame(); - if (frame) { - if (frame->scriptProxy()->isEnabled()) { - m_evaluated = true; - frame->scriptProxy()->evaluate(url, 0, script); - Document::updateDocumentsRendering(); - } - } + ScriptElement::removedFromDocument(m_data); } String HTMLScriptElement::text() const { - String val = ""; - - for (Node *n = firstChild(); n; n = n->nextSibling()) { - if (n->isTextNode()) - val += static_cast<Text *>(n)->data(); - } - - return val; + return m_data.scriptContent(); } void HTMLScriptElement::setText(const String &value) { ExceptionCode ec = 0; int numChildren = childNodeCount(); - + if (numChildren == 1 && firstChild()->isTextNode()) { - static_cast<Text *>(firstChild())->setData(value, ec); + static_cast<Text*>(firstChild())->setData(value, ec); return; } - - if (numChildren > 0) { + + if (numChildren > 0) removeChildren(); - } - + appendChild(document()->createTextNode(value.impl()), ec); } @@ -277,7 +120,7 @@ String HTMLScriptElement::htmlFor() const return String(); } -void HTMLScriptElement::setHtmlFor(const String &/*value*/) +void HTMLScriptElement::setHtmlFor(const String&) { // DOM Level 1 says: reserved for future use. } @@ -288,14 +131,14 @@ String HTMLScriptElement::event() const return String(); } -void HTMLScriptElement::setEvent(const String &/*value*/) +void HTMLScriptElement::setEvent(const String&) { // DOM Level 1 says: reserved for future use. } String HTMLScriptElement::charset() const { - return getAttribute(charsetAttr); + return charsetAttributeValue(); } void HTMLScriptElement::setCharset(const String &value) @@ -313,9 +156,9 @@ void HTMLScriptElement::setDefer(bool defer) setAttribute(deferAttr, defer ? "" : 0); } -String HTMLScriptElement::src() const +KURL HTMLScriptElement::src() const { - return document()->completeURL(getAttribute(srcAttr)); + return document()->completeURL(sourceAttributeValue()); } void HTMLScriptElement::setSrc(const String &value) @@ -325,7 +168,7 @@ void HTMLScriptElement::setSrc(const String &value) String HTMLScriptElement::type() const { - return getAttribute(typeAttr); + return typeAttributeValue(); } void HTMLScriptElement::setType(const String &value) @@ -333,4 +176,52 @@ void HTMLScriptElement::setType(const String &value) setAttribute(typeAttr, value); } +String HTMLScriptElement::scriptCharset() const +{ + return m_data.scriptCharset(); +} + +String HTMLScriptElement::scriptContent() const +{ + return m_data.scriptContent(); +} + +void HTMLScriptElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + urls.append(src().string()); +} + +String HTMLScriptElement::sourceAttributeValue() const +{ + return getAttribute(srcAttr).string(); +} + +String HTMLScriptElement::charsetAttributeValue() const +{ + return getAttribute(charsetAttr).string(); +} + +String HTMLScriptElement::typeAttributeValue() const +{ + return getAttribute(typeAttr).string(); +} + +String HTMLScriptElement::languageAttributeValue() const +{ + return getAttribute(languageAttr).string(); +} + +void HTMLScriptElement::dispatchLoadEvent() +{ + ASSERT(!m_data.haveFiredLoadEvent()); + m_data.setHaveFiredLoadEvent(true); + + dispatchEventForType(eventNames().loadEvent, false, false); +} + +void HTMLScriptElement::dispatchErrorEvent() +{ + dispatchEventForType(eventNames().errorEvent, true, false); +} + } diff --git a/WebCore/html/HTMLScriptElement.h b/WebCore/html/HTMLScriptElement.h index 1bf7d7e..aa5b7d9 100644 --- a/WebCore/html/HTMLScriptElement.h +++ b/WebCore/html/HTMLScriptElement.h @@ -1,7 +1,8 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,18 +24,21 @@ #ifndef HTMLScriptElement_h #define HTMLScriptElement_h -#include "CachedResourceClient.h" +#include "ScriptElement.h" #include "HTMLElement.h" namespace WebCore { -class CachedScript; - -class HTMLScriptElement : public HTMLElement, public CachedResourceClient { +class HTMLScriptElement : public HTMLElement + , public ScriptElement { public: HTMLScriptElement(Document*); ~HTMLScriptElement(); + void setCreatedByParser(bool); + bool shouldExecuteAsJavaScript() const; + virtual String scriptContent() const; + virtual HTMLTagStatus endTagRequirement() const { return TagStatusRequired; } virtual int tagPriority() const { return 1; } virtual bool checkDTD(const Node* newChild) { return newChild->isTextNode(); } @@ -42,18 +46,11 @@ public: virtual void parseMappedAttribute(MappedAttribute*); virtual void insertedIntoDocument(); virtual void removedFromDocument(); - virtual void notifyFinished(CachedResource*); - - virtual void childrenChanged(bool changedByParser = false); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); virtual bool isURLAttribute(Attribute*) const; - - void setCreatedByParser(bool createdByParser) { m_createdByParser = createdByParser; } virtual void finishParsingChildren(); - bool shouldExecuteAsJavaScript(); - void evaluateScript(const String& url, const String& script); - String text() const; void setText(const String&); @@ -69,16 +66,27 @@ public: bool defer() const; void setDefer(bool); - String src() const; + KURL src() const; void setSrc(const String&); String type() const; void setType(const String&); + virtual String scriptCharset() const; + + virtual void getSubresourceAttributeStrings(Vector<String>&) const; + +protected: + virtual String sourceAttributeValue() const; + virtual String charsetAttributeValue() const; + virtual String typeAttributeValue() const; + virtual String languageAttributeValue() const; + + virtual void dispatchLoadEvent(); + virtual void dispatchErrorEvent(); + private: - CachedScript* m_cachedScript; - bool m_createdByParser; - bool m_evaluated; + ScriptElementData m_data; }; } //namespace diff --git a/WebCore/html/HTMLSelectElement.cpp b/WebCore/html/HTMLSelectElement.cpp index 115e473..44e7fe4 100644 --- a/WebCore/html/HTMLSelectElement.cpp +++ b/WebCore/html/HTMLSelectElement.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "HTMLSelectElement.h" +#include "AXObjectCache.h" #include "CSSPropertyNames.h" #include "CSSStyleSelector.h" #include "CharacterNames.h" @@ -57,7 +58,6 @@ using namespace Unicode; namespace WebCore { -using namespace EventNames; using namespace HTMLNames; static const DOMTimeStamp typeAheadTimeout = 1000; @@ -301,17 +301,17 @@ void HTMLSelectElement::restoreState(const String& state) setChanged(); } -bool HTMLSelectElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec) +bool HTMLSelectElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach) { - bool result = HTMLFormControlElementWithState::insertBefore(newChild, refChild, ec); + bool result = HTMLFormControlElementWithState::insertBefore(newChild, refChild, ec, shouldLazyAttach); if (result) setRecalcListItems(); return result; } -bool HTMLSelectElement::replaceChild(PassRefPtr<Node> newChild, Node *oldChild, ExceptionCode& ec) +bool HTMLSelectElement::replaceChild(PassRefPtr<Node> newChild, Node *oldChild, ExceptionCode& ec, bool shouldLazyAttach) { - bool result = HTMLFormControlElementWithState::replaceChild(newChild, oldChild, ec); + bool result = HTMLFormControlElementWithState::replaceChild(newChild, oldChild, ec, shouldLazyAttach); if (result) setRecalcListItems(); return result; @@ -325,9 +325,9 @@ bool HTMLSelectElement::removeChild(Node* oldChild, ExceptionCode& ec) return result; } -bool HTMLSelectElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec) +bool HTMLSelectElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach) { - bool result = HTMLFormControlElementWithState::appendChild(newChild, ec); + bool result = HTMLFormControlElementWithState::appendChild(newChild, ec, shouldLazyAttach); if (result) setRecalcListItems(); return result; @@ -373,11 +373,11 @@ void HTMLSelectElement::parseMappedAttribute(MappedAttribute *attr) // Don't map 'align' attribute. This matches what Firefox, Opera and IE do. // See http://bugs.webkit.org/show_bug.cgi?id=12072 } else if (attr->name() == onfocusAttr) { - setHTMLEventListener(focusEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().focusEvent, attr); } else if (attr->name() == onblurAttr) { - setHTMLEventListener(blurEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().blurEvent, attr); } else if (attr->name() == onchangeAttr) { - setHTMLEventListener(changeEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().changeEvent, attr); } else HTMLFormControlElementWithState::parseMappedAttribute(attr); } @@ -491,7 +491,7 @@ int HTMLSelectElement::listToOptionIndex(int listIndex) const PassRefPtr<HTMLOptionsCollection> HTMLSelectElement::options() { - return new HTMLOptionsCollection(this); + return HTMLOptionsCollection::create(this); } void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const @@ -529,10 +529,13 @@ void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const m_recalcListItems = false; } -void HTMLSelectElement::childrenChanged(bool changedByParser) +void HTMLSelectElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { setRecalcListItems(); - HTMLFormControlElementWithState::childrenChanged(changedByParser); + HTMLFormControlElementWithState::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); + + if (AXObjectCache::accessibilityEnabled() && renderer()) + renderer()->document()->axObjectCache()->childrenChanged(renderer()); } void HTMLSelectElement::setRecalcListItems() @@ -605,7 +608,7 @@ void HTMLSelectElement::defaultEventHandler(Event* evt) if (evt->defaultHandled()) return; - if (evt->type() == keypressEvent && evt->isKeyboardEvent()) { + if (evt->type() == eventNames().keypressEvent && evt->isKeyboardEvent()) { KeyboardEvent* keyboardEvent = static_cast<KeyboardEvent*>(evt); if (!keyboardEvent->ctrlKey() && !keyboardEvent->altKey() && !keyboardEvent->metaKey() && @@ -623,7 +626,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* evt) { RenderMenuList* menuList = static_cast<RenderMenuList*>(renderer()); - if (evt->type() == keydownEvent) { + if (evt->type() == eventNames().keydownEvent) { if (!renderer() || !evt->isKeyboardEvent()) return; String keyIdentifier = static_cast<KeyboardEvent*>(evt)->keyIdentifier(); @@ -648,7 +651,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* evt) int size = listItems().size(); for (listIndex += 1; listIndex >= 0 && listIndex < size && (listItems()[listIndex]->disabled() || !listItems()[listIndex]->hasTagName(optionTag)); - ++listIndex); + ++listIndex) { } if (listIndex >= 0 && listIndex < size) setSelectedIndex(listToOptionIndex(listIndex)); @@ -657,7 +660,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* evt) int size = listItems().size(); for (listIndex -= 1; listIndex >= 0 && listIndex < size && (listItems()[listIndex]->disabled() || !listItems()[listIndex]->hasTagName(optionTag)); - --listIndex); + --listIndex) { } if (listIndex >= 0 && listIndex < size) setSelectedIndex(listToOptionIndex(listIndex)); @@ -670,7 +673,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* evt) // Use key press event here since sending simulated mouse events // on key down blocks the proper sending of the key press event. - if (evt->type() == keypressEvent) { + if (evt->type() == eventNames().keypressEvent) { if (!renderer() || !evt->isKeyboardEvent()) return; int keyCode = static_cast<KeyboardEvent*>(evt)->keyCode(); @@ -702,7 +705,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* evt) evt->setDefaultHandled(); } - if (evt->type() == mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) { + if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) { focus(); if (menuList->popupIsVisible()) menuList->hidePopup(); @@ -718,7 +721,7 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* evt) void HTMLSelectElement::listBoxDefaultEventHandler(Event* evt) { - if (evt->type() == mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) { + if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) { focus(); MouseEvent* mEvt = static_cast<MouseEvent*>(evt); @@ -778,10 +781,10 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* evt) evt->setDefaultHandled(); } - } else if (evt->type() == mouseupEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton && document()->frame()->eventHandler()->autoscrollRenderer() != renderer()) + } else if (evt->type() == eventNames().mouseupEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton && document()->frame()->eventHandler()->autoscrollRenderer() != renderer()) // This makes sure we fire onChange for a single click. For drag selection, onChange will fire when the autoscroll timer stops. listBoxOnChange(); - else if (evt->type() == keydownEvent) { + else if (evt->type() == eventNames().keydownEvent) { if (!evt->isKeyboardEvent()) return; String keyIdentifier = static_cast<KeyboardEvent*>(evt)->keyIdentifier(); @@ -822,7 +825,7 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* evt) listBoxOnChange(); evt->setDefaultHandled(); } - } else if (evt->type() == keypressEvent) { + } else if (evt->type() == eventNames().keypressEvent) { if (!evt->isKeyboardEvent()) return; int keyCode = static_cast<KeyboardEvent*>(evt)->keyCode(); @@ -981,13 +984,17 @@ void HTMLSelectElement::typeAheadFind(KeyboardEvent* event) if (itemCount < 1) return; - int index = (optionToListIndex(selectedIndex()) + searchStartOffset) % itemCount; + int selected = selectedIndex(); + int index = (optionToListIndex(selected >= 0 ? selected : 0) + searchStartOffset) % itemCount; + ASSERT(index >= 0); for (int i = 0; i < itemCount; i++, index = (index + 1) % itemCount) { if (!items[index]->hasTagName(optionTag) || items[index]->disabled()) continue; if (stripLeadingWhiteSpace(static_cast<HTMLOptionElement*>(items[index])->optionText()).startsWith(prefix, false)) { setSelectedIndex(listToOptionIndex(index)); + if(!usesMenuList()) + listBoxOnChange(); setChanged(); return; } @@ -1024,6 +1031,26 @@ void HTMLSelectElement::accessKeyAction(bool sendToAnyElement) dispatchSimulatedClick(0, sendToAnyElement); } +void HTMLSelectElement::accessKeySetSelectedIndex(int index) +{ + // first bring into focus the list box + if (!focused()) + accessKeyAction(false); + + // if this index is already selected, unselect. otherwise update the selected index + Node* listNode = item(index); + if (listNode && listNode->hasTagName(optionTag)) { + HTMLOptionElement* listElement = static_cast<HTMLOptionElement*>(listNode); + if (listElement->selected()) + listElement->setSelectedState(false); + else + setSelectedIndex(index, false, true); + } + + listBoxOnChange(); + scrollToSelection(); +} + void HTMLSelectElement::setMultiple(bool multiple) { setAttribute(multipleAttr, multiple ? "" : 0); diff --git a/WebCore/html/HTMLSelectElement.h b/WebCore/html/HTMLSelectElement.h index ea8e990..0b438ab 100644 --- a/WebCore/html/HTMLSelectElement.h +++ b/WebCore/html/HTMLSelectElement.h @@ -26,7 +26,7 @@ #include "Event.h" #include "HTMLCollection.h" -#include "HTMLGenericFormElement.h" +#include "HTMLFormControlElement.h" #include <wtf/Vector.h> namespace WebCore { @@ -82,12 +82,12 @@ public: virtual bool saveState(String& value) const; virtual void restoreState(const String&); - virtual bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode&); - virtual bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode&); + 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&); + virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&, bool shouldLazyAttach = false); virtual bool removeChildren(); - virtual void childrenChanged(bool changedByParser = false); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); virtual void parseMappedAttribute(MappedAttribute*); @@ -113,6 +113,7 @@ public: virtual void defaultEventHandler(Event*); virtual void accessKeyAction(bool sendToAnyElement); + void accessKeySetSelectedIndex(int); void setMultiple(bool); diff --git a/WebCore/html/HTMLSelectElement.idl b/WebCore/html/HTMLSelectElement.idl index e154ace..d3e85a8 100644 --- a/WebCore/html/HTMLSelectElement.idl +++ b/WebCore/html/HTMLSelectElement.idl @@ -41,15 +41,16 @@ module html { #endif readonly attribute HTMLFormElement form; + readonly attribute boolean willValidate; // Modified in DOM Level 2: readonly attribute HTMLOptionsCollection options; attribute boolean disabled; + attribute boolean autofocus; attribute boolean multiple; attribute [ConvertNullToNullString] DOMString name; attribute long size; - attribute long tabIndex; [OldStyleObjC] void add(in HTMLElement element, in HTMLElement before) @@ -61,8 +62,6 @@ module html { #else void remove(in long index); #endif - void blur(); - void focus(); // These methods are not in DOM Level 2 IDL, but are mentioned in the standard: // "The contained options can be directly accessed through the select element as a collection." diff --git a/WebCore/html/HTMLSourceElement.cpp b/WebCore/html/HTMLSourceElement.cpp index 66f7305..86af4e4 100644 --- a/WebCore/html/HTMLSourceElement.cpp +++ b/WebCore/html/HTMLSourceElement.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,6 +30,7 @@ #include "HTMLDocument.h" #include "HTMLMediaElement.h" +#include "HTMLNames.h" using namespace std; @@ -56,7 +57,7 @@ void HTMLSourceElement::insertedIntoDocument() } } -String HTMLSourceElement::src() const +KURL HTMLSourceElement::src() const { return document()->completeURL(getAttribute(srcAttr)); } diff --git a/WebCore/html/HTMLSourceElement.h b/WebCore/html/HTMLSourceElement.h index e47411a..8187877 100644 --- a/WebCore/html/HTMLSourceElement.h +++ b/WebCore/html/HTMLSourceElement.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,15 +29,12 @@ #if ENABLE(VIDEO) #include "HTMLElement.h" -#include "HTMLNames.h" #include <limits> namespace WebCore { -using namespace HTMLNames; - -class MediaError; - +class KURL; + class HTMLSourceElement : public HTMLElement { public: HTMLSourceElement(Document*); @@ -48,7 +45,7 @@ public: virtual void insertedIntoDocument(); - String src() const; + KURL src() const; String media() const; String type() const; void setSrc(const String&); diff --git a/WebCore/html/HTMLStyleElement.cpp b/WebCore/html/HTMLStyleElement.cpp index 67eb1cc..dd00db6 100644 --- a/WebCore/html/HTMLStyleElement.cpp +++ b/WebCore/html/HTMLStyleElement.cpp @@ -43,7 +43,7 @@ HTMLStyleElement::HTMLStyleElement(Document* doc) void HTMLStyleElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == mediaAttr) - m_media = attr->value().domString().lower(); + m_media = attr->value().string().lower(); else if (attr->name() == titleAttr && m_sheet) m_sheet->setTitle(attr->value()); else @@ -52,6 +52,7 @@ void HTMLStyleElement::parseMappedAttribute(MappedAttribute *attr) void HTMLStyleElement::finishParsingChildren() { + StyleElement::process(this); StyleElement::sheet(this); m_createdByParser = false; HTMLElement::finishParsingChildren(); @@ -61,6 +62,7 @@ void HTMLStyleElement::insertedIntoDocument() { HTMLElement::insertedIntoDocument(); + document()->addStyleSheetCandidateNode(this, m_createdByParser); if (!m_createdByParser) StyleElement::insertedIntoDocument(document(), this); } @@ -68,13 +70,16 @@ void HTMLStyleElement::insertedIntoDocument() void HTMLStyleElement::removedFromDocument() { HTMLElement::removedFromDocument(); + if (document()->renderer()) + document()->removeStyleSheetCandidateNode(this); StyleElement::removedFromDocument(document()); } -void HTMLStyleElement::childrenChanged(bool changedByParser) +void HTMLStyleElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { - StyleElement::process(this); - HTMLElement::childrenChanged(changedByParser); + if (!changedByParser) + StyleElement::process(this); + HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); } StyleSheet* HTMLStyleElement::sheet() @@ -130,4 +135,16 @@ void HTMLStyleElement::setType(const AtomicString &value) setAttribute(typeAttr, value); } +void HTMLStyleElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + HashSet<String> styleURLs; + StyleSheet* styleSheet = const_cast<HTMLStyleElement*>(this)->sheet(); + if (styleSheet) + styleSheet->addSubresourceURLStrings(styleURLs, ownerDocument()->baseURL()); + + HashSet<String>::iterator end = styleURLs.end(); + for (HashSet<String>::iterator i = styleURLs.begin(); i != end; ++i) + urls.append(*i); +} + } diff --git a/WebCore/html/HTMLStyleElement.h b/WebCore/html/HTMLStyleElement.h index 05909d6..a85916f 100644 --- a/WebCore/html/HTMLStyleElement.h +++ b/WebCore/html/HTMLStyleElement.h @@ -43,7 +43,7 @@ public: virtual void parseMappedAttribute(MappedAttribute*); virtual void insertedIntoDocument(); virtual void removedFromDocument(); - virtual void childrenChanged(bool changedByParser = false); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); void setCreatedByParser(bool createdByParser) { m_createdByParser = createdByParser; } virtual void finishParsingChildren(); @@ -64,6 +64,8 @@ public: virtual void setLoading(bool loading) { m_loading = loading; } + virtual void getSubresourceAttributeStrings(Vector<String>&) const; + protected: String m_media; bool m_loading; diff --git a/WebCore/html/HTMLTableCaptionElement.cpp b/WebCore/html/HTMLTableCaptionElement.cpp index 7bc190e..b6c9c73 100644 --- a/WebCore/html/HTMLTableCaptionElement.cpp +++ b/WebCore/html/HTMLTableCaptionElement.cpp @@ -52,7 +52,7 @@ void HTMLTableCaptionElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == alignAttr) { if (!attr->value().isEmpty()) - addCSSProperty(attr, CSS_PROP_CAPTION_SIDE, attr->value()); + addCSSProperty(attr, CSSPropertyCaptionSide, attr->value()); } else HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLTableCellElement.cpp b/WebCore/html/HTMLTableCellElement.cpp index 29ec6c4..3395d23 100644 --- a/WebCore/html/HTMLTableCellElement.cpp +++ b/WebCore/html/HTMLTableCellElement.cpp @@ -106,18 +106,18 @@ void HTMLTableCellElement::parseMappedAttribute(MappedAttribute *attr) if (!(document()->frame()) || document()->frame()->settings()->layoutAlgorithm() != Settings::kLayoutSSR) #endif if (!attr->isNull()) - addCSSProperty(attr, CSS_PROP_WHITE_SPACE, CSS_VAL__WEBKIT_NOWRAP); + addCSSProperty(attr, CSSPropertyWhiteSpace, CSSValueWebkitNowrap); } else if (attr->name() == widthAttr) { if (!attr->value().isEmpty()) { int widthInt = attr->value().toInt(); if (widthInt > 0) // width="0" is ignored for compatibility with WinIE. - addCSSLength(attr, CSS_PROP_WIDTH, attr->value()); + addCSSLength(attr, CSSPropertyWidth, attr->value()); } } else if (attr->name() == heightAttr) { if (!attr->value().isEmpty()) { int heightInt = attr->value().toInt(); if (heightInt > 0) // height="0" is ignored for compatibility with WinIE. - addCSSLength(attr, CSS_PROP_HEIGHT, attr->value()); + addCSSLength(attr, CSSPropertyHeight, attr->value()); } } else HTMLTablePartElement::parseMappedAttribute(attr); @@ -269,4 +269,9 @@ void HTMLTableCellElement::setWidth(const String &value) setAttribute(widthAttr, value); } +void HTMLTableCellElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + urls.append(getAttribute(HTMLNames::backgroundAttr).string()); +} + } diff --git a/WebCore/html/HTMLTableCellElement.h b/WebCore/html/HTMLTableCellElement.h index 1099857..6ac4b29 100644 --- a/WebCore/html/HTMLTableCellElement.h +++ b/WebCore/html/HTMLTableCellElement.h @@ -102,6 +102,8 @@ public: String width() const; void setWidth(const String&); + virtual void getSubresourceAttributeStrings(Vector<String>&) const; + protected: int _row; int _col; diff --git a/WebCore/html/HTMLTableColElement.cpp b/WebCore/html/HTMLTableColElement.cpp index 6192ca2..11f6df6 100644 --- a/WebCore/html/HTMLTableColElement.cpp +++ b/WebCore/html/HTMLTableColElement.cpp @@ -80,7 +80,7 @@ void HTMLTableColElement::parseMappedAttribute(MappedAttribute *attr) static_cast<RenderTableCol*>(renderer())->updateFromElement(); } else if (attr->name() == widthAttr) { if (!attr->value().isEmpty()) - addCSSLength(attr, CSS_PROP_WIDTH, attr->value()); + addCSSLength(attr, CSSPropertyWidth, attr->value()); } else HTMLTablePartElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLTableElement.cpp b/WebCore/html/HTMLTableElement.cpp index 92f2b54..ed5c577 100644 --- a/WebCore/html/HTMLTableElement.cpp +++ b/WebCore/html/HTMLTableElement.cpp @@ -320,13 +320,13 @@ void HTMLTableElement::parseMappedAttribute(MappedAttribute* attr) unsigned short oldPadding = m_padding; if (attr->name() == widthAttr) - addCSSLength(attr, CSS_PROP_WIDTH, attr->value()); + addCSSLength(attr, CSSPropertyWidth, attr->value()); else if (attr->name() == heightAttr) - addCSSLength(attr, CSS_PROP_HEIGHT, attr->value()); + addCSSLength(attr, CSSPropertyHeight, attr->value()); else if (attr->name() == borderAttr) { m_borderAttr = true; if (attr->decl()) { - RefPtr<CSSValue> val = attr->decl()->getPropertyCSSValue(CSS_PROP_BORDER_LEFT_WIDTH); + RefPtr<CSSValue> val = attr->decl()->getPropertyCSSValue(CSSPropertyBorderLeftWidth); if (val && val->isPrimitiveValue()) { CSSPrimitiveValue* primVal = static_cast<CSSPrimitiveValue*>(val.get()); m_borderAttr = primVal->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER); @@ -338,20 +338,20 @@ void HTMLTableElement::parseMappedAttribute(MappedAttribute* attr) else border = attr->value().toInt(); m_borderAttr = border; - addCSSLength(attr, CSS_PROP_BORDER_WIDTH, String::number(border)); + addCSSLength(attr, CSSPropertyBorderWidth, String::number(border)); } } else if (attr->name() == bgcolorAttr) - addCSSColor(attr, CSS_PROP_BACKGROUND_COLOR, attr->value()); + addCSSColor(attr, CSSPropertyBackgroundColor, attr->value()); else if (attr->name() == bordercolorAttr) { m_borderColorAttr = attr->decl(); if (!attr->decl() && !attr->isEmpty()) { - addCSSColor(attr, CSS_PROP_BORDER_COLOR, attr->value()); + addCSSColor(attr, CSSPropertyBorderColor, attr->value()); m_borderColorAttr = true; } } else if (attr->name() == backgroundAttr) { String url = parseURL(attr->value()); if (!url.isEmpty()) - addCSSImageProperty(attr, CSS_PROP_BACKGROUND_IMAGE, document()->completeURL(url)); + addCSSImageProperty(attr, CSSPropertyBackgroundImage, document()->completeURL(url).string()); } else if (attr->name() == frameAttr) { // Cache the value of "frame" so that the table can examine it later. m_frameAttr = false; @@ -392,14 +392,14 @@ void HTMLTableElement::parseMappedAttribute(MappedAttribute* attr) // Now map in the border styles of solid and hidden respectively. if (m_frameAttr) { - addCSSProperty(attr, CSS_PROP_BORDER_TOP_WIDTH, CSS_VAL_THIN); - addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_VAL_THIN); - addCSSProperty(attr, CSS_PROP_BORDER_LEFT_WIDTH, CSS_VAL_THIN); - addCSSProperty(attr, CSS_PROP_BORDER_RIGHT_WIDTH, CSS_VAL_THIN); - addCSSProperty(attr, CSS_PROP_BORDER_TOP_STYLE, borders[cTop] ? CSS_VAL_SOLID : CSS_VAL_HIDDEN); - addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_STYLE, borders[cBottom] ? CSS_VAL_SOLID : CSS_VAL_HIDDEN); - addCSSProperty(attr, CSS_PROP_BORDER_LEFT_STYLE, borders[cLeft] ? CSS_VAL_SOLID : CSS_VAL_HIDDEN); - addCSSProperty(attr, CSS_PROP_BORDER_RIGHT_STYLE, borders[cRight] ? CSS_VAL_SOLID : CSS_VAL_HIDDEN); + addCSSProperty(attr, CSSPropertyBorderTopWidth, CSSValueThin); + addCSSProperty(attr, CSSPropertyBorderBottomWidth, CSSValueThin); + addCSSProperty(attr, CSSPropertyBorderLeftWidth, CSSValueThin); + addCSSProperty(attr, CSSPropertyBorderRightWidth, CSSValueThin); + addCSSProperty(attr, CSSPropertyBorderTopStyle, borders[cTop] ? CSSValueSolid : CSSValueHidden); + addCSSProperty(attr, CSSPropertyBorderBottomStyle, borders[cBottom] ? CSSValueSolid : CSSValueHidden); + addCSSProperty(attr, CSSPropertyBorderLeftStyle, borders[cLeft] ? CSSValueSolid : CSSValueHidden); + addCSSProperty(attr, CSSPropertyBorderRightStyle, borders[cRight] ? CSSValueSolid : CSSValueHidden); } } else if (attr->name() == rulesAttr) { m_rulesAttr = UnsetRules; @@ -416,10 +416,10 @@ void HTMLTableElement::parseMappedAttribute(MappedAttribute* attr) // The presence of a valid rules attribute causes border collapsing to be enabled. if (m_rulesAttr != UnsetRules) - addCSSProperty(attr, CSS_PROP_BORDER_COLLAPSE, CSS_VAL_COLLAPSE); + addCSSProperty(attr, CSSPropertyBorderCollapse, CSSValueCollapse); } else if (attr->name() == cellspacingAttr) { if (!attr->value().isEmpty()) - addCSSLength(attr, CSS_PROP_BORDER_SPACING, attr->value()); + addCSSLength(attr, CSSPropertyBorderSpacing, attr->value()); } else if (attr->name() == cellpaddingAttr) { if (!attr->value().isEmpty()) m_padding = max(0, attr->value().toInt()); @@ -428,22 +428,22 @@ void HTMLTableElement::parseMappedAttribute(MappedAttribute* attr) } else if (attr->name() == colsAttr) { // ### } else if (attr->name() == vspaceAttr) { - addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value()); + addCSSLength(attr, CSSPropertyMarginTop, attr->value()); + addCSSLength(attr, CSSPropertyMarginBottom, attr->value()); } else if (attr->name() == hspaceAttr) { - addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value()); - addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value()); + addCSSLength(attr, CSSPropertyMarginLeft, attr->value()); + addCSSLength(attr, CSSPropertyMarginRight, attr->value()); } else if (attr->name() == alignAttr) { if (!attr->value().isEmpty()) { if (equalIgnoringCase(attr->value(), "center")) { - addCSSProperty(attr, CSS_PROP_MARGIN_LEFT, CSS_VAL_AUTO); - addCSSProperty(attr, CSS_PROP_MARGIN_RIGHT, CSS_VAL_AUTO); + addCSSProperty(attr, CSSPropertyMarginLeft, CSSValueAuto); + addCSSProperty(attr, CSSPropertyMarginRight, CSSValueAuto); } else - addCSSProperty(attr, CSS_PROP_FLOAT, attr->value()); + addCSSProperty(attr, CSSPropertyFloat, attr->value()); } } else if (attr->name() == valignAttr) { if (!attr->value().isEmpty()) - addCSSProperty(attr, CSS_PROP_VERTICAL_ALIGN, attr->value()); + addCSSProperty(attr, CSSPropertyVerticalAlign, attr->value()); } else HTMLElement::parseMappedAttribute(attr); @@ -462,27 +462,25 @@ void HTMLTableElement::additionalAttributeStyleDecls(Vector<CSSMutableStyleDecla { if ((!m_borderAttr && !m_borderColorAttr) || m_frameAttr) return; - - MappedAttribute attr(tableborderAttr, m_borderColorAttr ? "solid" : "outset"); - CSSMappedAttributeDeclaration* decl = getMappedAttributeDecl(ePersistent, &attr); + + AtomicString borderValue = m_borderColorAttr ? "solid" : "outset"; + CSSMappedAttributeDeclaration* decl = getMappedAttributeDecl(ePersistent, tableborderAttr, borderValue); if (!decl) { - decl = new CSSMappedAttributeDeclaration(0); + decl = CSSMappedAttributeDeclaration::create().releaseRef(); // This single ref pins us in the table until the document dies. decl->setParent(document()->elementSheet()); decl->setNode(this); decl->setStrictParsing(false); // Mapped attributes are just always quirky. - decl->ref(); // This single ref pins us in the table until the document dies. - - int v = m_borderColorAttr ? CSS_VAL_SOLID : CSS_VAL_OUTSET; - decl->setProperty(CSS_PROP_BORDER_TOP_STYLE, v, false); - decl->setProperty(CSS_PROP_BORDER_BOTTOM_STYLE, v, false); - decl->setProperty(CSS_PROP_BORDER_LEFT_STYLE, v, false); - decl->setProperty(CSS_PROP_BORDER_RIGHT_STYLE, v, false); + int v = m_borderColorAttr ? CSSValueSolid : CSSValueOutset; + decl->setProperty(CSSPropertyBorderTopStyle, v, false); + decl->setProperty(CSSPropertyBorderBottomStyle, v, false); + decl->setProperty(CSSPropertyBorderLeftStyle, v, false); + decl->setProperty(CSSPropertyBorderRightStyle, v, false); - setMappedAttributeDecl(ePersistent, &attr, decl); + setMappedAttributeDecl(ePersistent, tableborderAttr, borderValue, decl); decl->setParent(0); decl->setNode(0); - decl->setMappedState(ePersistent, attr.name(), attr.value()); + decl->setMappedState(ePersistent, tableborderAttr, borderValue); } @@ -522,58 +520,55 @@ void HTMLTableElement::addSharedCellBordersDecl(Vector<CSSMutableStyleDeclaratio { CellBorders borders = cellBorders(); - static AtomicString cellBorderNames[] = { "none", "solid", "inset", "solid-cols", "solid-rows" }; - MappedAttribute attr(cellborderAttr, cellBorderNames[borders]); - - CSSMappedAttributeDeclaration* decl = getMappedAttributeDecl(ePersistent, &attr); + static const AtomicString cellBorderNames[] = { "none", "solid", "inset", "solid-cols", "solid-rows" }; + const AtomicString& cellborderValue = cellBorderNames[borders]; + CSSMappedAttributeDeclaration* decl = getMappedAttributeDecl(ePersistent, cellborderAttr, cellborderValue); if (!decl) { - decl = new CSSMappedAttributeDeclaration(0); + decl = CSSMappedAttributeDeclaration::create().releaseRef(); // This single ref pins us in the table until the document dies. decl->setParent(document()->elementSheet()); decl->setNode(this); decl->setStrictParsing(false); // Mapped attributes are just always quirky. - decl->ref(); // This single ref pins us in the table until the document dies. - switch (borders) { case SolidBordersColsOnly: - decl->setProperty(CSS_PROP_BORDER_LEFT_WIDTH, CSS_VAL_THIN, false); - decl->setProperty(CSS_PROP_BORDER_RIGHT_WIDTH, CSS_VAL_THIN, false); - decl->setProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID, false); - decl->setProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID, false); - decl->setProperty(CSS_PROP_BORDER_COLOR, "inherit", false); + decl->setProperty(CSSPropertyBorderLeftWidth, CSSValueThin, false); + decl->setProperty(CSSPropertyBorderRightWidth, CSSValueThin, false); + decl->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid, false); + decl->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid, false); + decl->setProperty(CSSPropertyBorderColor, "inherit", false); break; case SolidBordersRowsOnly: - decl->setProperty(CSS_PROP_BORDER_TOP_WIDTH, CSS_VAL_THIN, false); - decl->setProperty(CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_VAL_THIN, false); - decl->setProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID, false); - decl->setProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID, false); - decl->setProperty(CSS_PROP_BORDER_COLOR, "inherit", false); + decl->setProperty(CSSPropertyBorderTopWidth, CSSValueThin, false); + decl->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin, false); + decl->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid, false); + decl->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid, false); + decl->setProperty(CSSPropertyBorderColor, "inherit", false); break; case SolidBorders: - decl->setProperty(CSS_PROP_BORDER_WIDTH, "1px", false); - decl->setProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID, false); - decl->setProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID, false); - decl->setProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID, false); - decl->setProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID, false); - decl->setProperty(CSS_PROP_BORDER_COLOR, "inherit", false); + decl->setProperty(CSSPropertyBorderWidth, "1px", false); + decl->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid, false); + decl->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid, false); + decl->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid, false); + decl->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid, false); + decl->setProperty(CSSPropertyBorderColor, "inherit", false); break; case InsetBorders: - decl->setProperty(CSS_PROP_BORDER_WIDTH, "1px", false); - decl->setProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_INSET, false); - decl->setProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_INSET, false); - decl->setProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_INSET, false); - decl->setProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_INSET, false); - decl->setProperty(CSS_PROP_BORDER_COLOR, "inherit", false); + decl->setProperty(CSSPropertyBorderWidth, "1px", false); + decl->setProperty(CSSPropertyBorderTopStyle, CSSValueInset, false); + decl->setProperty(CSSPropertyBorderBottomStyle, CSSValueInset, false); + decl->setProperty(CSSPropertyBorderLeftStyle, CSSValueInset, false); + decl->setProperty(CSSPropertyBorderRightStyle, CSSValueInset, false); + decl->setProperty(CSSPropertyBorderColor, "inherit", false); break; case NoBorders: - decl->setProperty(CSS_PROP_BORDER_WIDTH, "0", false); + decl->setProperty(CSSPropertyBorderWidth, "0", false); break; } - setMappedAttributeDecl(ePersistent, &attr, decl); + setMappedAttributeDecl(ePersistent, cellborderAttr, cellBorderNames[borders], decl); decl->setParent(0); decl->setNode(0); - decl->setMappedState(ePersistent, attr.name(), attr.value()); + decl->setMappedState(ePersistent, cellborderAttr, cellborderValue); } results.append(decl); @@ -585,61 +580,57 @@ void HTMLTableElement::addSharedCellPaddingDecl(Vector<CSSMutableStyleDeclaratio return; if (!m_paddingDecl) { - String numericStr = String::number(m_padding); - MappedAttribute attr(cellpaddingAttr, numericStr); - m_paddingDecl = getMappedAttributeDecl(eUniversal, &attr); + String paddingValue = String::number(m_padding); + m_paddingDecl = getMappedAttributeDecl(eUniversal, cellpaddingAttr, paddingValue); if (!m_paddingDecl) { - m_paddingDecl = new CSSMappedAttributeDeclaration(0); + m_paddingDecl = CSSMappedAttributeDeclaration::create(); m_paddingDecl->setParent(document()->elementSheet()); m_paddingDecl->setNode(this); m_paddingDecl->setStrictParsing(false); // Mapped attributes are just always quirky. - m_paddingDecl->setProperty(CSS_PROP_PADDING_TOP, numericStr, false); - m_paddingDecl->setProperty(CSS_PROP_PADDING_RIGHT, numericStr, false); - m_paddingDecl->setProperty(CSS_PROP_PADDING_BOTTOM, numericStr, false); - m_paddingDecl->setProperty(CSS_PROP_PADDING_LEFT, numericStr, false); + m_paddingDecl->setProperty(CSSPropertyPaddingTop, paddingValue, false); + m_paddingDecl->setProperty(CSSPropertyPaddingRight, paddingValue, false); + m_paddingDecl->setProperty(CSSPropertyPaddingBottom, paddingValue, false); + m_paddingDecl->setProperty(CSSPropertyPaddingLeft, paddingValue, false); } - setMappedAttributeDecl(eUniversal, &attr, m_paddingDecl.get()); + setMappedAttributeDecl(eUniversal, cellpaddingAttr, paddingValue, m_paddingDecl.get()); m_paddingDecl->setParent(0); m_paddingDecl->setNode(0); - m_paddingDecl->setMappedState(eUniversal, attr.name(), attr.value()); + m_paddingDecl->setMappedState(eUniversal, cellpaddingAttr, paddingValue); } results.append(m_paddingDecl.get()); } void HTMLTableElement::addSharedGroupDecls(bool rows, Vector<CSSMutableStyleDeclaration*>& results) - { if (m_rulesAttr != GroupsRules) return; - MappedAttribute attr(rulesAttr, rows ? "rowgroups" : "colgroups"); - CSSMappedAttributeDeclaration* decl = getMappedAttributeDecl(ePersistent, &attr); + AtomicString rulesValue = rows ? "rowgroups" : "colgroups"; + CSSMappedAttributeDeclaration* decl = getMappedAttributeDecl(ePersistent, rulesAttr, rulesValue); if (!decl) { - decl = new CSSMappedAttributeDeclaration(0); + decl = CSSMappedAttributeDeclaration::create().releaseRef(); // This single ref pins us in the table until the document dies. decl->setParent(document()->elementSheet()); decl->setNode(this); decl->setStrictParsing(false); // Mapped attributes are just always quirky. - decl->ref(); // This single ref pins us in the table until the document dies. - if (rows) { - decl->setProperty(CSS_PROP_BORDER_TOP_WIDTH, CSS_VAL_THIN, false); - decl->setProperty(CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_VAL_THIN, false); - decl->setProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID, false); - decl->setProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID, false); + decl->setProperty(CSSPropertyBorderTopWidth, CSSValueThin, false); + decl->setProperty(CSSPropertyBorderBottomWidth, CSSValueThin, false); + decl->setProperty(CSSPropertyBorderTopStyle, CSSValueSolid, false); + decl->setProperty(CSSPropertyBorderBottomStyle, CSSValueSolid, false); } else { - decl->setProperty(CSS_PROP_BORDER_LEFT_WIDTH, CSS_VAL_THIN, false); - decl->setProperty(CSS_PROP_BORDER_RIGHT_WIDTH, CSS_VAL_THIN, false); - decl->setProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID, false); - decl->setProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID, false); + decl->setProperty(CSSPropertyBorderLeftWidth, CSSValueThin, false); + decl->setProperty(CSSPropertyBorderRightWidth, CSSValueThin, false); + decl->setProperty(CSSPropertyBorderLeftStyle, CSSValueSolid, false); + decl->setProperty(CSSPropertyBorderRightStyle, CSSValueSolid, false); } - setMappedAttributeDecl(ePersistent, &attr, decl); + setMappedAttributeDecl(ePersistent, rulesAttr, rulesValue, decl); decl->setParent(0); decl->setNode(0); - decl->setMappedState(ePersistent, attr.name(), attr.value()); + decl->setMappedState(ePersistent, rulesAttr, rulesValue); } results.append(decl); @@ -647,7 +638,7 @@ void HTMLTableElement::addSharedGroupDecls(bool rows, Vector<CSSMutableStyleDecl void HTMLTableElement::attach() { - ASSERT(!m_attached); + ASSERT(!attached()); HTMLElement::attach(); } @@ -658,12 +649,12 @@ bool HTMLTableElement::isURLAttribute(Attribute *attr) const PassRefPtr<HTMLCollection> HTMLTableElement::rows() { - return new HTMLTableRowsCollection(this); + return HTMLTableRowsCollection::create(this); } PassRefPtr<HTMLCollection> HTMLTableElement::tBodies() { - return new HTMLCollection(this, HTMLCollection::TableTBodies); + return HTMLCollection::create(this, HTMLCollection::TableTBodies); } String HTMLTableElement::align() const @@ -756,4 +747,9 @@ void HTMLTableElement::setWidth(const String &value) setAttribute(widthAttr, value); } +void HTMLTableElement::getSubresourceAttributeStrings(Vector<String>& urls) const +{ + urls.append(getAttribute(HTMLNames::backgroundAttr).string()); +} + } diff --git a/WebCore/html/HTMLTableElement.h b/WebCore/html/HTMLTableElement.h index 1a8df12..aced79e 100644 --- a/WebCore/html/HTMLTableElement.h +++ b/WebCore/html/HTMLTableElement.h @@ -103,6 +103,8 @@ public: void addSharedCellDecls(Vector<CSSMutableStyleDeclaration*>&); void addSharedGroupDecls(bool rows, Vector<CSSMutableStyleDeclaration*>&); + virtual void getSubresourceAttributeStrings(Vector<String>&) const; + private: void addSharedCellBordersDecl(Vector<CSSMutableStyleDeclaration*>&); void addSharedCellPaddingDecl(Vector<CSSMutableStyleDeclaration*>&); diff --git a/WebCore/html/HTMLTablePartElement.cpp b/WebCore/html/HTMLTablePartElement.cpp index 4070de9..6341197 100644 --- a/WebCore/html/HTMLTablePartElement.cpp +++ b/WebCore/html/HTMLTablePartElement.cpp @@ -62,37 +62,37 @@ bool HTMLTablePartElement::mapToEntry(const QualifiedName& attrName, MappedAttri void HTMLTablePartElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == bgcolorAttr) - addCSSColor(attr, CSS_PROP_BACKGROUND_COLOR, attr->value()); + addCSSColor(attr, CSSPropertyBackgroundColor, attr->value()); else if (attr->name() == backgroundAttr) { String url = parseURL(attr->value()); if (!url.isEmpty()) - addCSSImageProperty(attr, CSS_PROP_BACKGROUND_IMAGE, document()->completeURL(url)); + addCSSImageProperty(attr, CSSPropertyBackgroundImage, document()->completeURL(url).string()); } else if (attr->name() == bordercolorAttr) { if (!attr->value().isEmpty()) { - addCSSColor(attr, CSS_PROP_BORDER_COLOR, attr->value()); - addCSSProperty(attr, CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID); - addCSSProperty(attr, CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID); + addCSSColor(attr, CSSPropertyBorderColor, attr->value()); + addCSSProperty(attr, CSSPropertyBorderTopStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderBottomStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderLeftStyle, CSSValueSolid); + addCSSProperty(attr, CSSPropertyBorderRightStyle, CSSValueSolid); } } else if (attr->name() == valignAttr) { if (!attr->value().isEmpty()) - addCSSProperty(attr, CSS_PROP_VERTICAL_ALIGN, attr->value()); + addCSSProperty(attr, CSSPropertyVerticalAlign, attr->value()); } else if (attr->name() == alignAttr) { const AtomicString& v = attr->value(); if (equalIgnoringCase(v, "middle") || equalIgnoringCase(v, "center")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__WEBKIT_CENTER); + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitCenter); else if (equalIgnoringCase(v, "absmiddle")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL_CENTER); + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueCenter); else if (equalIgnoringCase(v, "left")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__WEBKIT_LEFT); + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitLeft); else if (equalIgnoringCase(v, "right")) - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, CSS_VAL__WEBKIT_RIGHT); + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitRight); else - addCSSProperty(attr, CSS_PROP_TEXT_ALIGN, v); + addCSSProperty(attr, CSSPropertyTextAlign, v); } else if (attr->name() == heightAttr) { if (!attr->value().isEmpty()) - addCSSLength(attr, CSS_PROP_HEIGHT, attr->value()); + addCSSLength(attr, CSSPropertyHeight, attr->value()); } else HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLTableRowElement.cpp b/WebCore/html/HTMLTableRowElement.cpp index a9558a0..da07594 100644 --- a/WebCore/html/HTMLTableRowElement.cpp +++ b/WebCore/html/HTMLTableRowElement.cpp @@ -167,7 +167,7 @@ void HTMLTableRowElement::deleteCell(int index, ExceptionCode& ec) PassRefPtr<HTMLCollection> HTMLTableRowElement::cells() { - return new HTMLCollection(this, HTMLCollection::TRCells); + return HTMLCollection::create(this, HTMLCollection::TRCells); } void HTMLTableRowElement::setCells(HTMLCollection *, ExceptionCode& ec) diff --git a/WebCore/html/HTMLTableRowsCollection.cpp b/WebCore/html/HTMLTableRowsCollection.cpp index 3630fdc..7047576 100644 --- a/WebCore/html/HTMLTableRowsCollection.cpp +++ b/WebCore/html/HTMLTableRowsCollection.cpp @@ -149,10 +149,15 @@ HTMLTableRowElement* HTMLTableRowsCollection::lastRow(HTMLTableElement* table) } HTMLTableRowsCollection::HTMLTableRowsCollection(PassRefPtr<HTMLTableElement> table) - : HTMLCollection(table, Other) + : HTMLCollection(table, Other, 0) { } +PassRefPtr<HTMLTableRowsCollection> HTMLTableRowsCollection::create(PassRefPtr<HTMLTableElement> table) +{ + return adoptRef(new HTMLTableRowsCollection(table)); +} + Element* HTMLTableRowsCollection::itemAfter(Element* previous) const { ASSERT(!previous || previous->hasLocalName(trTag)); diff --git a/WebCore/html/HTMLTableRowsCollection.h b/WebCore/html/HTMLTableRowsCollection.h index 9acce69..f997e3c 100644 --- a/WebCore/html/HTMLTableRowsCollection.h +++ b/WebCore/html/HTMLTableRowsCollection.h @@ -38,12 +38,14 @@ class HTMLTableRowElement; class HTMLTableRowsCollection : public HTMLCollection { public: - HTMLTableRowsCollection(PassRefPtr<HTMLTableElement>); + static PassRefPtr<HTMLTableRowsCollection> create(PassRefPtr<HTMLTableElement>); static HTMLTableRowElement* rowAfter(HTMLTableElement*, HTMLTableRowElement*); static HTMLTableRowElement* lastRow(HTMLTableElement*); private: + HTMLTableRowsCollection(PassRefPtr<HTMLTableElement>); + virtual Element* itemAfter(Element*) const; }; diff --git a/WebCore/html/HTMLTableSectionElement.cpp b/WebCore/html/HTMLTableSectionElement.cpp index 15999e0..8190d93 100644 --- a/WebCore/html/HTMLTableSectionElement.cpp +++ b/WebCore/html/HTMLTableSectionElement.cpp @@ -169,7 +169,7 @@ void HTMLTableSectionElement::setVAlign(const String &value) PassRefPtr<HTMLCollection> HTMLTableSectionElement::rows() { - return new HTMLCollection(this, HTMLCollection::TSectionRows); + return HTMLCollection::create(this, HTMLCollection::TSectionRows); } } diff --git a/WebCore/html/HTMLTagNames.in b/WebCore/html/HTMLTagNames.in index 816f88d..6493c39 100644 --- a/WebCore/html/HTMLTagNames.in +++ b/WebCore/html/HTMLTagNames.in @@ -1,62 +1,68 @@ -a +namespace="HTML" +namespacePrefix="xhtml" +namespaceURI="http://www.w3.org/1999/xhtml" + +a interfaceName=AnchorElement abbr acronym address applet area -audio +#if ENABLE_VIDEO +audio applyAudioHack=1 +#endif b base -basefont +basefont interfaceName=BaseFontElement bdo big blockquote body -br +br interfaceName=BRElement button canvas -caption +caption interfaceName=TableCaptionElement center cite code -col +col interfaceName=TableColElement colgroup dd -del +del interfaceName=ModElement dfn -dir +dir interfaceName=DirectoryElement div -dl +dl interfaceName=DListElement dt em embed -fieldset +fieldset interfaceName=FieldSetElement font form frame -frameset +frameset interfaceName=FrameSetElement head -h1 +h1 interfaceName=HeadingElement h2 h3 h4 h5 h6 -hr +hr interfaceName=HRElement html i -iframe +iframe interfaceName=IFrameElement image -img +img interfaceName=ImageElement input ins -isindex +isindex interfaceName=IsIndexElement kbd keygen label layer legend -li +li interfaceName=LIElement link listing map @@ -69,20 +75,22 @@ noframes nolayer noscript object -ol -optgroup +ol interfaceName=OListElement +optgroup interfaceName=OptGroupElement option -p +p interfaceName=ParagraphElement param plaintext pre -q +q interfaceName=QuoteElement s samp script select small -source +#if ENABLE_VIDEO +source applyAudioHack=1 +#endif span strike strong @@ -90,18 +98,20 @@ style sub sup table -tbody -td -textarea +tbody interfaceName=TableSectionElement +td interfaceName=TableCellElement +textarea interfaceName=TextAreaElement tfoot th thead title -tr +tr interfaceName=TableRowElement tt u -ul +ul interfaceName=UListElement var -video +#if ENABLE_VIDEO +video applyAudioHack=1 +#endif wbr xmp diff --git a/WebCore/html/HTMLTextAreaElement.cpp b/WebCore/html/HTMLTextAreaElement.cpp index 4277f30..1882fe5 100644 --- a/WebCore/html/HTMLTextAreaElement.cpp +++ b/WebCore/html/HTMLTextAreaElement.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, 2008 Apple Inc. All rights reserved. * (C) 2006 Alexey Proskuryakov (ap@nypop.com) * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) * @@ -40,25 +40,23 @@ #include "Text.h" #ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS -#include "FrameView.h" -#include "WebCoreViewBridge.h" +#include "WebViewCore.h" #endif namespace WebCore { -using namespace EventNames; using namespace HTMLNames; static const int defaultRows = 2; static const int defaultCols = 20; -HTMLTextAreaElement::HTMLTextAreaElement(Document* doc, HTMLFormElement* f) - : HTMLFormControlElementWithState(textareaTag, doc, f) +HTMLTextAreaElement::HTMLTextAreaElement(Document* document, HTMLFormElement* form) + : HTMLFormControlElementWithState(textareaTag, document, form) , m_rows(defaultRows) , m_cols(defaultCols) - , m_wrap(ta_Virtual) - , cachedSelStart(-1) - , cachedSelEnd(-1) + , m_wrap(SoftWrap) + , m_cachedSelectionStart(-1) + , m_cachedSelectionEnd(-1) { setValueMatchesRenderer(); } @@ -82,55 +80,57 @@ void HTMLTextAreaElement::restoreState(const String& state) int HTMLTextAreaElement::selectionStart() { - if (renderer()) { - if (document()->focusedNode() != this && cachedSelStart != -1) - return cachedSelStart; - return static_cast<RenderTextControl *>(renderer())->selectionStart(); - } - return 0; + if (!renderer()) + return 0; + if (document()->focusedNode() != this && m_cachedSelectionStart >= 0) + return m_cachedSelectionStart; + return static_cast<RenderTextControl*>(renderer())->selectionStart(); } int HTMLTextAreaElement::selectionEnd() { - if (renderer()) { - if (document()->focusedNode() != this && cachedSelEnd != -1) - return cachedSelEnd; - return static_cast<RenderTextControl *>(renderer())->selectionEnd(); - } - return 0; + if (!renderer()) + return 0; + if (document()->focusedNode() != this && m_cachedSelectionEnd >= 0) + return m_cachedSelectionEnd; + return static_cast<RenderTextControl*>(renderer())->selectionEnd(); } void HTMLTextAreaElement::setSelectionStart(int start) { - if (renderer()) - static_cast<RenderTextControl*>(renderer())->setSelectionStart(start); + if (!renderer()) + return; + static_cast<RenderTextControl*>(renderer())->setSelectionStart(start); } void HTMLTextAreaElement::setSelectionEnd(int end) { - if (renderer()) - static_cast<RenderTextControl*>(renderer())->setSelectionEnd(end); + if (!renderer()) + return; + static_cast<RenderTextControl*>(renderer())->setSelectionEnd(end); } void HTMLTextAreaElement::select() { - if (renderer()) - static_cast<RenderTextControl *>(renderer())->select(); + if (!renderer()) + return; + static_cast<RenderTextControl*>(renderer())->select(); } void HTMLTextAreaElement::setSelectionRange(int start, int end) { - if (renderer()) - static_cast<RenderTextControl*>(renderer())->setSelectionRange(start, end); + if (!renderer()) + return; + static_cast<RenderTextControl*>(renderer())->setSelectionRange(start, end); } -void HTMLTextAreaElement::childrenChanged(bool changedByParser) +void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { setValue(defaultValue()); - HTMLElement::childrenChanged(changedByParser); + HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); } -void HTMLTextAreaElement::parseMappedAttribute(MappedAttribute *attr) +void HTMLTextAreaElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == rowsAttr) { int rows = attr->value().toInt(); @@ -151,36 +151,38 @@ void HTMLTextAreaElement::parseMappedAttribute(MappedAttribute *attr) renderer()->setNeedsLayoutAndPrefWidthsRecalc(); } } else if (attr->name() == wrapAttr) { - // virtual / physical is Netscape extension of HTML 3.0, now deprecated - // soft/ hard / off is recommendation for HTML 4 extension by IE and NS 4 - if (equalIgnoringCase(attr->value(), "virtual") || equalIgnoringCase(attr->value(), "soft")) - m_wrap = ta_Virtual; - else if (equalIgnoringCase(attr->value(), "physical") || equalIgnoringCase(attr->value(), "hard")) - m_wrap = ta_Physical; - else if (equalIgnoringCase(attr->value(), "on" )) - m_wrap = ta_Physical; + // The virtual/physical values were a Netscape extension of HTML 3.0, now deprecated. + // The soft/hard /off values are a recommendation for HTML 4 extension by IE and NS 4. + WrapMethod wrap; + if (equalIgnoringCase(attr->value(), "physical") || equalIgnoringCase(attr->value(), "hard") || equalIgnoringCase(attr->value(), "on")) + wrap = HardWrap; else if (equalIgnoringCase(attr->value(), "off")) - m_wrap = ta_NoWrap; - if (renderer()) - renderer()->setNeedsLayoutAndPrefWidthsRecalc(); + wrap = NoWrap; + else + wrap = SoftWrap; + if (wrap != m_wrap) { + m_wrap = wrap; + if (renderer()) + renderer()->setNeedsLayoutAndPrefWidthsRecalc(); + } } else if (attr->name() == accesskeyAttr) { // ignore for the moment } else if (attr->name() == alignAttr) { // Don't map 'align' attribute. This matches what Firefox, Opera and IE do. // See http://bugs.webkit.org/show_bug.cgi?id=7075 } else if (attr->name() == onfocusAttr) - setHTMLEventListener(focusEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().focusEvent, attr); else if (attr->name() == onblurAttr) - setHTMLEventListener(blurEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().blurEvent, attr); else if (attr->name() == onselectAttr) - setHTMLEventListener(selectEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().selectEvent, attr); else if (attr->name() == onchangeAttr) - setHTMLEventListener(changeEvent, attr); + setInlineEventListenerForTypeAndAttribute(eventNames().changeEvent, attr); else HTMLFormControlElementWithState::parseMappedAttribute(attr); } -RenderObject* HTMLTextAreaElement::createRenderer(RenderArena* arena, RenderStyle* style) +RenderObject* HTMLTextAreaElement::createRenderer(RenderArena* arena, RenderStyle*) { return new (arena) RenderTextControl(this, true); } @@ -189,10 +191,12 @@ bool HTMLTextAreaElement::appendFormData(FormDataList& encoding, bool) { if (name().isEmpty()) return false; - - bool hardWrap = renderer() && wrap() == ta_Physical; - String v = hardWrap ? static_cast<RenderTextControl*>(renderer())->textWithHardLineBreaks() : value(); - encoding.appendData(name(), v); + + // 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()); + const String& text = (m_wrap == HardWrap && control) ? control->textWithHardLineBreaks() : value(); + encoding.appendData(name(), text); return true; } @@ -203,42 +207,43 @@ void HTMLTextAreaElement::reset() bool HTMLTextAreaElement::isKeyboardFocusable(KeyboardEvent*) const { - // If text areas can be focused, then they should always be keyboard focusable - return HTMLFormControlElementWithState::isFocusable(); + // If a given text area can be focused at all, then it will always be keyboard focusable. + return isFocusable(); } bool HTMLTextAreaElement::isMouseFocusable() const { - return HTMLFormControlElementWithState::isFocusable(); + return isFocusable(); } void HTMLTextAreaElement::updateFocusAppearance(bool restorePreviousSelection) { ASSERT(renderer()); - if (!restorePreviousSelection || cachedSelStart == -1) { + if (!restorePreviousSelection || m_cachedSelectionStart < 0) { // If this is the first focus, set a caret at the beginning of the text. - // This matches some browsers' behavior; see Bugzilla Bug 11746 Comment #15. + // This matches some browsers' behavior; see bug 11746 Comment #15. // http://bugs.webkit.org/show_bug.cgi?id=11746#c15 setSelectionRange(0, 0); #ifdef ANDROID_SELECT_TEXT_AREAS // We need to select the entire text to match the platform text field. select(); #endif - } else + } else { // Restore the cached selection. This matches other browsers' behavior. - setSelectionRange(cachedSelStart, cachedSelEnd); + setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd); + } if (document()->frame()) document()->frame()->revealSelection(); } -void HTMLTextAreaElement::defaultEventHandler(Event *evt) +void HTMLTextAreaElement::defaultEventHandler(Event* event) { - if (renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == blurEvent)) - static_cast<RenderTextControl*>(renderer())->forwardEvent(evt); + if (renderer() && (event->isMouseEvent() || event->isDragEvent() || event->isWheelEvent() || event->type() == eventNames().blurEvent)) + static_cast<RenderTextControl*>(renderer())->forwardEvent(event); - HTMLFormControlElementWithState::defaultEventHandler(evt); + HTMLFormControlElementWithState::defaultEventHandler(event); } void HTMLTextAreaElement::rendererWillBeDestroyed() @@ -248,11 +253,12 @@ void HTMLTextAreaElement::rendererWillBeDestroyed() void HTMLTextAreaElement::updateValue() const { - if (!valueMatchesRenderer()) { - ASSERT(renderer()); - m_value = static_cast<RenderTextControl*>(renderer())->text(); - setValueMatchesRenderer(); - } + if (valueMatchesRenderer()) + return; + + ASSERT(renderer()); + m_value = static_cast<RenderTextControl*>(renderer())->text(); + setValueMatchesRenderer(); } String HTMLTextAreaElement::value() const @@ -265,24 +271,21 @@ void HTMLTextAreaElement::setValue(const String& value) { // Code elsewhere normalizes line endings added by the user via the keyboard or pasting. // We must normalize line endings coming from JS. - DeprecatedString valueWithNormalizedLineEndings = value.deprecatedString(); - valueWithNormalizedLineEndings.replace("\r\n", "\n"); - valueWithNormalizedLineEndings.replace("\r", "\n"); - - m_value = valueWithNormalizedLineEndings; + m_value = value; + m_value.replace("\r\n", "\n"); + m_value.replace('\r', '\n'); + setValueMatchesRenderer(); if (inDocument()) document()->updateRendering(); if (renderer()) renderer()->updateFromElement(); - // Set the caret to the end of the text value. if (document()->focusedNode() == this) { #ifdef ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS // Make sure our UI side textfield changes to match the RenderTextControl - WebCoreViewBridge* viewImpl = document()->frame()->view()->getWebCoreViewBridge(); - viewImpl->updateTextfield(this, false, value); + android::WebViewCore::getWebViewCore(document()->view())->updateTextfield(this, false, value); #endif unsigned endOfString = m_value.length(); setSelectionRange(endOfString, endOfString); @@ -293,45 +296,57 @@ void HTMLTextAreaElement::setValue(const String& value) String HTMLTextAreaElement::defaultValue() const { - String val = ""; + String value = ""; // Since there may be comments, ignore nodes other than text nodes. - for (Node* n = firstChild(); n; n = n->nextSibling()) + for (Node* n = firstChild(); n; n = n->nextSibling()) { if (n->isTextNode()) - val += static_cast<Text*>(n)->data(); + value += static_cast<Text*>(n)->data(); + } - // FIXME: We should only drop the first carriage return for the default - // value in the original source, not defaultValues set from JS. This code - // will do both. - if (val.length() >= 2 && val[0] == '\r' && val[1] == '\n') - val.remove(0, 2); - else if (val.length() >= 1 && (val[0] == '\r' || val[0] == '\n')) - val.remove(0, 1); + UChar firstCharacter = value[0]; + if (firstCharacter == '\r' && value[1] == '\n') + value.remove(0, 2); + else if (firstCharacter == '\r' || firstCharacter == '\n') + value.remove(0, 1); - return val; + return value; } void HTMLTextAreaElement::setDefaultValue(const String& defaultValue) { - // To preserve comments, remove all the text nodes, then add a single one. + // To preserve comments, remove only the text nodes, then add a single text node. + Vector<RefPtr<Node> > textNodes; - for (Node* n = firstChild(); n; n = n->nextSibling()) + for (Node* n = firstChild(); n; n = n->nextSibling()) { if (n->isTextNode()) textNodes.append(n); - ExceptionCode ec = 0; + } + ExceptionCode ec; size_t size = textNodes.size(); for (size_t i = 0; i < size; ++i) removeChild(textNodes[i].get(), ec); - insertBefore(document()->createTextNode(defaultValue), firstChild(), ec); - setValue(defaultValue); + + // Normalize line endings. + // Add an extra line break if the string starts with one, since + // the code to read default values from the DOM strips the leading one. + String value = defaultValue; + value.replace("\r\n", "\n"); + value.replace('\r', '\n'); + if (value[0] == '\n') + value = "\n" + value; + + insertBefore(document()->createTextNode(value), firstChild(), ec); + + setValue(value); } -void HTMLTextAreaElement::accessKeyAction(bool sendToAnyElement) +void HTMLTextAreaElement::accessKeyAction(bool) { focus(); } -String HTMLTextAreaElement::accessKey() const +const AtomicString& HTMLTextAreaElement::accessKey() const { return getAttribute(accesskeyAttr); } @@ -353,9 +368,9 @@ void HTMLTextAreaElement::setRows(int rows) Selection HTMLTextAreaElement::selection() const { - if (!renderer() || cachedSelStart == -1 || cachedSelEnd == -1) + if (!renderer() || m_cachedSelectionStart < 0 || m_cachedSelectionEnd < 0) return Selection(); - return static_cast<RenderTextControl*>(renderer())->selection(cachedSelStart, cachedSelEnd); + return static_cast<RenderTextControl*>(renderer())->selection(m_cachedSelectionStart, m_cachedSelectionEnd); } bool HTMLTextAreaElement::shouldUseInputMethod() const diff --git a/WebCore/html/HTMLTextAreaElement.h b/WebCore/html/HTMLTextAreaElement.h index c4d712d..d5b06fa 100644 --- a/WebCore/html/HTMLTextAreaElement.h +++ b/WebCore/html/HTMLTextAreaElement.h @@ -24,7 +24,7 @@ #ifndef HTMLTextAreaElement_h #define HTMLTextAreaElement_h -#include "HTMLGenericFormElement.h" +#include "HTMLFormControlElement.h" namespace WebCore { @@ -32,8 +32,6 @@ class Selection; class HTMLTextAreaElement : public HTMLFormControlElementWithState { public: - enum WrapMethod { ta_NoWrap, ta_Virtual, ta_Physical }; - HTMLTextAreaElement(Document*, HTMLFormElement* = 0); virtual bool checkDTD(const Node* newChild) { return newChild->isTextNode(); } @@ -41,7 +39,7 @@ public: int cols() const { return m_cols; } int rows() const { return m_rows; } - WrapMethod wrap() const { return m_wrap; } + bool shouldWrapText() const { return m_wrap != NoWrap; } virtual bool isEnumeratable() const { return true; } @@ -52,6 +50,8 @@ public: bool readOnly() const { return isReadOnlyControl(); } + virtual bool isTextControl() const { return true; } + int selectionStart(); int selectionEnd(); @@ -61,7 +61,7 @@ public: void select(); void setSelectionRange(int, int); - virtual void childrenChanged(bool changedByParser = false); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); virtual void parseMappedAttribute(MappedAttribute*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); virtual bool appendFormData(FormDataList&, bool); @@ -80,25 +80,28 @@ public: virtual void accessKeyAction(bool sendToAnyElement); - String accessKey() const; + const AtomicString& accessKey() const; void setAccessKey(const String&); void setCols(int); void setRows(int); - void cacheSelection(int s, int e) { cachedSelStart = s; cachedSelEnd = e; }; + void cacheSelection(int s, int e) { m_cachedSelectionStart = s; m_cachedSelectionEnd = e; }; Selection selection() const; virtual bool shouldUseInputMethod() const; + private: + enum WrapMethod { NoWrap, SoftWrap, HardWrap }; + void updateValue() const; int m_rows; int m_cols; WrapMethod m_wrap; mutable String m_value; - int cachedSelStart; - int cachedSelEnd; + int m_cachedSelectionStart; + int m_cachedSelectionEnd; }; } //namespace diff --git a/WebCore/html/HTMLTextAreaElement.idl b/WebCore/html/HTMLTextAreaElement.idl index 40c3feb..c4f144b 100644 --- a/WebCore/html/HTMLTextAreaElement.idl +++ b/WebCore/html/HTMLTextAreaElement.idl @@ -30,17 +30,17 @@ module html { attribute [ConvertNullToNullString] DOMString accessKey; attribute long cols; attribute boolean disabled; + attribute boolean autofocus; attribute [ConvertNullToNullString] DOMString name; attribute boolean readOnly; attribute long rows; - attribute long tabIndex; readonly attribute DOMString type; attribute [ConvertNullToNullString] DOMString value; - void blur(); - void focus(); void select(); + readonly attribute boolean willValidate; + // WinIE & FireFox extension: attribute long selectionStart; attribute long selectionEnd; diff --git a/WebCore/html/HTMLTextFieldInnerElement.cpp b/WebCore/html/HTMLTextFieldInnerElement.cpp deleted file mode 100644 index e6d5871..0000000 --- a/WebCore/html/HTMLTextFieldInnerElement.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "HTMLTextFieldInnerElement.h" - -#include "BeforeTextInsertedEvent.h" -#include "Document.h" -#include "EventHandler.h" -#include "EventNames.h" -#include "Frame.h" -#include "HTMLInputElement.h" -#include "HTMLTextAreaElement.h" -#include "MouseEvent.h" -#include "RenderTextControl.h" - -namespace WebCore { - -using namespace EventNames; - -HTMLTextFieldInnerElement::HTMLTextFieldInnerElement(Document* doc, Node* shadowParent) - : HTMLDivElement(doc), m_shadowParent(shadowParent) -{ -} - -HTMLTextFieldInnerTextElement::HTMLTextFieldInnerTextElement(Document* doc, Node* shadowParent) - : HTMLTextFieldInnerElement(doc, shadowParent) -{ -} - -void HTMLTextFieldInnerTextElement::defaultEventHandler(Event* evt) -{ - // FIXME: In the future, we should add a way to have default event listeners. Then we would add one to the text field's inner div, and we wouldn't need this subclass. - Node* shadowAncestor = shadowAncestorNode(); - if (shadowAncestor && shadowAncestor->renderer()) { - ASSERT(shadowAncestor->renderer()->isTextField() || shadowAncestor->renderer()->isTextArea()); - if (evt->isBeforeTextInsertedEvent()) - if (shadowAncestor->renderer()->isTextField()) - static_cast<HTMLInputElement*>(shadowAncestor)->defaultEventHandler(evt); - else - static_cast<HTMLTextAreaElement*>(shadowAncestor)->defaultEventHandler(evt); - if (evt->type() == webkitEditableContentChangedEvent) - static_cast<RenderTextControl*>(shadowAncestor->renderer())->subtreeHasChanged(); - } - if (!evt->defaultHandled()) - HTMLDivElement::defaultEventHandler(evt); -} - -HTMLSearchFieldResultsButtonElement::HTMLSearchFieldResultsButtonElement(Document* doc) - : HTMLTextFieldInnerElement(doc) -{ -} - -void HTMLSearchFieldResultsButtonElement::defaultEventHandler(Event* evt) -{ - // On mousedown, bring up a menu, if needed - HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode()); - if (evt->type() == mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) { - input->focus(); - input->select(); - if (input && input->renderer() && static_cast<RenderTextControl*>(input->renderer())->popupIsVisible()) - static_cast<RenderTextControl*>(input->renderer())->hidePopup(); - else if (input->maxResults() > 0) - static_cast<RenderTextControl*>(input->renderer())->showPopup(); - evt->setDefaultHandled(); - } - if (!evt->defaultHandled()) - HTMLDivElement::defaultEventHandler(evt); -} - -HTMLSearchFieldCancelButtonElement::HTMLSearchFieldCancelButtonElement(Document* doc) - : HTMLTextFieldInnerElement(doc) - , m_capturing(false) -{ -} - -void HTMLSearchFieldCancelButtonElement::defaultEventHandler(Event* evt) -{ - // If the element is visible, on mouseup, clear the value, and set selection - HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode()); - if (evt->type() == mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) { - input->focus(); - input->select(); - evt->setDefaultHandled(); - if (Frame* frame = document()->frame()) - frame->eventHandler()->setCapturingMouseEventsNode(this); - m_capturing = true; - } else if (evt->type() == mouseupEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) { - if (m_capturing && renderer() && renderer()->style()->visibility() == VISIBLE) { - if (hovered()) { - input->setValue(""); - input->onSearch(); - evt->setDefaultHandled(); - } - if (Frame* frame = document()->frame()) - frame->eventHandler()->setCapturingMouseEventsNode(0); - m_capturing = false; - } - } - if (!evt->defaultHandled()) - HTMLDivElement::defaultEventHandler(evt); -} - -} diff --git a/WebCore/html/HTMLTextFieldInnerElement.h b/WebCore/html/HTMLTextFieldInnerElement.h deleted file mode 100644 index c6fcb19..0000000 --- a/WebCore/html/HTMLTextFieldInnerElement.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HTMLTextFieldInnerElement_h -#define HTMLTextFieldInnerElement_h - -#include "HTMLDivElement.h" - -namespace WebCore { - -class String; - -class HTMLTextFieldInnerElement : public HTMLDivElement -{ -public: - HTMLTextFieldInnerElement(Document*, Node* shadowParent = 0); - - virtual bool isMouseFocusable() const { return false; } - virtual bool isShadowNode() const { return m_shadowParent; } - virtual Node* shadowParentNode() { return m_shadowParent; } - void setShadowParentNode(Node* node) { m_shadowParent = node; } - -private: - Node* m_shadowParent; -}; - -class HTMLTextFieldInnerTextElement : public HTMLTextFieldInnerElement { -public: - HTMLTextFieldInnerTextElement(Document*, Node* shadowParent); - virtual void defaultEventHandler(Event*); -}; - -class HTMLSearchFieldResultsButtonElement : public HTMLTextFieldInnerElement { -public: - HTMLSearchFieldResultsButtonElement(Document*); - virtual void defaultEventHandler(Event*); -}; - -class HTMLSearchFieldCancelButtonElement : public HTMLTextFieldInnerElement { -public: - HTMLSearchFieldCancelButtonElement(Document*); - virtual void defaultEventHandler(Event*); -private: - bool m_capturing; -}; - -} //namespace - -#endif diff --git a/WebCore/html/HTMLTitleElement.cpp b/WebCore/html/HTMLTitleElement.cpp index 1f855e1..a75b1ee 100644 --- a/WebCore/html/HTMLTitleElement.cpp +++ b/WebCore/html/HTMLTitleElement.cpp @@ -54,7 +54,7 @@ void HTMLTitleElement::removedFromDocument() document()->removeTitle(this); } -void HTMLTitleElement::childrenChanged(bool changedByParser) +void HTMLTitleElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { m_title = ""; for (Node* c = firstChild(); c != 0; c = c->nextSibling()) @@ -62,7 +62,7 @@ void HTMLTitleElement::childrenChanged(bool changedByParser) m_title += c->nodeValue(); if (inDocument()) document()->setTitle(m_title, this); - HTMLElement::childrenChanged(changedByParser); + HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); } String HTMLTitleElement::text() const diff --git a/WebCore/html/HTMLTitleElement.h b/WebCore/html/HTMLTitleElement.h index 195305d..5bb05bc 100644 --- a/WebCore/html/HTMLTitleElement.h +++ b/WebCore/html/HTMLTitleElement.h @@ -38,7 +38,7 @@ public: virtual void insertedIntoDocument(); virtual void removedFromDocument(); - virtual void childrenChanged(bool changedByParser = false); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); String text() const; void setText(const String&); diff --git a/WebCore/html/HTMLTokenizer.cpp b/WebCore/html/HTMLTokenizer.cpp index 3481df0..bc0e215 100644 --- a/WebCore/html/HTMLTokenizer.cpp +++ b/WebCore/html/HTMLTokenizer.cpp @@ -23,6 +23,9 @@ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifdef ANDROID_INSTRUMENT +#define LOG_TAG "WebCore" +#endif #include "config.h" #include "HTMLTokenizer.h" @@ -41,61 +44,54 @@ #include "HTMLParser.h" #include "HTMLScriptElement.h" #include "HTMLViewSourceDocument.h" -#ifdef ANDROID_PRELOAD_CHANGES +#include "Page.h" #include "PreloadScanner.h" -#endif -#include "Settings.h" +#include "ScriptController.h" #include "SystemTime.h" -#include "kjs_proxy.h" #include <wtf/ASCIICType.h> #include "HTMLEntityNames.c" -#ifdef ANDROID_INSTRUMENT -#undef LOG -#include <utils/Log.h> -#endif - -#ifdef ANDROID_PRELOAD_CHANGES #define PRELOAD_SCANNER_ENABLED 1 -#endif // #define INSTRUMENT_LAYOUT_SCHEDULING 1 -#if MOBILE -// The mobile device needs to be responsive, as such the tokenizer chunk size is reduced. -// This value is used to define how many characters the tokenizer will process before -// yeilding control. -#define TOKENIZER_CHUNK_SIZE 256 -#else -#define TOKENIZER_CHUNK_SIZE 4096 -#endif - using namespace std; using namespace WTF; namespace WebCore { using namespace HTMLNames; -using namespace EventNames; + +#if MOBILE +// The mobile device needs to be responsive, as such the tokenizer chunk size is reduced. +// This value is used to define how many characters the tokenizer will process before +// yeilding control. +static const int defaultTokenizerChunkSize = 256; +#else +static const int defaultTokenizerChunkSize = 4096; +#endif #if MOBILE // As the chunks are smaller (above), the tokenizer should not yield for as long a period, otherwise // it will take way to long to load a page. -const double tokenizerTimeDelay = 0.300; - +static const double defaultTokenizerTimeDelay = 0.300; #else // FIXME: We would like this constant to be 200ms. // Yielding more aggressively results in increased responsiveness and better incremental rendering. // It slows down overall page-load on slower machines, though, so for now we set a value of 500. -const double tokenizerTimeDelay = 0.500; +static const double defaultTokenizerTimeDelay = 0.500; #endif static const char commentStart [] = "<!--"; +static const char doctypeStart [] = "<!doctype"; +static const char publicStart [] = "public"; +static const char systemStart [] = "system"; static const char scriptEnd [] = "</script"; static const char xmpEnd [] = "</xmp"; static const char styleEnd [] = "</style"; static const char textareaEnd [] = "</textarea"; static const char titleEnd [] = "</title"; +static const char iframeEnd [] = "</iframe"; // Full support for MS Windows extensions to Latin-1. // Technically these extensions should only be activated for pages @@ -142,9 +138,11 @@ inline void Token::addAttribute(Document* doc, AtomicString& attrName, const Ato { if (!attrName.isEmpty()) { ASSERT(!attrName.contains('/')); - RefPtr<MappedAttribute> a = new MappedAttribute(attrName, v); - if (!attrs) - attrs = new NamedMappedAttrMap(0); + RefPtr<MappedAttribute> a = MappedAttribute::create(attrName, v); + if (!attrs) { + attrs = NamedMappedAttrMap::create(); + attrs->reserveCapacity(10); + } attrs->insertAttribute(a.release(), viewSourceMode); } @@ -166,8 +164,7 @@ void Frame::resetParsingTimeCounter() void Frame::reportParsingTimeCounter() { - LOG(LOG_DEBUG, "WebCore", - "*-* Total parsing time (may include calcStyle or Java callback): %d ms called %d times\n", + LOGD("*-* Total parsing time (may include calcStyle or Java callback): %d ms called %d times\n", sTotalTimeUsed, sCounter); } #endif @@ -233,9 +230,10 @@ void HTMLTokenizer::reset() ASSERT(m_executingScript == 0); while (!pendingScripts.isEmpty()) { - CachedScript *cs = pendingScripts.dequeue(); - ASSERT(cache()->disabled() || cs->accessCount() > 0); - cs->deref(this); + CachedScript *cs = pendingScripts.first().get(); + pendingScripts.removeFirst(); + ASSERT(cache()->disabled() || cs->accessCount() > 0); + cs->removeClient(this); } fastFree(buffer); @@ -251,6 +249,9 @@ void HTMLTokenizer::reset() m_state.setForceSynchronous(false); currToken.reset(); + m_doctypeToken.reset(); + m_doctypeSearchCount = 0; + m_doctypeSecondarySearchCount = 0; } void HTMLTokenizer::begin() @@ -276,6 +277,17 @@ void HTMLTokenizer::begin() scriptStartLineno = 0; tagStartLineno = 0; m_state.setForceSynchronous(false); + + Page* page = m_doc->page(); + if (page && page->hasCustomHTMLTokenizerTimeDelay()) + m_tokenizerTimeDelay = page->customHTMLTokenizerTimeDelay(); + else + m_tokenizerTimeDelay = defaultTokenizerTimeDelay; + + if (page && page->hasCustomHTMLTokenizerChunkSize()) + m_tokenizerChunkSize = page->customHTMLTokenizerChunkSize(); + else + m_tokenizerChunkSize = defaultTokenizerChunkSize; } void HTMLTokenizer::setForceSynchronous(bool force) @@ -322,20 +334,24 @@ HTMLTokenizer::State HTMLTokenizer::processListing(SegmentedString list, State s HTMLTokenizer::State HTMLTokenizer::parseSpecial(SegmentedString &src, State state) { - ASSERT(state.inTextArea() || state.inTitle() || !state.hasEntityState()); + ASSERT(state.inTextArea() || state.inTitle() || state.inIFrame() || !state.hasEntityState()); ASSERT(!state.hasTagState()); - ASSERT(state.inXmp() + state.inTextArea() + state.inTitle() + state.inStyle() + state.inScript() == 1 ); - if (state.inScript()) - scriptStartLineno = m_lineNumber; + ASSERT(state.inXmp() + state.inTextArea() + state.inTitle() + state.inStyle() + state.inScript() + state.inIFrame() == 1 ); + if (state.inScript() && !scriptStartLineno) + scriptStartLineno = m_lineNumber + 1; // Script line numbers are 1 based. if (state.inComment()) state = parseComment(src, state); + int lastDecodedEntityPosition = -1; while ( !src.isEmpty() ) { checkScriptBuffer(); UChar ch = *src; - if (!scriptCodeResync && !brokenComments && !state.inTextArea() && !state.inXmp() && ch == '-' && scriptCodeSize >= 3 && !src.escaped() && scriptCode[scriptCodeSize-3] == '<' && scriptCode[scriptCodeSize-2] == '!' && scriptCode[scriptCodeSize-1] == '-') { + if (!scriptCodeResync && !brokenComments && + !state.inXmp() && ch == '-' && scriptCodeSize >= 3 && !src.escaped() && + scriptCode[scriptCodeSize-3] == '<' && scriptCode[scriptCodeSize-2] == '!' && scriptCode[scriptCodeSize-1] == '-' && + (lastDecodedEntityPosition < scriptCodeSize - 3)) { state.setInComment(true); state = parseComment(src, state); continue; @@ -362,6 +378,9 @@ HTMLTokenizer::State HTMLTokenizer::parseSpecial(SegmentedString &src, State sta } else if (state.inXmp()) { currToken.tagName = xmpTag.localName(); currToken.beginTag = false; + } else if (state.inIFrame()) { + currToken.tagName = iframeTag.localName(); + currToken.beginTag = false; } processToken(); state.setInStyle(false); @@ -369,6 +388,7 @@ HTMLTokenizer::State HTMLTokenizer::parseSpecial(SegmentedString &src, State sta state.setInTextArea(false); state.setInTitle(false); state.setInXmp(false); + state.setInIFrame(false); tquote = NoQuote; scriptCodeSize = scriptCodeResync = 0; } @@ -377,7 +397,8 @@ HTMLTokenizer::State HTMLTokenizer::parseSpecial(SegmentedString &src, State sta // possible end of tagname, lets check. if (!scriptCodeResync && !state.escaped() && !src.escaped() && (ch == '>' || ch == '/' || isASCIISpace(ch)) && scriptCodeSize >= searchStopperLen && - tagMatch( searchStopper, scriptCode+scriptCodeSize-searchStopperLen, searchStopperLen )) { + tagMatch(searchStopper, scriptCode + scriptCodeSize - searchStopperLen, searchStopperLen) && + (lastDecodedEntityPosition < scriptCodeSize - searchStopperLen)) { scriptCodeResync = scriptCodeSize-searchStopperLen+1; tquote = NoQuote; continue; @@ -391,11 +412,14 @@ HTMLTokenizer::State HTMLTokenizer::parseSpecial(SegmentedString &src, State sta tquote = NoQuote; } state.setEscaped(!state.escaped() && ch == '\\'); - if (!scriptCodeResync && (state.inTextArea() || state.inTitle()) && !src.escaped() && ch == '&') { + if (!scriptCodeResync && (state.inTextArea() || state.inTitle() || state.inIFrame()) && !src.escaped() && ch == '&') { UChar* scriptCodeDest = scriptCode+scriptCodeSize; src.advancePastNonNewline(); state = parseEntity(src, scriptCodeDest, state, m_cBufferPos, true, false); - scriptCodeSize = scriptCodeDest - scriptCode; + if (scriptCodeDest == scriptCode + scriptCodeSize) + lastDecodedEntityPosition = scriptCodeSize; + else + scriptCodeSize = scriptCodeDest - scriptCode; } else { scriptCode[scriptCodeSize++] = ch; src.advance(m_lineNumber); @@ -409,6 +433,10 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state) { // We are inside a <script> bool doScriptExec = false; + int startLine = scriptStartLineno; + + // Reset scriptStartLineno to indicate that we've finished parsing the current script element + scriptStartLineno = 0; // (Bugzilla 3837) Scripts following a frameset element should not execute or, // in the case of extern scripts, even load. @@ -427,18 +455,13 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state) // The parser might have been stopped by for example a window.close call in an earlier script. // If so, we don't want to load scripts. if (!m_parserStopped && (cs = m_doc->docLoader()->requestScript(scriptSrc, scriptSrcCharset))) - pendingScripts.enqueue(cs); + pendingScripts.append(cs); else scriptNode = 0; } else scriptNode = 0; scriptSrc = String(); } else { -#ifdef TOKEN_DEBUG - kdDebug( 6036 ) << "---START SCRIPT---" << endl; - kdDebug( 6036 ) << DeprecatedString(scriptCode, scriptCodeSize) << endl; - kdDebug( 6036 ) << "---END SCRIPT---" << endl; -#endif // Parse scriptCode containing <script> info #if USE(LOW_BANDWIDTH_DISPLAY) if (m_doc->inLowBandwidthDisplay()) { @@ -455,13 +478,14 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state) } state = processListing(SegmentedString(scriptCode, scriptCodeSize), state); - String scriptCode(buffer, dest - buffer); - processToken(); + RefPtr<Node> node = processToken(); + String scriptString = node ? node->textContent() : ""; currToken.tagName = scriptTag.localName(); currToken.beginTag = false; processToken(); state.setInScript(false); + scriptCodeSize = scriptCodeResync = 0; // FIXME: The script should be syntax highlighted. if (inViewSourceMode()) @@ -470,7 +494,6 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state) SegmentedString *savedPrependingSrc = currentPrependingSrc; SegmentedString prependingSrc; currentPrependingSrc = &prependingSrc; - scriptCodeSize = scriptCodeResync = 0; #ifdef ANDROID_INSTRUMENT sTotalTimeUsed += get_thread_msec() - sCurrentTime; @@ -489,7 +512,7 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state) m_state = state; bool savedRequestingScript = m_requestingScript; m_requestingScript = true; - cs->ref(this); + cs->addClient(this); m_requestingScript = savedRequestingScript; state = m_state; // will be 0 if script was already loaded and ref() executed it @@ -501,7 +524,7 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state) else prependingSrc = src; setSrc(SegmentedString()); - state = scriptExecution(scriptCode, state, String(), scriptStartLineno); + state = scriptExecution(scriptString, state, String(), startLine); } } @@ -520,7 +543,7 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state) // we need to do this slightly modified bit of one of the write() cases // because we want to prepend to pendingSrc rather than appending // if there's no previous prependingSrc - if (state.loadingExtScript()) { + if (!pendingScripts.isEmpty()) { if (currentPrependingSrc) { currentPrependingSrc->append(prependingSrc); } else { @@ -532,6 +555,7 @@ HTMLTokenizer::State HTMLTokenizer::scriptHandler(State state) state = m_state; } } + #if PRELOAD_SCANNER_ENABLED if (!pendingScripts.isEmpty() && !m_executingScript) { @@ -553,7 +577,7 @@ HTMLTokenizer::State HTMLTokenizer::scriptExecution(const String& str, State sta if (m_fragment || !m_doc->frame()) return state; m_executingScript++; - DeprecatedString url = scriptURL.isNull() ? m_doc->frame()->document()->url() : scriptURL.deprecatedString(); + String url = scriptURL.isNull() ? m_doc->frame()->document()->url().string() : scriptURL; SegmentedString *savedPrependingSrc = currentPrependingSrc; SegmentedString prependingSrc; @@ -589,12 +613,12 @@ HTMLTokenizer::State HTMLTokenizer::scriptExecution(const String& str, State sta // we need to do this slightly modified bit of one of the write() cases // because we want to prepend to pendingSrc rather than appending // if there's no previous prependingSrc - if (state.loadingExtScript()) { + if (!pendingScripts.isEmpty()) { if (currentPrependingSrc) currentPrependingSrc->append(prependingSrc); else pendingSrc.prepend(prependingSrc); - + #if PRELOAD_SCANNER_ENABLED // We are stuck waiting for another script. Lets check the source that // was just document.write()n for anything to load. @@ -635,7 +659,7 @@ HTMLTokenizer::State HTMLTokenizer::parseComment(SegmentedString &src, State sta } if (handleBrokenComments || endCharsCount > 1) { src.advancePastNonNewline(); - if (!(state.inTitle() || state.inScript() || state.inXmp() || state.inTextArea() || state.inStyle())) { + if (!(state.inTitle() || state.inScript() || state.inXmp() || state.inTextArea() || state.inStyle() || state.inIFrame())) { checkScriptBuffer(); scriptCode[scriptCodeSize] = 0; scriptCode[scriptCodeSize + 1] = 0; @@ -901,6 +925,222 @@ HTMLTokenizer::State HTMLTokenizer::parseEntity(SegmentedString &src, UChar*& de return state; } +HTMLTokenizer::State HTMLTokenizer::parseDoctype(SegmentedString& src, State state) +{ + ASSERT(state.inDoctype()); + while (!src.isEmpty() && state.inDoctype()) { + UChar c = *src; + bool isWhitespace = c == '\r' || c == '\n' || c == '\t' || c == ' '; + switch (m_doctypeToken.state()) { + case DoctypeBegin: { + m_doctypeToken.setState(DoctypeBeforeName); + if (isWhitespace) { + src.advance(m_lineNumber); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } + break; + } + case DoctypeBeforeName: { + if (c == '>') { + // Malformed. Just exit. + src.advancePastNonNewline(); + state.setInDoctype(false); + if (inViewSourceMode()) + processDoctypeToken(); + } else if (isWhitespace) { + src.advance(m_lineNumber); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else + m_doctypeToken.setState(DoctypeName); + break; + } + case DoctypeName: { + if (c == '>') { + // Valid doctype. Emit it. + src.advancePastNonNewline(); + state.setInDoctype(false); + processDoctypeToken(); + } else if (isWhitespace) { + m_doctypeSearchCount = 0; // Used now to scan for PUBLIC + m_doctypeSecondarySearchCount = 0; // Used now to scan for SYSTEM + m_doctypeToken.setState(DoctypeAfterName); + src.advance(m_lineNumber); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else { + src.advancePastNonNewline(); + m_doctypeToken.m_name.append(c); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } + break; + } + case DoctypeAfterName: { + if (c == '>') { + // Valid doctype. Emit it. + src.advancePastNonNewline(); + state.setInDoctype(false); + processDoctypeToken(); + } else if (!isWhitespace) { + src.advancePastNonNewline(); + if (toASCIILower(c) == publicStart[m_doctypeSearchCount]) { + m_doctypeSearchCount++; + if (m_doctypeSearchCount == 6) + // Found 'PUBLIC' sequence + m_doctypeToken.setState(DoctypeBeforePublicID); + } else if (m_doctypeSearchCount > 0) { + m_doctypeSearchCount = 0; + m_doctypeToken.setState(DoctypeBogus); + } else if (toASCIILower(c) == systemStart[m_doctypeSecondarySearchCount]) { + m_doctypeSecondarySearchCount++; + if (m_doctypeSecondarySearchCount == 6) + // Found 'SYSTEM' sequence + m_doctypeToken.setState(DoctypeBeforeSystemID); + } else { + m_doctypeSecondarySearchCount = 0; + m_doctypeToken.setState(DoctypeBogus); + } + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else { + src.advance(m_lineNumber); // Whitespace keeps us in the after name state. + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } + break; + } + case DoctypeBeforePublicID: { + if (c == '\"' || c == '\'') { + tquote = c == '\"' ? DoubleQuote : SingleQuote; + m_doctypeToken.setState(DoctypePublicID); + src.advancePastNonNewline(); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else if (c == '>') { + // Considered bogus. Don't process the doctype. + src.advancePastNonNewline(); + state.setInDoctype(false); + if (inViewSourceMode()) + processDoctypeToken(); + } else if (isWhitespace) { + src.advance(m_lineNumber); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else + m_doctypeToken.setState(DoctypeBogus); + break; + } + case DoctypePublicID: { + if ((c == '\"' && tquote == DoubleQuote) || (c == '\'' && tquote == SingleQuote)) { + src.advancePastNonNewline(); + m_doctypeToken.setState(DoctypeAfterPublicID); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else if (c == '>') { + // Considered bogus. Don't process the doctype. + src.advancePastNonNewline(); + state.setInDoctype(false); + if (inViewSourceMode()) + processDoctypeToken(); + } else { + m_doctypeToken.m_publicID.append(c); + src.advance(m_lineNumber); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } + break; + } + case DoctypeAfterPublicID: + if (c == '\"' || c == '\'') { + tquote = c == '\"' ? DoubleQuote : SingleQuote; + m_doctypeToken.setState(DoctypeSystemID); + src.advancePastNonNewline(); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else if (c == '>') { + // Valid doctype. Emit it now. + src.advancePastNonNewline(); + state.setInDoctype(false); + processDoctypeToken(); + } else if (isWhitespace) { + src.advance(m_lineNumber); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else + m_doctypeToken.setState(DoctypeBogus); + break; + case DoctypeBeforeSystemID: + if (c == '\"' || c == '\'') { + tquote = c == '\"' ? DoubleQuote : SingleQuote; + m_doctypeToken.setState(DoctypeSystemID); + src.advancePastNonNewline(); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else if (c == '>') { + // Considered bogus. Don't process the doctype. + src.advancePastNonNewline(); + state.setInDoctype(false); + } else if (isWhitespace) { + src.advance(m_lineNumber); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else + m_doctypeToken.setState(DoctypeBogus); + break; + case DoctypeSystemID: + if ((c == '\"' && tquote == DoubleQuote) || (c == '\'' && tquote == SingleQuote)) { + src.advancePastNonNewline(); + m_doctypeToken.setState(DoctypeAfterSystemID); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else if (c == '>') { + // Considered bogus. Don't process the doctype. + src.advancePastNonNewline(); + state.setInDoctype(false); + if (inViewSourceMode()) + processDoctypeToken(); + } else { + m_doctypeToken.m_systemID.append(c); + src.advance(m_lineNumber); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } + break; + case DoctypeAfterSystemID: + if (c == '>') { + // Valid doctype. Emit it now. + src.advancePastNonNewline(); + state.setInDoctype(false); + processDoctypeToken(); + } else if (isWhitespace) { + src.advance(m_lineNumber); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } else + m_doctypeToken.setState(DoctypeBogus); + break; + case DoctypeBogus: + if (c == '>') { + // Done with the bogus doctype. + src.advancePastNonNewline(); + state.setInDoctype(false); + if (inViewSourceMode()) + processDoctypeToken(); + } else { + src.advance(m_lineNumber); // Just keep scanning for '>' + if (inViewSourceMode()) + m_doctypeToken.m_source.append(c); + } + break; + default: + break; + } + } + return state; +} + HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state) { ASSERT(!state.hasEntityState()); @@ -919,19 +1159,14 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state) } case TagName: { -#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1 - qDebug("TagName"); -#endif - if (searchCount > 0) - { - if (*src == commentStart[searchCount]) - { + if (searchCount > 0) { + if (*src == commentStart[searchCount]) { searchCount++; - if (searchCount == 4) - { -#ifdef TOKEN_DEBUG - kdDebug( 6036 ) << "Found comment" << endl; -#endif + if (searchCount == 2) + m_doctypeSearchCount++; // A '!' is also part of a doctype, so we are moving through that still as well. + else + m_doctypeSearchCount = 0; + if (searchCount == 4) { // Found '<!--' sequence src.advancePastNonNewline(); dest = buffer; // ignore the previous part of this tag @@ -942,12 +1177,11 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state) // <!--> as a valid comment, since both mozilla and IE on windows // can handle this case. Only do this in quirks mode. -dwh if (!src.isEmpty() && *src == '>' && m_doc->inCompatMode()) { - state.setInComment(false); - src.advancePastNonNewline(); - if (!src.isEmpty()) - cBuffer[cBufferPos++] = *src; - } - else + state.setInComment(false); + src.advancePastNonNewline(); + if (!src.isEmpty()) + cBuffer[cBufferPos++] = *src; + } else state = parseComment(src, state); m_cBufferPos = cBufferPos; @@ -956,10 +1190,30 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state) cBuffer[cBufferPos++] = *src; src.advancePastNonNewline(); break; - } - else + } else searchCount = 0; // Stop looking for '<!--' sequence } + + if (m_doctypeSearchCount > 0) { + if (toASCIILower(*src) == doctypeStart[m_doctypeSearchCount]) { + m_doctypeSearchCount++; + cBuffer[cBufferPos++] = *src; + src.advancePastNonNewline(); + if (m_doctypeSearchCount == 9) { + // Found '<!DOCTYPE' sequence + state.setInDoctype(true); + state.setTagState(NoTag); + m_doctypeToken.reset(); + if (inViewSourceMode()) + m_doctypeToken.m_source.append(cBuffer, cBufferPos); + state = parseDoctype(src, state); + m_cBufferPos = cBufferPos; + return state; + } + break; + } else + m_doctypeSearchCount = 0; // Stop looking for '<!DOCTYPE' sequence + } bool finish = false; unsigned int ll = min(src.length(), CBUFLEN - cBufferPos); @@ -1153,7 +1407,8 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state) while (dest > buffer + 1 && (dest[-1] == '\n' || dest[-1] == '\r')) dest--; // remove trailing newlines AtomicString v(buffer + 1, dest - buffer - 1); - attrName = v; // Just make the name/value match. (FIXME: Is this some WinIE quirk?) + if (!v.contains('/')) + attrName = v; // Just make the name/value match. (FIXME: Is this some WinIE quirk?) currToken.addAttribute(m_doc, attrName, v, inViewSourceMode()); if (inViewSourceMode()) currToken.addViewSourceChar('x'); @@ -1174,7 +1429,7 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state) while (dest > buffer + 1 && (dest[-1] == '\n' || dest[-1] == '\r')) dest--; // remove trailing newlines AtomicString v(buffer + 1, dest - buffer - 1); - if (attrName.isEmpty()) { + if (attrName.isEmpty() && !v.contains('/')) { attrName = v; // Make the name match the value. (FIXME: Is this a WinIE quirk?) if (inViewSourceMode()) currToken.addViewSourceChar('x'); @@ -1256,9 +1511,6 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state) } AtomicString tagName = currToken.tagName; -#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 0 - kdDebug( 6036 ) << "appending Tag: " << tagName.deprecatedString() << endl; -#endif // Handle <script src="foo"/> like Mozilla/Opera. We have to do this now for Dashboard // compatibility. @@ -1269,26 +1521,24 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state) scriptSrc = String(); scriptSrcCharset = String(); if (currToken.attrs && !m_fragment) { - if (m_doc->frame() && m_doc->frame()->scriptProxy()->isEnabled()) { + if (m_doc->frame() && m_doc->frame()->script()->isEnabled()) { if ((a = currToken.attrs->getAttributeItem(srcAttr))) - scriptSrc = m_doc->completeURL(parseURL(a->value())); - if ((a = currToken.attrs->getAttributeItem(charsetAttr))) - scriptSrcCharset = a->value().domString().stripWhiteSpace(); - if (scriptSrcCharset.isEmpty()) - scriptSrcCharset = m_doc->frame()->loader()->encoding(); + scriptSrc = m_doc->completeURL(parseURL(a->value())).string(); } } } RefPtr<Node> n = processToken(); m_cBufferPos = cBufferPos; - if (n) { + if (n || inViewSourceMode()) { if ((tagName == preTag || tagName == listingTag) && !inViewSourceMode()) { if (beginTag) state.setDiscardLF(true); // Discard the first LF after we open a pre. - } else if (tagName == scriptTag && n) { + } else if (tagName == scriptTag) { ASSERT(!scriptNode); scriptNode = n; + if (n) + scriptSrcCharset = static_cast<HTMLScriptElement*>(n.get())->scriptCharset(); if (beginTag) { searchStopper = scriptEnd; searchStopperLen = 8; @@ -1342,6 +1592,13 @@ HTMLTokenizer::State HTMLTokenizer::parseTag(SegmentedString &src, State state) state.setInXmp(true); state = parseSpecial(src, state); } + } else if (tagName == iframeTag) { + if (beginTag) { + searchStopper = iframeEnd; + searchStopperLen = 8; + state.setInIFrame(true); + state = parseSpecial(src, state); + } } } if (tagName == plaintextTag) @@ -1360,9 +1617,9 @@ inline bool HTMLTokenizer::continueProcessing(int& processedCount, double startT // processed a certain number of characters. bool allowedYield = state.allowYield(); state.setAllowYield(false); - if (!state.loadingExtScript() && !state.forceSynchronous() && !m_executingScript && (processedCount > TOKENIZER_CHUNK_SIZE || allowedYield)) { + if (!state.loadingExtScript() && !state.forceSynchronous() && !m_executingScript && (processedCount > m_tokenizerChunkSize || allowedYield)) { processedCount = 0; - if (currentTime() - startTime > tokenizerTimeDelay) { + if (currentTime() - startTime > m_tokenizerTimeDelay) { /* FIXME: We'd like to yield aggressively to give stylesheets the opportunity to load, but this hurts overall performance on slower machines. For now turn this off. @@ -1371,7 +1628,7 @@ inline bool HTMLTokenizer::continueProcessing(int& processedCount, double startT // Schedule the timer to keep processing as soon as possible. m_timer.startOneShot(0); #ifdef INSTRUMENT_LAYOUT_SCHEDULING - if (currentTime() - startTime > tokenizerTimeDelay) + if (currentTime() - startTime > m_tokenizerTimeDelay) printf("Deferring processing of data because 500ms elapsed away from event loop.\n"); #endif return false; @@ -1411,6 +1668,7 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData) } return false; } + #if PRELOAD_SCANNER_ENABLED if (m_preloadScanner && m_preloadScanner->inProgress() && appendData) @@ -1469,6 +1727,8 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData) state = parseSpecial(src, state); else if (state.inComment()) state = parseComment(src, state); + else if (state.inDoctype()) + state = parseDoctype(src, state); else if (state.inServer()) state = parseServer(src, state); else if (state.inProcessingInstruction()) @@ -1482,9 +1742,9 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData) case '/': break; case '!': { - // <!-- comment --> - searchCount = 1; // Look for '<!--' sequence to start comment - + // <!-- comment --> or <!DOCTYPE ...> + searchCount = 1; // Look for '<!--' sequence to start comment or '<!DOCTYPE' sequence to start doctype + m_doctypeSearchCount = 1; break; } case '?': { @@ -1531,6 +1791,7 @@ bool HTMLTokenizer::write(const SegmentedString& str, bool appendData) tagStartLineno = m_lineNumber; src.advancePastNonNewline(); state.setStartTag(true); + state.setDiscardLF(false); } else if (cc == '\n' || cc == '\r') { if (state.discardLF()) // Ignore this LF @@ -1642,7 +1903,7 @@ void HTMLTokenizer::end() void HTMLTokenizer::finish() { // do this as long as we don't find matching comment ends - while((m_state.inComment() || m_state.inServer()) && scriptCode && scriptCodeSize) { + while ((m_state.inComment() || m_state.inServer()) && scriptCode && scriptCodeSize) { // we've found an unmatched comment start if (m_state.inComment()) brokenComments = true; @@ -1653,13 +1914,13 @@ void HTMLTokenizer::finish() scriptCode[scriptCodeSize + 1] = 0; int pos; String food; - if (m_state.inScript() || m_state.inStyle()) + if (m_state.inScript() || m_state.inStyle() || m_state.inTextArea()) food = String(scriptCode, scriptCodeSize); else if (m_state.inServer()) { food = "<"; - food.append(String(scriptCode, scriptCodeSize)); + food.append(scriptCode, scriptCodeSize); } else { - pos = DeprecatedConstString(reinterpret_cast<DeprecatedChar*>(scriptCode), scriptCodeSize).string().find('>'); + pos = find(scriptCode, scriptCodeSize, '>'); food = String(scriptCode + pos + 1, scriptCodeSize - pos - 1); } fastFree(scriptCode); @@ -1679,55 +1940,27 @@ void HTMLTokenizer::finish() PassRefPtr<Node> HTMLTokenizer::processToken() { - KJSProxy* jsProxy = (!m_fragment && m_doc->frame()) ? m_doc->frame()->scriptProxy() : 0; - if (jsProxy && m_doc->frame()->scriptProxy()->isEnabled()) - jsProxy->setEventHandlerLineno(tagStartLineno); + ScriptController* jsProxy = (!m_fragment && m_doc->frame()) ? m_doc->frame()->script() : 0; + if (jsProxy && m_doc->frame()->script()->isEnabled()) + jsProxy->setEventHandlerLineno(tagStartLineno + 1); // Script line numbers are 1 based. if (dest > buffer) { -#ifdef TOKEN_DEBUG - if(currToken.tagName.length()) { - qDebug( "unexpected token: %s, str: *%s*", currToken.tagName.deprecatedString().latin1(),DeprecatedConstString( buffer,dest-buffer ).deprecatedString().latin1() ); - ASSERT(0); - } - -#endif currToken.text = StringImpl::createStrippingNullCharacters(buffer, dest - buffer); if (currToken.tagName != commentAtom) currToken.tagName = textAtom; } else if (currToken.tagName == nullAtom) { currToken.reset(); if (jsProxy) - jsProxy->setEventHandlerLineno(m_lineNumber); + jsProxy->setEventHandlerLineno(m_lineNumber + 1); // Script line numbers are 1 based. return 0; } dest = buffer; -#ifdef TOKEN_DEBUG - DeprecatedString name = currToken.tagName.deprecatedString(); - DeprecatedString text; - if(currToken.text) - text = DeprecatedConstString(currToken.text->unicode(), currToken.text->length()).deprecatedString(); - - kdDebug( 6036 ) << "Token --> " << name << endl; - if (currToken.flat) - kdDebug( 6036 ) << "Token is FLAT!" << endl; - if(!text.isNull()) - kdDebug( 6036 ) << "text: \"" << text << "\"" << endl; - unsigned l = currToken.attrs ? currToken.attrs->length() : 0; - if(l) { - kdDebug( 6036 ) << "Attributes: " << l << endl; - for (unsigned i = 0; i < l; ++i) { - Attribute* c = currToken.attrs->attributeItem(i); - kdDebug( 6036 ) << " " << c->localName().deprecatedString() - << "=\"" << c->value().deprecatedString() << "\"" << endl; - } - } - kdDebug( 6036 ) << endl; -#endif - RefPtr<Node> n; if (!m_parserStopped) { + if (NamedMappedAttrMap* map = currToken.attrs.get()) + map->shrinkToLength(); if (inViewSourceMode()) static_cast<HTMLViewSourceDocument*>(m_doc)->addViewSourceToken(&currToken); else @@ -1741,6 +1974,14 @@ PassRefPtr<Node> HTMLTokenizer::processToken() return n.release(); } +void HTMLTokenizer::processDoctypeToken() +{ + if (inViewSourceMode()) + static_cast<HTMLViewSourceDocument*>(m_doc)->addViewSourceDoctypeToken(&m_doctypeToken); + else + parser->parseDoctypeToken(&m_doctypeToken); +} + HTMLTokenizer::~HTMLTokenizer() { ASSERT(!inWrite); @@ -1782,33 +2023,26 @@ void HTMLTokenizer::notifyFinished(CachedResource*) ASSERT(!pendingScripts.isEmpty()); - // Make scripts loaded from file URLs wait for stylesheets to match Tiger behavior where - // file loads were serialized in lower level. - // FIXME: this should really be done for all script loads or the same effect should be achieved by other - // means, like javascript suspend/resume - m_hasScriptsWaitingForStylesheets = !m_doc->haveStylesheetsLoaded() && pendingScripts.head()->url().startsWith("file:", false); + // Make external scripts wait for external stylesheets. + // FIXME: This needs to be done for inline scripts too. + m_hasScriptsWaitingForStylesheets = !m_doc->haveStylesheetsLoaded(); if (m_hasScriptsWaitingForStylesheets) return; bool finished = false; - while (!finished && pendingScripts.head()->isLoaded()) { -#ifdef TOKEN_DEBUG - kdDebug( 6036 ) << "Finished loading an external script" << endl; -#endif - CachedScript* cs = pendingScripts.dequeue(); + while (!finished && pendingScripts.first()->isLoaded()) { + CachedScript *cs = pendingScripts.first().get(); + pendingScripts.removeFirst(); ASSERT(cache()->disabled() || cs->accessCount() > 0); String scriptSource = cs->script(); -#ifdef TOKEN_DEBUG - kdDebug( 6036 ) << "External script is:" << endl << scriptSource.deprecatedString() << endl; -#endif setSrc(SegmentedString()); // make sure we forget about the script before we execute the new one // infinite recursion might happen otherwise String cachedScriptUrl(cs->url()); bool errorOccurred = cs->errorOccurred(); - cs->deref(this); + cs->removeClient(this); RefPtr<Node> n = scriptNode.release(); #ifdef INSTRUMENT_LAYOUT_SCHEDULING @@ -1817,11 +2051,11 @@ void HTMLTokenizer::notifyFinished(CachedResource*) #endif if (errorOccurred) - EventTargetNodeCast(n.get())->dispatchHTMLEvent(errorEvent, true, false); + EventTargetNodeCast(n.get())->dispatchEventForType(eventNames().errorEvent, true, false); else { if (static_cast<HTMLScriptElement*>(n.get())->shouldExecuteAsJavaScript()) m_state = scriptExecution(scriptSource, m_state, cachedScriptUrl); - EventTargetNodeCast(n.get())->dispatchHTMLEvent(loadEvent, false, false); + EventTargetNodeCast(n.get())->dispatchEventForType(eventNames().loadEvent, false, false); } // The state of pendingScripts.isEmpty() can change inside the scriptExecution() diff --git a/WebCore/html/HTMLTokenizer.h b/WebCore/html/HTMLTokenizer.h index 7657f95..0d175db 100644 --- a/WebCore/html/HTMLTokenizer.h +++ b/WebCore/html/HTMLTokenizer.h @@ -24,14 +24,15 @@ #ifndef HTMLTokenizer_h #define HTMLTokenizer_h -#include "DeprecatedPtrQueue.h" +#include "CachedResourceClient.h" +#include "CachedResourceHandle.h" #include "NamedMappedAttrMap.h" #include "SegmentedString.h" #include "Timer.h" #include "Tokenizer.h" -#include "CachedResourceClient.h" -#include <wtf/Vector.h> +#include <wtf/Deque.h> #include <wtf/OwnPtr.h> +#include <wtf/Vector.h> namespace WebCore { @@ -43,9 +44,7 @@ class HTMLViewSourceDocument; class FrameView; class HTMLParser; class Node; -#ifdef ANDROID_PRELOAD_CHANGES class PreloadScanner; -#endif /** * @internal @@ -86,6 +85,44 @@ public: OwnPtr<Vector<UChar> > m_sourceInfo; }; +enum DoctypeState { + DoctypeBegin, + DoctypeBeforeName, + DoctypeName, + DoctypeAfterName, + DoctypeBeforePublicID, + DoctypePublicID, + DoctypeAfterPublicID, + DoctypeBeforeSystemID, + DoctypeSystemID, + DoctypeAfterSystemID, + DoctypeBogus +}; + +class DoctypeToken { +public: + DoctypeToken() {} + + void reset() + { + m_name.clear(); + m_publicID.clear(); + m_systemID.clear(); + m_state = DoctypeBegin; + m_source.clear(); + } + + DoctypeState state() { return m_state; } + void setState(DoctypeState s) { m_state = s; } + + Vector<UChar> m_name; + Vector<UChar> m_publicID; + Vector<UChar> m_systemID; + DoctypeState m_state; + + Vector<UChar> m_source; +}; + //----------------------------------------------------------------------------- class HTMLTokenizer : public Tokenizer, public CachedResourceClient { @@ -121,10 +158,13 @@ private: void end(); void reset(); + PassRefPtr<Node> processToken(); + void processDoctypeToken(); State processListing(SegmentedString, State); State parseComment(SegmentedString&, State); + State parseDoctype(SegmentedString&, State); State parseServer(SegmentedString&, State); State parseText(SegmentedString&, State); State parseSpecial(SegmentedString&, State); @@ -132,7 +172,7 @@ private: State parseEntity(SegmentedString&, UChar*& dest, State, unsigned& _cBufferPos, bool start, bool parsingTag); State parseProcessingInstruction(SegmentedString&, State); State scriptHandler(State); - State scriptExecution(const String& script, State, const String& scriptURL, int baseLine = 0); + State scriptExecution(const String& script, State, const String& scriptURL, int baseLine = 1); void setSrc(const SegmentedString&); // check if we have enough space in the buffer. @@ -215,12 +255,16 @@ private: void setInXmp(bool v) { setBit(InXmp, v); } bool inTitle() const { return testBit(InTitle); } void setInTitle(bool v) { setBit(InTitle, v); } + bool inIFrame() const { return testBit(InIFrame); } + void setInIFrame(bool v) { setBit(InIFrame, v); } bool inPlainText() const { return testBit(InPlainText); } void setInPlainText(bool v) { setBit(InPlainText, v); } bool inProcessingInstruction() const { return testBit(InProcessingInstruction); } void setInProcessingInstruction(bool v) { return setBit(InProcessingInstruction, v); } bool inComment() const { return testBit(InComment); } void setInComment(bool v) { setBit(InComment, v); } + bool inDoctype() const { return testBit(InDoctype); } + void setInDoctype(bool v) { setBit(InDoctype, v); } bool inTextArea() const { return testBit(InTextArea); } void setInTextArea(bool v) { setBit(InTextArea, v); } bool escaped() const { return testBit(Escaped); } @@ -240,11 +284,11 @@ private: bool forceSynchronous() const { return testBit(ForceSynchronous); } void setForceSynchronous(bool v) { setBit(ForceSynchronous, v); } - bool inAnySpecial() const { return m_bits & (InScript | InStyle | InXmp | InTextArea | InTitle); } + bool inAnySpecial() const { return m_bits & (InScript | InStyle | InXmp | InTextArea | InTitle | InIFrame); } bool hasTagState() const { return m_bits & TagMask; } bool hasEntityState() const { return m_bits & EntityMask; } - bool needsSpecialWriteHandling() const { return m_bits & (InScript | InStyle | InXmp | InTextArea | InTitle | TagMask | EntityMask | InPlainText | InComment | InServer | InProcessingInstruction | StartTag); } + bool needsSpecialWriteHandling() const { return m_bits & (InScript | InStyle | InXmp | InTextArea | InTitle | InIFrame | TagMask | EntityMask | InPlainText | InComment | InDoctype | InServer | InProcessingInstruction | StartTag); } private: static const int EntityShift = 4; @@ -267,7 +311,9 @@ private: DiscardLF = 1 << 20, // FIXME: should clarify difference between skip and discard AllowYield = 1 << 21, LoadingExtScript = 1 << 22, - ForceSynchronous = 1 << 23 + ForceSynchronous = 1 << 23, + InIFrame = 1 << 24, + InDoctype = 1 << 25 }; void setBit(StateBits bit, bool value) @@ -283,13 +329,17 @@ private: }; State m_state; + + DoctypeToken m_doctypeToken; + int m_doctypeSearchCount; + int m_doctypeSecondarySearchCount; bool brokenServer; // Name of an attribute that we just scanned. AtomicString attrName; - // Used to store the code of a srcipting sequence + // Used to store the code of a scripting sequence UChar* scriptCode; // Size of the script sequenze stored in @ref #scriptCode int scriptCodeSize; @@ -300,14 +350,14 @@ private: // Stores characters if we are scanning for a string like "</script>" UChar searchBuffer[10]; + // Counts where we are in the string we are scanning for int searchCount; - // The string we are searching for - const UChar* searchFor; // the stopper string const char* searchStopper; // the stopper len int searchStopperLen; + // if no more data is coming, just parse what we have (including ext scripts that // may be still downloading) and finish bool noMoreData; @@ -324,7 +374,7 @@ private: // true if we are executing a script while parsing a document. This causes the parsing of // the output of the script to be postponed until after the script has finished executing int m_executingScript; - DeprecatedPtrQueue<CachedScript> pendingScripts; + Deque<CachedResourceHandle<CachedScript> > pendingScripts; RefPtr<Node> scriptNode; bool m_requestingScript; @@ -339,6 +389,9 @@ private: int scriptStartLineno; int tagStartLineno; + double m_tokenizerTimeDelay; + int m_tokenizerChunkSize; + // The timer for continued processing. Timer<HTMLTokenizer> m_timer; @@ -355,9 +408,7 @@ private: bool inWrite; bool m_fragment; -#ifdef ANDROID_PRELOAD_CHANGES OwnPtr<PreloadScanner> m_preloadScanner; -#endif }; void parseHTMLDocumentFragment(const String&, DocumentFragment*); diff --git a/WebCore/html/HTMLUListElement.cpp b/WebCore/html/HTMLUListElement.cpp index b1d1125..4557294 100644 --- a/WebCore/html/HTMLUListElement.cpp +++ b/WebCore/html/HTMLUListElement.cpp @@ -48,7 +48,7 @@ bool HTMLUListElement::mapToEntry(const QualifiedName& attrName, MappedAttribute void HTMLUListElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == typeAttr) - addCSSProperty(attr, CSS_PROP_LIST_STYLE_TYPE, attr->value()); + addCSSProperty(attr, CSSPropertyListStyleType, attr->value()); else HTMLElement::parseMappedAttribute(attr); } diff --git a/WebCore/html/HTMLVideoElement.cpp b/WebCore/html/HTMLVideoElement.cpp index 4a2b2c9..2fb4a19 100644 --- a/WebCore/html/HTMLVideoElement.cpp +++ b/WebCore/html/HTMLVideoElement.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -83,7 +83,7 @@ void HTMLVideoElement::detach() m_imageLoader.clear(); } -void HTMLVideoElement::parseMappedAttribute(MappedAttribute *attr) +void HTMLVideoElement::parseMappedAttribute(MappedAttribute* attr) { const QualifiedName& attrName = attr->name(); @@ -95,52 +95,52 @@ void HTMLVideoElement::parseMappedAttribute(MappedAttribute *attr) m_imageLoader->updateFromElement(); } } else if (attrName == widthAttr) - addCSSLength(attr, CSS_PROP_WIDTH, attr->value()); + addCSSLength(attr, CSSPropertyWidth, attr->value()); else if (attrName == heightAttr) - addCSSLength(attr, CSS_PROP_HEIGHT, attr->value()); + addCSSLength(attr, CSSPropertyHeight, attr->value()); else HTMLMediaElement::parseMappedAttribute(attr); } -int HTMLVideoElement::videoWidth() const +unsigned HTMLVideoElement::videoWidth() const { if (!m_player) return 0; return m_player->naturalSize().width(); } -int HTMLVideoElement::videoHeight() const +unsigned HTMLVideoElement::videoHeight() const { if (!m_player) return 0; return m_player->naturalSize().height(); } -int HTMLVideoElement::width() const +unsigned HTMLVideoElement::width() const { bool ok; - int w = getAttribute(widthAttr).toInt(&ok); + unsigned w = getAttribute(widthAttr).string().toUInt(&ok); return ok ? w : 0; } -void HTMLVideoElement::setWidth(int value) +void HTMLVideoElement::setWidth(unsigned value) { setAttribute(widthAttr, String::number(value)); } -int HTMLVideoElement::height() const +unsigned HTMLVideoElement::height() const { bool ok; - int h = getAttribute(heightAttr).toInt(&ok); + unsigned h = getAttribute(heightAttr).string().toUInt(&ok); return ok ? h : 0; } -void HTMLVideoElement::setHeight(int value) +void HTMLVideoElement::setHeight(unsigned value) { setAttribute(heightAttr, String::number(value)); } -String HTMLVideoElement::poster() const +KURL HTMLVideoElement::poster() const { return document()->completeURL(getAttribute(posterAttr)); } @@ -150,7 +150,7 @@ void HTMLVideoElement::setPoster(const String& value) setAttribute(posterAttr, value); } -bool HTMLVideoElement::isURLAttribute(Attribute *attr) const +bool HTMLVideoElement::isURLAttribute(Attribute* attr) const { return attr->name() == posterAttr; } diff --git a/WebCore/html/HTMLVideoElement.h b/WebCore/html/HTMLVideoElement.h index 8d9be2c..e424e3d 100644 --- a/WebCore/html/HTMLVideoElement.h +++ b/WebCore/html/HTMLVideoElement.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,15 +50,15 @@ public: virtual bool isURLAttribute(Attribute*) const; virtual const QualifiedName& imageSourceAttributeName() const; - int width() const; - void setWidth(int); - int height() const; - void setHeight(int); + unsigned width() const; + void setWidth(unsigned); + unsigned height() const; + void setHeight(unsigned); - int videoWidth() const; - int videoHeight() const; + unsigned videoWidth() const; + unsigned videoHeight() const; - String poster() const; + KURL poster() const; void setPoster(const String&); void updatePosterImage(); diff --git a/WebCore/html/HTMLVideoElement.idl b/WebCore/html/HTMLVideoElement.idl index fa8aad0..c78594f 100644 --- a/WebCore/html/HTMLVideoElement.idl +++ b/WebCore/html/HTMLVideoElement.idl @@ -25,8 +25,8 @@ module html { interface [GenerateConstructor, Conditional=VIDEO] HTMLVideoElement : HTMLMediaElement { - attribute long width; - attribute long height; + attribute unsigned long width; + attribute unsigned long height; readonly attribute unsigned long videoWidth; readonly attribute unsigned long videoHeight; attribute [ConvertNullToNullString] DOMString poster; diff --git a/WebCore/html/HTMLViewSourceDocument.cpp b/WebCore/html/HTMLViewSourceDocument.cpp index 10c7a6d..7b141d1 100644 --- a/WebCore/html/HTMLViewSourceDocument.cpp +++ b/WebCore/html/HTMLViewSourceDocument.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,8 +23,9 @@ */ #include "config.h" -#include "DOMImplementation.h" #include "HTMLViewSourceDocument.h" + +#include "DOMImplementation.h" #include "HTMLTokenizer.h" #include "HTMLHtmlElement.h" #include "HTMLAnchorElement.h" @@ -38,13 +39,12 @@ #include "TextDocument.h" #include "HTMLNames.h" -namespace WebCore -{ +namespace WebCore { using namespace HTMLNames; -HTMLViewSourceDocument::HTMLViewSourceDocument(DOMImplementation* implementation, Frame* frame, const String& mimeType) - : HTMLDocument(implementation, frame) +HTMLViewSourceDocument::HTMLViewSourceDocument(Frame* frame, const String& mimeType) + : HTMLDocument(frame) , m_type(mimeType) , m_current(0) , m_tbody(0) @@ -55,30 +55,29 @@ HTMLViewSourceDocument::HTMLViewSourceDocument(DOMImplementation* implementation Tokenizer* HTMLViewSourceDocument::createTokenizer() { if (implementation()->isTextMIMEType(m_type)) - return new TextTokenizer(this); + return createTextTokenizer(this); return new HTMLTokenizer(this); } void HTMLViewSourceDocument::createContainingTable() { - Element* html = new HTMLHtmlElement(this); + RefPtr<Element> html = new HTMLHtmlElement(this); addChild(html); html->attach(); - Element* body = new HTMLBodyElement(this); + RefPtr<Element> body = new HTMLBodyElement(this); html->addChild(body); body->attach(); // Create a line gutter div that can be used to make sure the gutter extends down the height of the whole // document. - Element* div = new HTMLDivElement(this); - Attribute* a = new MappedAttribute(classAttr, "webkit-line-gutter-backdrop"); - NamedMappedAttrMap* attrs = new NamedMappedAttrMap(0); - attrs->insertAttribute(a, true); - div->setAttributeMap(attrs); + RefPtr<Element> div = new HTMLDivElement(this); + RefPtr<NamedMappedAttrMap> attrs = NamedMappedAttrMap::create(); + attrs->insertAttribute(MappedAttribute::create(classAttr, "webkit-line-gutter-backdrop"), true); + div->setAttributeMap(attrs.release()); body->addChild(div); div->attach(); - Element* table = new HTMLTableElement(this); + RefPtr<Element> table = new HTMLTableElement(this); body->addChild(table); table->attach(); m_tbody = new HTMLTableSectionElement(tbodyTag, this); @@ -108,9 +107,7 @@ void HTMLViewSourceDocument::addViewSourceToken(Token* token) } } else { // Handle the tag. - bool doctype = token->tagName.startsWith("!DOCTYPE", false); - - String classNameStr = doctype ? "webkit-html-doctype" : "webkit-html-tag"; + String classNameStr = "webkit-html-tag"; m_current = addSpanWithClassName(classNameStr); String text = "<"; @@ -128,11 +125,11 @@ void HTMLViewSourceDocument::addViewSourceToken(Token* token) unsigned size = guide->size(); unsigned begin = 0; unsigned currAttr = 0; - Attribute* attr = 0; + RefPtr<Attribute> attr = 0; for (unsigned i = 0; i < size; i++) { if (guide->at(i) == 'a' || guide->at(i) == 'x' || guide->at(i) == 'v') { // Add in the string. - addText(String((UChar*)(guide->data()) + begin, i - begin), classNameStr); + addText(String(static_cast<UChar*>(guide->data()) + begin, i - begin), classNameStr); begin = i + 1; @@ -145,28 +142,21 @@ void HTMLViewSourceDocument::addViewSourceToken(Token* token) if (attr) { if (guide->at(i) == 'a') { String name = attr->name().toString(); - if (doctype) - addText(name, "webkit-html-doctype"); - else { - m_current = addSpanWithClassName("webkit-html-attribute-name"); - addText(name, "webkit-html-attribute-name"); - if (m_current != m_tbody) - m_current = static_cast<Element*>(m_current->parent()); - } + + m_current = addSpanWithClassName("webkit-html-attribute-name"); + addText(name, "webkit-html-attribute-name"); + if (m_current != m_tbody) + m_current = static_cast<Element*>(m_current->parent()); } else { - String value = attr->value().domString(); - if (doctype) - addText(value, "webkit-html-doctype"); - else { - // FIXME: XML could use namespace prefixes and confuse us. - if (equalIgnoringCase(attr->name().localName(), "src") || equalIgnoringCase(attr->name().localName(), "href")) - m_current = addLink(value, equalIgnoringCase(token->tagName, "a")); - else - m_current = addSpanWithClassName("webkit-html-attribute-value"); - addText(value, "webkit-html-attribute-value"); - if (m_current != m_tbody) - m_current = static_cast<Element*>(m_current->parent()); - } + const String& value = attr->value().string(); + // FIXME: XML could use namespace prefixes and confuse us. + if (equalIgnoringCase(attr->name().localName(), "src") || equalIgnoringCase(attr->name().localName(), "href")) + m_current = addLink(value, equalIgnoringCase(token->tagName, "a")); + else + m_current = addSpanWithClassName("webkit-html-attribute-value"); + addText(value, "webkit-html-attribute-value"); + if (m_current != m_tbody) + m_current = static_cast<Element*>(m_current->parent()); } } } @@ -174,7 +164,7 @@ void HTMLViewSourceDocument::addViewSourceToken(Token* token) // Add in any string that might be left. if (begin < size) - addText(String((UChar*)(guide->data()) + begin, size - begin), classNameStr); + addText(String(static_cast<UChar*>(guide->data()) + begin, size - begin), classNameStr); // Add in the end tag. addText(">", classNameStr); @@ -184,6 +174,17 @@ void HTMLViewSourceDocument::addViewSourceToken(Token* token) } } +void HTMLViewSourceDocument::addViewSourceDoctypeToken(DoctypeToken* doctypeToken) +{ + if (!m_current) + createContainingTable(); + m_current = addSpanWithClassName("webkit-html-doctype"); + String text = "<"; + text += String::adopt(doctypeToken->m_source); + text += ">"; + addText(text, "webkit-html-doctype"); +} + Element* HTMLViewSourceDocument::addSpanWithClassName(const String& className) { if (m_current == m_tbody) { @@ -192,10 +193,9 @@ Element* HTMLViewSourceDocument::addSpanWithClassName(const String& className) } Element* span = new HTMLElement(spanTag, this); - Attribute* a = new MappedAttribute(classAttr, className); - NamedMappedAttrMap* attrs = new NamedMappedAttrMap(0); - attrs->insertAttribute(a, true); - span->setAttributeMap(attrs); + RefPtr<NamedMappedAttrMap> attrs = NamedMappedAttrMap::create(); + attrs->insertAttribute(MappedAttribute::create(classAttr, className), true); + span->setAttributeMap(attrs.release()); m_current->addChild(span); span->attach(); return span; @@ -204,32 +204,29 @@ Element* HTMLViewSourceDocument::addSpanWithClassName(const String& className) void HTMLViewSourceDocument::addLine(const String& className) { // Create a table row. - Element* trow = new HTMLTableRowElement(this); + RefPtr<Element> trow = new HTMLTableRowElement(this); m_tbody->addChild(trow); trow->attach(); // Create a cell that will hold the line number (it is generated in the stylesheet using counters). Element* td = new HTMLTableCellElement(tdTag, this); - Attribute* classNameAttr = new MappedAttribute(classAttr, "webkit-line-number"); - NamedMappedAttrMap* attrs = new NamedMappedAttrMap(0); - attrs->insertAttribute(classNameAttr, true); - - td->setAttributeMap(attrs); + RefPtr<NamedMappedAttrMap> attrs = NamedMappedAttrMap::create(); + attrs->insertAttribute(MappedAttribute::create(classAttr, "webkit-line-number"), true); + td->setAttributeMap(attrs.release()); trow->addChild(td); td->attach(); // Create a second cell for the line contents td = new HTMLTableCellElement(tdTag, this); - classNameAttr = new MappedAttribute(classAttr, "webkit-line-content"); - attrs = new NamedMappedAttrMap(0); - attrs->insertAttribute(classNameAttr, true); - td->setAttributeMap(attrs); + attrs = NamedMappedAttrMap::create(); + attrs->insertAttribute(MappedAttribute::create(classAttr, "webkit-line-content"), true); + td->setAttributeMap(attrs.release()); trow->addChild(td); td->attach(); m_current = m_td = td; #ifdef DEBUG_LINE_NUMBERS - Text* lineNumberText = new Text(this, String::number(tokenizer()->lineNumber() + 1) + " "); + RefPtr<Text> lineNumberText = new Text(this, String::number(tokenizer()->lineNumber() + 1) + " "); td->addChild(lineNumberText); lineNumberText->attach(); #endif @@ -248,7 +245,8 @@ void HTMLViewSourceDocument::addText(const String& text, const String& className return; // Add in the content, splitting on newlines. - Vector<String> lines = text.split('\n', true); + Vector<String> lines; + text.split('\n', true, lines); unsigned size = lines.size(); for (unsigned i = 0; i < size; i++) { String substring = lines[i]; @@ -259,7 +257,7 @@ void HTMLViewSourceDocument::addText(const String& text, const String& className } if (m_current == m_tbody) addLine(className); - Text* t = new Text(this, substring); + RefPtr<Text> t = new Text(this, substring); m_current->addChild(t); t->attach(); if (i < size - 1) @@ -278,19 +276,16 @@ Element* HTMLViewSourceDocument::addLink(const String& url, bool isAnchor) // Now create a link for the attribute value instead of a span. Element* anchor = new HTMLAnchorElement(aTag, this); - NamedMappedAttrMap* attrs = new NamedMappedAttrMap(0); - String classValueStr("webkit-html-attribute-value"); + RefPtr<NamedMappedAttrMap> attrs = NamedMappedAttrMap::create(); + const char* classValue; if (isAnchor) - classValueStr += " webkit-html-external-link"; + classValue = "webkit-html-attribute-value webkit-html-external-link"; else - classValueStr += " webkit-html-resource-link"; - Attribute* classAttribute = new MappedAttribute(classAttr, classValueStr); - attrs->insertAttribute(classAttribute, true); - Attribute* targetAttribute = new MappedAttribute(targetAttr, "_blank"); - attrs->insertAttribute(targetAttribute, true); - Attribute* hrefAttribute = new MappedAttribute(hrefAttr, url); - attrs->insertAttribute(hrefAttribute, true); - anchor->setAttributeMap(attrs); + 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); + anchor->setAttributeMap(attrs.release()); m_current->addChild(anchor); anchor->attach(); return anchor; diff --git a/WebCore/html/HTMLViewSourceDocument.h b/WebCore/html/HTMLViewSourceDocument.h index efbbf9e..99c1ee4 100644 --- a/WebCore/html/HTMLViewSourceDocument.h +++ b/WebCore/html/HTMLViewSourceDocument.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -21,6 +21,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #ifndef HTMLViewSourceDocument_h #define HTMLViewSourceDocument_h @@ -28,26 +29,31 @@ namespace WebCore { +class DoctypeToken; class Token; -class HTMLViewSourceDocument : public HTMLDocument -{ +class HTMLViewSourceDocument : public HTMLDocument { public: - HTMLViewSourceDocument(DOMImplementation*, Frame*, const String& mimeType); + static PassRefPtr<HTMLViewSourceDocument> create(Frame* frame, const String& mimeType) + { + return new HTMLViewSourceDocument(frame, mimeType); + } virtual Tokenizer* createTokenizer(); void addViewSourceToken(Token*); // Used by the HTML tokenizer. void addViewSourceText(const String&); // Used by the plaintext tokenizer. - + void addViewSourceDoctypeToken(DoctypeToken*); + private: + HTMLViewSourceDocument(Frame*, const String& mimeType); + void createContainingTable(); Element* addSpanWithClassName(const String&); void addLine(const String& className); void addText(const String& text, const String& className); Element* addLink(const String& url, bool isAnchor); -private: String m_type; Element* m_current; Element* m_tbody; diff --git a/WebCore/html/ImageData.cpp b/WebCore/html/ImageData.cpp new file mode 100644 index 0000000..3653031 --- /dev/null +++ b/WebCore/html/ImageData.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ImageData.h" + +#include "CanvasPixelArray.h" + +namespace WebCore { + +PassRefPtr<ImageData> ImageData::create(unsigned width, unsigned height) +{ + return adoptRef(new ImageData(width, height)); +} + +ImageData::ImageData(unsigned width, unsigned height) + : m_width(width) + , m_height(height) + , m_data(CanvasPixelArray::create(width * height * 4)) +{ +} + +} + diff --git a/WebCore/html/ImageData.h b/WebCore/html/ImageData.h new file mode 100644 index 0000000..21af1f9 --- /dev/null +++ b/WebCore/html/ImageData.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ImageData_h +#define ImageData_h + +#include "CanvasPixelArray.h" +#include <wtf/RefCounted.h> + +namespace WebCore { + + class ImageData : public RefCounted<ImageData> { + public: + static PassRefPtr<ImageData> create(unsigned width, unsigned height); + + unsigned width() const { return m_width; } + unsigned height() const { return m_height; } + CanvasPixelArray* data() const { return m_data.get(); } + + private: + ImageData(unsigned width, unsigned height); + unsigned m_width; + unsigned m_height; + RefPtr<CanvasPixelArray> m_data; + }; + +} // namespace WebCore + +#endif // ImageData_h diff --git a/WebCore/html/ImageData.idl b/WebCore/html/ImageData.idl new file mode 100644 index 0000000..246632f --- /dev/null +++ b/WebCore/html/ImageData.idl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module html { + + interface [ + GenerateConstructor, + GenerateToJS + ] ImageData { + readonly attribute long width; + readonly attribute long height; + readonly attribute CanvasPixelArray data; + }; + +} diff --git a/WebCore/html/MediaError.h b/WebCore/html/MediaError.h index 33a2a70..fbf375f 100644 --- a/WebCore/html/MediaError.h +++ b/WebCore/html/MediaError.h @@ -36,10 +36,13 @@ class MediaError : public RefCounted<MediaError> { public: enum Code { MEDIA_ERR_ABORTED = 1, MEDIA_ERR_NETWORK, MEDIA_ERR_DECODE }; - MediaError(Code code) { m_code = code; } + static PassRefPtr<MediaError> create(Code code) { return adoptRef(new MediaError(code)); } + Code code() const { return m_code; } private: + MediaError(Code code) : m_code(code) { } + Code m_code; }; diff --git a/WebCore/html/PreloadScanner.cpp b/WebCore/html/PreloadScanner.cpp index f7fb27d..1580230 100644 --- a/WebCore/html/PreloadScanner.cpp +++ b/WebCore/html/PreloadScanner.cpp @@ -1,37 +1,32 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" -#ifdef ANDROID_PRELOAD_CHANGES #include "PreloadScanner.h" #include "AtomicString.h" -#include "Cache.h" #include "CachedCSSStyleSheet.h" #include "CachedImage.h" #include "CachedResource.h" @@ -46,6 +41,7 @@ #include "HTMLLinkElement.h" #include "HTMLNames.h" #include "SystemTime.h" +#include <wtf/unicode/Unicode.h> #ifdef __GNUC__ // The main tokenizer includes this too so we are getting two copies of the data. However, this way the code gets inlined. @@ -61,6 +57,8 @@ const struct Entity* findEntity(register const char* str, register unsigned int #define PRELOAD_DEBUG 0 +using namespace WTF; + namespace WebCore { using namespace HTMLNames; @@ -123,7 +121,7 @@ void PreloadScanner::reset() m_cssRuleValue.clear(); } -bool PreloadScanner::inBody() const +bool PreloadScanner::scanningBody() const { return m_document->body() || m_bodySeen; } @@ -352,11 +350,13 @@ void PreloadScanner::tokenize(const SegmentedString& source) m_state = CloseTagOpen; else if (cc >= 'A' && cc <= 'Z') { m_tagName.clear(); + m_charset = String(); m_tagName.append(cc + 0x20); m_closeTag = false; m_state = TagName; } else if (cc >= 'a' && cc <= 'z') { m_tagName.clear(); + m_charset = String(); m_tagName.append(cc); m_closeTag = false; m_state = TagName; @@ -382,7 +382,7 @@ void PreloadScanner::tokenize(const SegmentedString& source) UChar tmpChar = 0; bool match = true; for (unsigned n = 0; n < m_lastStartTag.length() + 1; n++) { - tmpChar = u_tolower(*m_source); + tmpChar = Unicode::toLower(*m_source); if (n < m_lastStartTag.length() && tmpChar != m_lastStartTag[n]) match = false; tmpString.append(tmpChar); @@ -396,11 +396,13 @@ void PreloadScanner::tokenize(const SegmentedString& source) } if (cc >= 'A' && cc <= 'Z') { m_tagName.clear(); + m_charset = String(); m_tagName.append(cc + 0x20); m_closeTag = true; m_state = TagName; } else if (cc >= 'a' && cc <= 'z') { m_tagName.clear(); + m_charset = String(); m_tagName.append(cc); m_closeTag = true; m_state = TagName; @@ -698,8 +700,9 @@ void PreloadScanner::processAttribute() bool styleSheet = false; bool alternate = false; bool icon = false; - HTMLLinkElement::tokenizeRelAttribute(value, styleSheet, alternate, icon); - m_linkIsStyleSheet = styleSheet && !alternate && !icon; + bool dnsPrefetch = false; + HTMLLinkElement::tokenizeRelAttribute(value, styleSheet, alternate, icon, dnsPrefetch); + m_linkIsStyleSheet = styleSheet && !alternate && !icon && !dnsPrefetch; } else if (attribute == charsetAttr) m_charset = value; } @@ -823,11 +826,11 @@ void PreloadScanner::emitTag() } if (tag == scriptTag) - m_document->docLoader()->preload(CachedResource::Script, m_urlToLoad, m_charset, inBody()); + m_document->docLoader()->preload(CachedResource::Script, m_urlToLoad, m_charset, scanningBody()); else if (tag == imgTag) - m_document->docLoader()->preload(CachedResource::ImageResource, m_urlToLoad, String(), inBody()); + m_document->docLoader()->preload(CachedResource::ImageResource, m_urlToLoad, String(), scanningBody()); else if (tag == linkTag && m_linkIsStyleSheet) - m_document->docLoader()->preload(CachedResource::CSSStyleSheet, m_urlToLoad, m_charset, inBody()); + m_document->docLoader()->preload(CachedResource::CSSStyleSheet, m_urlToLoad, m_charset, scanningBody()); m_urlToLoad = String(); m_charset = String(); @@ -837,15 +840,14 @@ void PreloadScanner::emitTag() void PreloadScanner::emitCSSRule() { String rule(m_cssRule.data(), m_cssRule.size()); - if (rule.lower() == "import" && !m_cssRuleValue.isEmpty()) { + if (equalIgnoringCase(rule, "import") && !m_cssRuleValue.isEmpty()) { String value(m_cssRuleValue.data(), m_cssRuleValue.size()); String url = parseURL(value); if (!url.isEmpty()) - m_document->docLoader()->preload(CachedResource::CSSStyleSheet, url, String(), inBody()); + m_document->docLoader()->preload(CachedResource::CSSStyleSheet, url, String(), scanningBody()); } m_cssRule.clear(); m_cssRuleValue.clear(); } } -#endif //ANDROID_PRELOAD_CHANGES diff --git a/WebCore/html/PreloadScanner.h b/WebCore/html/PreloadScanner.h index 8ef5d1a..b5908cf 100644 --- a/WebCore/html/PreloadScanner.h +++ b/WebCore/html/PreloadScanner.h @@ -1,32 +1,28 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #ifndef PreloadScanner_h #define PreloadScanner_h @@ -50,7 +46,7 @@ namespace WebCore { void end(); bool inProgress() const { return m_inProgress; } - bool inBody() const; + bool scanningBody() const; static unsigned consumeEntity(SegmentedString&, bool& notEnoughCharacters); diff --git a/WebCore/html/TextMetrics.h b/WebCore/html/TextMetrics.h new file mode 100644 index 0000000..34a3378 --- /dev/null +++ b/WebCore/html/TextMetrics.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TextMetrics_h +#define TextMetrics_h + +#include <wtf/RefCounted.h> + +namespace WebCore { + +class TextMetrics : public RefCounted<TextMetrics> { +public: + static PassRefPtr<TextMetrics> create() { return adoptRef(new TextMetrics); } + + unsigned width() const { return m_width; } + void setWidth(float w) { m_width = w; } + +private: + TextMetrics() + : m_width(0) + { } + + float m_width; +}; + +} // namespace WebCore + +#endif // TextMetrics_h diff --git a/WebCore/html/TextMetrics.idl b/WebCore/html/TextMetrics.idl new file mode 100644 index 0000000..dc88716 --- /dev/null +++ b/WebCore/html/TextMetrics.idl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module html { + + interface [ + GenerateConstructor + ] TextMetrics { + readonly attribute float width; + }; + +} diff --git a/WebCore/html/TimeRanges.h b/WebCore/html/TimeRanges.h index 16b0c25..eb54f6b 100644 --- a/WebCore/html/TimeRanges.h +++ b/WebCore/html/TimeRanges.h @@ -27,6 +27,7 @@ #define TimeRanges_h #include "ExceptionCode.h" +#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> @@ -34,9 +35,15 @@ namespace WebCore { class TimeRanges : public RefCounted<TimeRanges> { public: - TimeRanges() { } - TimeRanges(float start, float end); - + static PassRefPtr<TimeRanges> create() + { + return adoptRef(new TimeRanges); + } + static PassRefPtr<TimeRanges> create(float start, float end) + { + return adoptRef(new TimeRanges(start, end)); + } + unsigned length() const { return m_ranges.size(); } float start(unsigned index, ExceptionCode&) const; float end(unsigned index, ExceptionCode&) const; @@ -46,6 +53,9 @@ public: bool contain(float time) const; private: + TimeRanges() { } + TimeRanges(float start, float end); + struct Range { Range() { } Range(float start, float end) { diff --git a/WebCore/html/VoidCallback.h b/WebCore/html/VoidCallback.h index 478e2fc..c220411 100644 --- a/WebCore/html/VoidCallback.h +++ b/WebCore/html/VoidCallback.h @@ -32,10 +32,12 @@ namespace WebCore { class VoidCallback : public RefCounted<VoidCallback> { public: - VoidCallback() { } virtual ~VoidCallback() { } virtual void handleEvent() = 0; + +protected: + VoidCallback() {} }; } // namespace WebCore |