diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
commit | ad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (patch) | |
tree | b34b0daceb7c8e7fdde4b4ec43650ab7caadb0a9 /Source/WebCore/html | |
parent | 03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (diff) | |
download | qtwebkit-ad0d549d4cc13433f77c1ac8f0ab379c83d93f28.tar.gz |
Imported WebKit commit bb52bf3c0119e8a128cd93afe5572413a8617de9 (http://svn.webkit.org/repository/webkit/trunk@108790)
Diffstat (limited to 'Source/WebCore/html')
205 files changed, 2594 insertions, 1572 deletions
diff --git a/Source/WebCore/html/BaseButtonInputType.cpp b/Source/WebCore/html/BaseButtonInputType.cpp index 11546eddd..9a1616fce 100644 --- a/Source/WebCore/html/BaseButtonInputType.cpp +++ b/Source/WebCore/html/BaseButtonInputType.cpp @@ -100,7 +100,7 @@ bool BaseButtonInputType::storesValueSeparateFromAttribute() return false; } -void BaseButtonInputType::setValue(const String& sanitizedValue, bool, bool) +void BaseButtonInputType::setValue(const String& sanitizedValue, bool, TextFieldEventBehavior) { element()->setAttribute(valueAttr, sanitizedValue); } diff --git a/Source/WebCore/html/BaseButtonInputType.h b/Source/WebCore/html/BaseButtonInputType.h index dabc27cac..1b7543c05 100644 --- a/Source/WebCore/html/BaseButtonInputType.h +++ b/Source/WebCore/html/BaseButtonInputType.h @@ -48,7 +48,7 @@ private: virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) const OVERRIDE; virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; virtual bool storesValueSeparateFromAttribute() OVERRIDE; - virtual void setValue(const String&, bool, bool) OVERRIDE; + virtual void setValue(const String&, bool, TextFieldEventBehavior) OVERRIDE; }; } // namespace WebCore diff --git a/Source/WebCore/html/BaseCheckableInputType.cpp b/Source/WebCore/html/BaseCheckableInputType.cpp index 70f539d80..ff28dae36 100644 --- a/Source/WebCore/html/BaseCheckableInputType.cpp +++ b/Source/WebCore/html/BaseCheckableInputType.cpp @@ -104,7 +104,7 @@ bool BaseCheckableInputType::storesValueSeparateFromAttribute() return false; } -void BaseCheckableInputType::setValue(const String& sanitizedValue, bool, bool) +void BaseCheckableInputType::setValue(const String& sanitizedValue, bool, TextFieldEventBehavior) { element()->setAttribute(valueAttr, sanitizedValue); } diff --git a/Source/WebCore/html/BaseCheckableInputType.h b/Source/WebCore/html/BaseCheckableInputType.h index 2c2c4ad3c..4211ad521 100644 --- a/Source/WebCore/html/BaseCheckableInputType.h +++ b/Source/WebCore/html/BaseCheckableInputType.h @@ -50,7 +50,7 @@ private: virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; virtual String fallbackValue() const OVERRIDE; virtual bool storesValueSeparateFromAttribute() OVERRIDE; - virtual void setValue(const String&, bool, bool) OVERRIDE; + virtual void setValue(const String&, bool, TextFieldEventBehavior) OVERRIDE; virtual bool isCheckable() OVERRIDE; }; diff --git a/Source/WebCore/html/BaseDateAndTimeInputType.cpp b/Source/WebCore/html/BaseDateAndTimeInputType.cpp index 46366729f..2904f2e85 100644 --- a/Source/WebCore/html/BaseDateAndTimeInputType.cpp +++ b/Source/WebCore/html/BaseDateAndTimeInputType.cpp @@ -65,9 +65,9 @@ double BaseDateAndTimeInputType::valueAsNumber() const return parseToDouble(element()->value(), numeric_limits<double>::quiet_NaN()); } -void BaseDateAndTimeInputType::setValueAsNumber(double newValue, bool sendChangeEvent, ExceptionCode&) const +void BaseDateAndTimeInputType::setValueAsNumber(double newValue, TextFieldEventBehavior eventBehavior, ExceptionCode&) const { - element()->setValue(serialize(newValue), sendChangeEvent); + element()->setValue(serialize(newValue), eventBehavior); } bool BaseDateAndTimeInputType::typeMismatchFor(const String& value) const diff --git a/Source/WebCore/html/BaseDateAndTimeInputType.h b/Source/WebCore/html/BaseDateAndTimeInputType.h index 46c0c9d8d..e34535060 100644 --- a/Source/WebCore/html/BaseDateAndTimeInputType.h +++ b/Source/WebCore/html/BaseDateAndTimeInputType.h @@ -52,7 +52,7 @@ private: virtual double valueAsDate() const OVERRIDE; virtual void setValueAsDate(double, ExceptionCode&) const OVERRIDE; virtual double valueAsNumber() const OVERRIDE; - virtual void setValueAsNumber(double, bool sendChangeEvent, ExceptionCode&) const OVERRIDE; + virtual void setValueAsNumber(double, TextFieldEventBehavior, ExceptionCode&) const OVERRIDE; virtual bool typeMismatchFor(const String&) const OVERRIDE; virtual bool typeMismatch() const OVERRIDE; virtual bool rangeUnderflow(const String&) const OVERRIDE; diff --git a/Source/WebCore/html/CheckboxInputType.cpp b/Source/WebCore/html/CheckboxInputType.cpp index 4e9663443..02967bbf4 100644 --- a/Source/WebCore/html/CheckboxInputType.cpp +++ b/Source/WebCore/html/CheckboxInputType.cpp @@ -80,7 +80,7 @@ PassOwnPtr<ClickHandlingState> CheckboxInputType::willDispatchClick() if (state->indeterminate) element()->setIndeterminate(false); - element()->setChecked(!state->checked, true); + element()->setChecked(!state->checked, DispatchChangeEvent); return state.release(); } diff --git a/Source/WebCore/html/ColorInputType.cpp b/Source/WebCore/html/ColorInputType.cpp index 071cc3416..83647ea6a 100644 --- a/Source/WebCore/html/ColorInputType.cpp +++ b/Source/WebCore/html/ColorInputType.cpp @@ -106,6 +106,8 @@ Color ColorInputType::valueAsColor() const void ColorInputType::createShadowSubtree() { + ASSERT(element()->hasShadowRoot()); + Document* document = element()->document(); RefPtr<HTMLDivElement> wrapperElement = HTMLDivElement::create(document); wrapperElement->setShadowPseudoId("-webkit-color-swatch-wrapper"); @@ -114,15 +116,15 @@ void ColorInputType::createShadowSubtree() ExceptionCode ec = 0; wrapperElement->appendChild(colorSwatch.release(), ec); ASSERT(!ec); - element()->ensureShadowRoot()->appendChild(wrapperElement.release(), ec); + element()->shadowRootList()->oldestShadowRoot()->appendChild(wrapperElement.release(), ec); ASSERT(!ec); updateColorSwatch(); } -void ColorInputType::setValue(const String& value, bool valueChanged, bool sendChangeEvent) +void ColorInputType::setValue(const String& value, bool valueChanged, TextFieldEventBehavior eventBehavior) { - InputType::setValue(value, valueChanged, sendChangeEvent); + InputType::setValue(value, valueChanged, eventBehavior); if (!valueChanged) return; @@ -178,12 +180,12 @@ void ColorInputType::updateColorSwatch() if (!colorSwatch) return; - colorSwatch->ensureInlineStyleDecl()->setProperty(CSSPropertyBackgroundColor, element()->value(), false); + colorSwatch->setInlineStyleProperty(CSSPropertyBackgroundColor, element()->value(), false); } HTMLElement* ColorInputType::shadowColorSwatch() const { - ShadowRoot* shadow = element()->shadowRoot(); + ShadowRoot* shadow = element()->shadowRootList()->oldestShadowRoot(); return shadow ? toHTMLElement(shadow->firstChild()->firstChild()) : 0; } diff --git a/Source/WebCore/html/ColorInputType.h b/Source/WebCore/html/ColorInputType.h index 3e064bd44..f92b91ced 100644 --- a/Source/WebCore/html/ColorInputType.h +++ b/Source/WebCore/html/ColorInputType.h @@ -55,7 +55,7 @@ private: virtual String fallbackValue() const OVERRIDE; virtual String sanitizeValue(const String&) const OVERRIDE; virtual void createShadowSubtree() OVERRIDE; - virtual void setValue(const String&, bool valueChanged, bool sendChangeEvent) OVERRIDE; + virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior) OVERRIDE; virtual void handleDOMActivateEvent(Event*) OVERRIDE; virtual void detach() OVERRIDE; diff --git a/Source/WebCore/html/DOMFormData.idl b/Source/WebCore/html/DOMFormData.idl index 73ac211e1..4bab556be 100644 --- a/Source/WebCore/html/DOMFormData.idl +++ b/Source/WebCore/html/DOMFormData.idl @@ -33,13 +33,14 @@ module html { interface [ CustomConstructor, JSGenerateToNativeObject, - JSGenerateToJS + JSGenerateToJSObject, + InterfaceName=FormData ] DOMFormData { // void append(DOMString name, DOMString value); // void append(DOMString name, Blob value, optional DOMString filename); - [Custom] void append(in [Optional=CallWithDefaultValue] DOMString name, - in [Optional=CallWithDefaultValue] DOMString value, - in [Optional=CallWithDefaultValue] DOMString filename); + [Custom] void append(in [Optional=DefaultIsUndefined] DOMString name, + in [Optional=DefaultIsUndefined] DOMString value, + in [Optional=DefaultIsUndefined] DOMString filename); }; } diff --git a/Source/WebCore/html/DOMSettableTokenList.idl b/Source/WebCore/html/DOMSettableTokenList.idl index f0646e5a0..93bf67f69 100644 --- a/Source/WebCore/html/DOMSettableTokenList.idl +++ b/Source/WebCore/html/DOMSettableTokenList.idl @@ -26,7 +26,7 @@ module core { interface [ IndexedGetter, - JSGenerateToJS + JSGenerateToJSObject ] DOMSettableTokenList : DOMTokenList { attribute DOMString value; }; diff --git a/Source/WebCore/html/DOMTokenList.idl b/Source/WebCore/html/DOMTokenList.idl index 88169acb9..55b636f7d 100644 --- a/Source/WebCore/html/DOMTokenList.idl +++ b/Source/WebCore/html/DOMTokenList.idl @@ -26,10 +26,11 @@ module core { interface [ JSGenerateIsReachable=ImplElementRoot, - IndexedGetter + IndexedGetter, + V8CustomToJSObject ] DOMTokenList { readonly attribute unsigned long length; - [ConvertNullStringTo=Null] DOMString item(in unsigned long index); + [TreatReturnedNullStringAs=Null] DOMString item(in unsigned long index); boolean contains(in DOMString token) raises(DOMException); void add(in DOMString token) raises(DOMException); void remove(in DOMString token) raises(DOMException); diff --git a/Source/WebCore/html/DOMURL.cpp b/Source/WebCore/html/DOMURL.cpp index 086bf778c..36a401a22 100644 --- a/Source/WebCore/html/DOMURL.cpp +++ b/Source/WebCore/html/DOMURL.cpp @@ -34,6 +34,7 @@ #include "Blob.h" #include "BlobURL.h" #include "KURL.h" +#include "MemoryCache.h" #include "PublicURLManager.h" #include "ScriptExecutionContext.h" #include "SecurityOrigin.h" @@ -89,6 +90,8 @@ void DOMURL::revokeObjectURL(ScriptExecutionContext* scriptExecutionContext, con return; KURL url(KURL(), urlString); + if (CachedResource* resource = memoryCache()->resourceForURL(url)) + memoryCache()->remove(resource); HashSet<String>& blobURLs = scriptExecutionContext->publicURLManager().blobURLs(); if (blobURLs.contains(url.string())) { diff --git a/Source/WebCore/html/DOMURL.idl b/Source/WebCore/html/DOMURL.idl index 4f9722df3..e929ca86f 100644 --- a/Source/WebCore/html/DOMURL.idl +++ b/Source/WebCore/html/DOMURL.idl @@ -29,13 +29,13 @@ module html { Conditional=BLOB, Constructor, JSGenerateToNativeObject, - JSGenerateToJS, + JSGenerateToJSObject, JSNoStaticTables ] DOMURL { #if defined(ENABLE_MEDIA_STREAM) && ENABLE_MEDIA_STREAM - static [CallWith=ScriptExecutionContext,ConvertNullStringTo=Undefined] DOMString createObjectURL(in MediaStream stream); + static [CallWith=ScriptExecutionContext,TreatReturnedNullStringAs=Undefined] DOMString createObjectURL(in MediaStream stream); #endif - static [CallWith=ScriptExecutionContext,ConvertNullStringTo=Undefined] DOMString createObjectURL(in Blob blob); + static [CallWith=ScriptExecutionContext,TreatReturnedNullStringAs=Undefined] DOMString createObjectURL(in Blob blob); static [CallWith=ScriptExecutionContext] void revokeObjectURL(in DOMString url); }; } diff --git a/Source/WebCore/html/DOMWindowHTML.idl b/Source/WebCore/html/DOMWindowHTML.idl new file mode 100644 index 000000000..889c3a00e --- /dev/null +++ b/Source/WebCore/html/DOMWindowHTML.idl @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2012 Google 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. + */ + +module window { + + // FIXME: Most of this could/should be generated from make_names.pl/HTMLNames.in + // to reduce the chance that we forget a constructor when adding a new element. + interface [ + Supplemental=DOMWindow + ] DOMWindowHTML { + + attribute HTMLDocumentConstructor HTMLDocument; + attribute HTMLElementConstructor HTMLElement; + attribute HTMLAnchorElementConstructor HTMLAnchorElement; + attribute HTMLAppletElementConstructor HTMLAppletElement; + attribute HTMLAreaElementConstructor HTMLAreaElement; + attribute HTMLBRElementConstructor HTMLBRElement; + attribute HTMLBaseElementConstructor HTMLBaseElement; + attribute HTMLBaseFontElementConstructor HTMLBaseFontElement; + attribute HTMLBodyElementConstructor HTMLBodyElement; + attribute HTMLButtonElementConstructor HTMLButtonElement; + attribute HTMLCanvasElementConstructor HTMLCanvasElement; + attribute HTMLDListElementConstructor HTMLDListElement; + attribute HTMLDirectoryElementConstructor HTMLDirectoryElement; + attribute HTMLDivElementConstructor HTMLDivElement; + attribute HTMLEmbedElementConstructor HTMLEmbedElement; + attribute HTMLFieldSetElementConstructor HTMLFieldSetElement; + attribute HTMLFontElementConstructor HTMLFontElement; + attribute HTMLFormElementConstructor HTMLFormElement; + attribute HTMLFrameElementConstructor HTMLFrameElement; + attribute HTMLFrameSetElementConstructor HTMLFrameSetElement; + attribute HTMLHRElementConstructor HTMLHRElement; + attribute HTMLHeadElementConstructor HTMLHeadElement; + attribute HTMLHeadingElementConstructor HTMLHeadingElement; + attribute HTMLHtmlElementConstructor HTMLHtmlElement; + attribute HTMLIFrameElementConstructor HTMLIFrameElement; + attribute HTMLImageElementConstructor HTMLImageElement; + attribute HTMLInputElementConstructor HTMLInputElement; + attribute HTMLKeygenElementConstructor HTMLKeygenElement; + attribute HTMLLIElementConstructor HTMLLIElement; + attribute HTMLLabelElementConstructor HTMLLabelElement; + attribute HTMLLegendElementConstructor HTMLLegendElement; + attribute HTMLLinkElementConstructor HTMLLinkElement; + attribute HTMLMapElementConstructor HTMLMapElement; + attribute HTMLMarqueeElementConstructor HTMLMarqueeElement; + attribute HTMLMenuElementConstructor HTMLMenuElement; + attribute HTMLMetaElementConstructor HTMLMetaElement; +#if defined(ENABLE_METER_TAG) && ENABLE_METER_TAG + attribute HTMLMeterElementConstructor HTMLMeterElement; +#endif + attribute HTMLModElementConstructor HTMLModElement; + attribute HTMLOListElementConstructor HTMLOListElement; + attribute HTMLObjectElementConstructor HTMLObjectElement; + attribute HTMLOptGroupElementConstructor HTMLOptGroupElement; + attribute HTMLOptionElementConstructor HTMLOptionElement; + attribute HTMLOutputElementConstructor HTMLOutputElement; + attribute HTMLParagraphElementConstructor HTMLParagraphElement; + attribute HTMLParamElementConstructor HTMLParamElement; + attribute HTMLPreElementConstructor HTMLPreElement; +#if defined(ENABLE_PROGRESS_TAG) && ENABLE_PROGRESS_TAG + attribute HTMLProgressElementConstructor HTMLProgressElement; +#endif + attribute HTMLQuoteElementConstructor HTMLQuoteElement; + attribute HTMLScriptElementConstructor HTMLScriptElement; + attribute HTMLSelectElementConstructor HTMLSelectElement; + attribute HTMLSpanElementConstructor HTMLSpanElement; + attribute HTMLStyleElementConstructor HTMLStyleElement; + attribute HTMLTableCaptionElementConstructor HTMLTableCaptionElement; + attribute HTMLTableCellElementConstructor HTMLTableCellElement; + attribute HTMLTableColElementConstructor HTMLTableColElement; + attribute HTMLTableElementConstructor HTMLTableElement; + attribute HTMLTableRowElementConstructor HTMLTableRowElement; + attribute HTMLTableSectionElementConstructor HTMLTableSectionElement; + attribute HTMLTextAreaElementConstructor HTMLTextAreaElement; + attribute HTMLTitleElementConstructor HTMLTitleElement; + attribute HTMLUListElementConstructor HTMLUListElement; + + attribute HTMLCollectionConstructor HTMLCollection; + attribute HTMLAllCollectionConstructor HTMLAllCollection; + attribute [Conditional=MICRODATA] HTMLPropertiesCollectionConstructor HTMLPropertiesCollection; + attribute HTMLUnknownElementConstructor HTMLUnknownElement; + + attribute [JSCustomGetter, CustomConstructor] HTMLImageElementConstructorConstructor Image; // Usable with new operator + attribute [JSCustomGetter] HTMLOptionElementConstructorConstructor Option; // Usable with new operator + + attribute [Conditional=VIDEO_TRACK, V8EnabledAtRuntime=webkitVideoTrack] HTMLTrackElementConstructor HTMLTrackElement; + attribute [Conditional=VIDEO_TRACK, V8EnabledAtRuntime=webkitVideoTrack] TextTrackConstructor TextTrack; + attribute [Conditional=VIDEO_TRACK, V8EnabledAtRuntime=webkitVideoTrack] TextTrackCueConstructor TextTrackCue; // Usable with the new operator + attribute [Conditional=VIDEO_TRACK, V8EnabledAtRuntime=webkitVideoTrack] TextTrackCueListConstructor TextTrackCueList; + attribute [Conditional=VIDEO_TRACK, V8EnabledAtRuntime=webkitVideoTrack] TextTrackListConstructor TextTrackList; + attribute [Conditional=VIDEO_TRACK, V8EnabledAtRuntime=webkitVideoTrack] TrackEventConstructor TrackEvent; + + attribute [JSCustomGetter, Conditional=VIDEO, V8EnabledAtRuntime] HTMLAudioElementConstructorConstructor Audio; // Usable with the new operator + attribute [Conditional=VIDEO, V8EnabledAtRuntime] HTMLAudioElementConstructor HTMLAudioElement; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] HTMLMediaElementConstructor HTMLMediaElement; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] HTMLVideoElementConstructor HTMLVideoElement; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] MediaErrorConstructor MediaError; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] TimeRangesConstructor TimeRanges; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] HTMLSourceElementConstructor HTMLSourceElement; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] MediaControllerConstructor MediaController; + }; + +} diff --git a/Source/WebCore/html/FileInputType.cpp b/Source/WebCore/html/FileInputType.cpp index ea9a2ee68..5759f6741 100644 --- a/Source/WebCore/html/FileInputType.cpp +++ b/Source/WebCore/html/FileInputType.cpp @@ -36,6 +36,7 @@ #include "RenderFileUploadControl.h" #include "ScriptController.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include <wtf/PassOwnPtr.h> #include <wtf/text/StringBuilder.h> #include <wtf/text/WTFString.h> @@ -217,7 +218,7 @@ bool FileInputType::storesValueSeparateFromAttribute() return true; } -void FileInputType::setValue(const String&, bool, bool) +void FileInputType::setValue(const String&, bool, TextFieldEventBehavior) { m_fileList->clear(); m_icon.clear(); @@ -265,13 +266,15 @@ bool FileInputType::isFileUpload() const void FileInputType::createShadowSubtree() { + ASSERT(element()->hasShadowRoot()); ExceptionCode ec = 0; - element()->ensureShadowRoot()->appendChild(element()->multiple() ? UploadButtonElement::createForMultiple(element()->document()): UploadButtonElement::create(element()->document()), ec); + element()->shadowRootList()->oldestShadowRoot()->appendChild(element()->multiple() ? UploadButtonElement::createForMultiple(element()->document()): UploadButtonElement::create(element()->document()), ec); } void FileInputType::multipleAttributeChanged() { - UploadButtonElement* button = static_cast<UploadButtonElement*>(element()->ensureShadowRoot()->firstChild()); + ASSERT(element()->hasShadowRoot()); + UploadButtonElement* button = static_cast<UploadButtonElement*>(element()->shadowRootList()->oldestShadowRoot()->firstChild()); if (button) button->setValue(element()->multiple() ? fileButtonChooseMultipleFilesLabel() : fileButtonChooseFileLabel()); } diff --git a/Source/WebCore/html/FileInputType.h b/Source/WebCore/html/FileInputType.h index b5a5d196d..53575a420 100644 --- a/Source/WebCore/html/FileInputType.h +++ b/Source/WebCore/html/FileInputType.h @@ -59,7 +59,7 @@ private: virtual bool canSetValue(const String&) OVERRIDE; virtual bool getTypeSpecificValue(String&) OVERRIDE; // Checked first, before internal storage or the value attribute. virtual bool storesValueSeparateFromAttribute() OVERRIDE; - virtual void setValue(const String&, bool valueChanged, bool sendChangeEvent) OVERRIDE; + virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior) OVERRIDE; virtual void receiveDroppedFiles(const Vector<String>&) OVERRIDE; virtual Icon* icon() const OVERRIDE; virtual bool isFileUpload() const OVERRIDE; diff --git a/Source/WebCore/html/HTMLAllCollection.idl b/Source/WebCore/html/HTMLAllCollection.idl index 3068e40fd..5ceae016c 100644 --- a/Source/WebCore/html/HTMLAllCollection.idl +++ b/Source/WebCore/html/HTMLAllCollection.idl @@ -33,7 +33,7 @@ module html { JSGenerateIsReachable ] HTMLAllCollection { readonly attribute unsigned long length; - [Custom] Node item(in [Optional=CallWithDefaultValue] unsigned long index); + [Custom] Node item(in [Optional=DefaultIsUndefined] unsigned long index); [Custom] Node namedItem(in DOMString name); // FIXME: This should return an HTMLAllCollection. diff --git a/Source/WebCore/html/HTMLAnchorElement.cpp b/Source/WebCore/html/HTMLAnchorElement.cpp index 8b932b4fa..cf86b283f 100644 --- a/Source/WebCore/html/HTMLAnchorElement.cpp +++ b/Source/WebCore/html/HTMLAnchorElement.cpp @@ -293,7 +293,7 @@ void HTMLAnchorElement::setRel(const String& value) const AtomicString& HTMLAnchorElement::name() const { - return getAttribute(nameAttr); + return getNameAttribute(); } short HTMLAnchorElement::tabIndex() const @@ -489,7 +489,7 @@ void HTMLAnchorElement::sendPings(const KURL& destinationURL) if (!hasAttribute(pingAttr) || !document()->settings()->hyperlinkAuditingEnabled()) return; - SpaceSplitString pingURLs(getAttribute(pingAttr), true); + SpaceSplitString pingURLs(getAttribute(pingAttr), false); for (unsigned i = 0; i < pingURLs.size(); i++) PingLoader::sendPing(document()->frame(), document()->completeURL(pingURLs[i]), destinationURL); } diff --git a/Source/WebCore/html/HTMLAnchorElement.idl b/Source/WebCore/html/HTMLAnchorElement.idl index 3c40b73b6..7bd174c63 100644 --- a/Source/WebCore/html/HTMLAnchorElement.idl +++ b/Source/WebCore/html/HTMLAnchorElement.idl @@ -35,6 +35,10 @@ module html { attribute [Reflect] DOMString type; #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C + attribute [Reflect] DOMString accessKey; +#endif + +#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C readonly attribute DOMString hash; readonly attribute DOMString host; readonly attribute DOMString hostname; diff --git a/Source/WebCore/html/HTMLAppletElement.cpp b/Source/WebCore/html/HTMLAppletElement.cpp index df55cd901..af63d2677 100644 --- a/Source/WebCore/html/HTMLAppletElement.cpp +++ b/Source/WebCore/html/HTMLAppletElement.cpp @@ -78,7 +78,7 @@ RenderObject* HTMLAppletElement::createRenderer(RenderArena*, RenderStyle* style if (!codeBase.isNull()) args.set("codeBase", codeBase); - const AtomicString& name = document()->isHTMLDocument() ? getAttribute(nameAttr) : getIdAttribute(); + const AtomicString& name = document()->isHTMLDocument() ? getNameAttribute() : getIdAttribute(); if (!name.isNull()) args.set("name", name); const AtomicString& archive = getAttribute(archiveAttr); diff --git a/Source/WebCore/html/HTMLAppletElement.idl b/Source/WebCore/html/HTMLAppletElement.idl index 6a683d7fc..8f16a400f 100644 --- a/Source/WebCore/html/HTMLAppletElement.idl +++ b/Source/WebCore/html/HTMLAppletElement.idl @@ -22,7 +22,7 @@ module html { interface [ CustomNamedSetter, - JSCustomGetOwnPropertySlotDelegate, + JSCustomGetOwnPropertySlotAndDescriptor, CustomCall ] HTMLAppletElement : HTMLElement { attribute [Reflect] DOMString align; diff --git a/Source/WebCore/html/HTMLAreaElement.idl b/Source/WebCore/html/HTMLAreaElement.idl index a14a4701f..dfb9c9b5d 100644 --- a/Source/WebCore/html/HTMLAreaElement.idl +++ b/Source/WebCore/html/HTMLAreaElement.idl @@ -29,6 +29,9 @@ module html { attribute [Reflect] DOMString shape; attribute [Reflect] DOMString target; +#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C + attribute [Reflect] DOMString accessKey; +#endif // IE Extensions readonly attribute DOMString hash; readonly attribute DOMString host; diff --git a/Source/WebCore/html/HTMLAttributeNames.in b/Source/WebCore/html/HTMLAttributeNames.in index 60d96d53d..151df7f38 100644 --- a/Source/WebCore/html/HTMLAttributeNames.in +++ b/Source/WebCore/html/HTMLAttributeNames.in @@ -304,6 +304,7 @@ text title top topmargin +translate truespeed type usemap diff --git a/Source/WebCore/html/HTMLAudioElement.cpp b/Source/WebCore/html/HTMLAudioElement.cpp index e3dcf47f1..98decc152 100644 --- a/Source/WebCore/html/HTMLAudioElement.cpp +++ b/Source/WebCore/html/HTMLAudioElement.cpp @@ -43,7 +43,9 @@ HTMLAudioElement::HTMLAudioElement(const QualifiedName& tagName, Document* docum PassRefPtr<HTMLAudioElement> HTMLAudioElement::create(const QualifiedName& tagName, Document* document, bool createdByParser) { - return adoptRef(new HTMLAudioElement(tagName, document, createdByParser)); + RefPtr<HTMLAudioElement> audioElement(adoptRef(new HTMLAudioElement(tagName, document, createdByParser))); + audioElement->suspendIfNeeded(); + return audioElement.release(); } PassRefPtr<HTMLAudioElement> HTMLAudioElement::createForJSConstructor(Document* document, const String& src) @@ -54,6 +56,7 @@ PassRefPtr<HTMLAudioElement> HTMLAudioElement::createForJSConstructor(Document* audio->setSrc(src); audio->scheduleLoad(HTMLMediaElement::MediaResource); } + audio->suspendIfNeeded(); return audio.release(); } diff --git a/Source/WebCore/html/HTMLAudioElement.idl b/Source/WebCore/html/HTMLAudioElement.idl index 109164627..1adf01c46 100644 --- a/Source/WebCore/html/HTMLAudioElement.idl +++ b/Source/WebCore/html/HTMLAudioElement.idl @@ -27,7 +27,7 @@ module html { interface [ ActiveDOMObject, Conditional=VIDEO, - NamedConstructor=Audio(in [Optional=CallWithNullValue] DOMString src) + NamedConstructor=Audio(in [Optional=DefaultIsNullString] DOMString src) ] HTMLAudioElement : HTMLMediaElement { }; } diff --git a/Source/WebCore/html/HTMLBRElement.cpp b/Source/WebCore/html/HTMLBRElement.cpp index 5efe6379a..33f0c533c 100644 --- a/Source/WebCore/html/HTMLBRElement.cpp +++ b/Source/WebCore/html/HTMLBRElement.cpp @@ -48,21 +48,26 @@ PassRefPtr<HTMLBRElement> HTMLBRElement::create(const QualifiedName& tagName, Do return adoptRef(new HTMLBRElement(tagName, document)); } -void HTMLBRElement::parseAttribute(Attribute* attr) +bool HTMLBRElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == clearAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLBRElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == clearAttr) { - // If the string is empty, then don't add the clear property. + // If the string is empty, then don't add the clear property. // <br clear> and <br clear=""> are just treated like <br> by Gecko, Mac IE, etc. -dwh - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyClear); - else if (!attr->value().isEmpty()) { + if (!attr->isEmpty()) { if (equalIgnoringCase(attr->value(), "all")) - addCSSProperty(CSSPropertyClear, "both"); + addPropertyToAttributeStyle(style, CSSPropertyClear, "both"); else - addCSSProperty(CSSPropertyClear, attr->value()); + addPropertyToAttributeStyle(style, CSSPropertyClear, attr->value()); } } else - HTMLElement::parseAttribute(attr); + HTMLElement::collectStyleForAttribute(attr, style); } RenderObject* HTMLBRElement::createRenderer(RenderArena* arena, RenderStyle* style) diff --git a/Source/WebCore/html/HTMLBRElement.h b/Source/WebCore/html/HTMLBRElement.h index 10a6432c7..16c1beae7 100644 --- a/Source/WebCore/html/HTMLBRElement.h +++ b/Source/WebCore/html/HTMLBRElement.h @@ -38,8 +38,9 @@ public: private: HTMLBRElement(const QualifiedName&, Document*); - virtual void parseAttribute(Attribute*) OVERRIDE; - + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); }; diff --git a/Source/WebCore/html/HTMLBodyElement.cpp b/Source/WebCore/html/HTMLBodyElement.cpp index a769a2c21..34d2924fa 100644 --- a/Source/WebCore/html/HTMLBodyElement.cpp +++ b/Source/WebCore/html/HTMLBodyElement.cpp @@ -25,6 +25,7 @@ #include "HTMLBodyElement.h" #include "Attribute.h" +#include "CSSImageValue.h" #include "CSSParser.h" #include "CSSValueKeywords.h" #include "EventNames.h" @@ -60,46 +61,39 @@ HTMLBodyElement::~HTMLBodyElement() { } -void HTMLBodyElement::parseAttribute(Attribute* attr) +bool HTMLBodyElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == backgroundAttr || attr->name() == marginwidthAttr || attr->name() == leftmarginAttr || attr->name() == marginheightAttr || attr->name() == topmarginAttr || attr->name() == bgcolorAttr || attr->name() == textAttr || attr->name() == bgpropertiesAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLBodyElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == backgroundAttr) { String url = stripLeadingAndTrailingHTMLSpaces(attr->value()); if (!url.isEmpty()) - addCSSImageProperty(CSSPropertyBackgroundImage, document()->completeURL(url).string()); - else - removeCSSProperty(CSSPropertyBackgroundImage); + style->setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document()->completeURL(url).string()))); } else if (attr->name() == marginwidthAttr || attr->name() == leftmarginAttr) { - if (attr->value().isNull()) - removeCSSProperties(CSSPropertyMarginRight, CSSPropertyMarginLeft); - else { - addCSSLength(CSSPropertyMarginRight, attr->value()); - addCSSLength(CSSPropertyMarginLeft, attr->value()); - } + addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value()); } else if (attr->name() == marginheightAttr || attr->name() == topmarginAttr) { - if (attr->value().isNull()) - removeCSSProperties(CSSPropertyMarginBottom, CSSPropertyMarginTop); - else { - addCSSLength(CSSPropertyMarginBottom, attr->value()); - addCSSLength(CSSPropertyMarginTop, attr->value()); - } + addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value()); } else if (attr->name() == bgcolorAttr) { - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyBackgroundColor); - else - addCSSColor(CSSPropertyBackgroundColor, attr->value()); + addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attr->value()); } else if (attr->name() == textAttr) { - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyColor); - else - addCSSColor(CSSPropertyColor, attr->value()); + addHTMLColorToStyle(style, CSSPropertyColor, attr->value()); } else if (attr->name() == bgpropertiesAttr) { if (equalIgnoringCase(attr->value(), "fixed")) - addCSSProperty(CSSPropertyBackgroundAttachment, CSSValueFixed); - else - removeCSSProperty(CSSPropertyBackgroundAttachment); - } else if (attr->name() == vlinkAttr || - attr->name() == alinkAttr || - attr->name() == linkAttr) { + addPropertyToAttributeStyle(style, CSSPropertyBackgroundAttachment, CSSValueFixed); + } else + HTMLElement::collectStyleForAttribute(attr, style); +} + +void HTMLBodyElement::parseAttribute(Attribute* attr) +{ + if (attr->name() == vlinkAttr || attr->name() == alinkAttr || attr->name() == linkAttr) { if (attr->isNull()) { if (attr->name() == linkAttr) document()->resetLinkColor(); @@ -118,9 +112,8 @@ void HTMLBodyElement::parseAttribute(Attribute* attr) document()->setActiveLinkColor(color); } } - - if (attached()) - document()->recalcStyle(Force); + + setNeedsStyleRecalc(); } else if (attr->name() == onloadAttr) document()->setWindowAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(document()->frame(), attr)); else if (attr->name() == onbeforeunloadAttr) diff --git a/Source/WebCore/html/HTMLBodyElement.h b/Source/WebCore/html/HTMLBodyElement.h index 8004b10da..41ba4485c 100644 --- a/Source/WebCore/html/HTMLBodyElement.h +++ b/Source/WebCore/html/HTMLBodyElement.h @@ -71,6 +71,8 @@ private: HTMLBodyElement(const QualifiedName&, Document*); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual void insertedIntoDocument(); diff --git a/Source/WebCore/html/HTMLButtonElement.cpp b/Source/WebCore/html/HTMLButtonElement.cpp index 1468248b9..a79641a31 100644 --- a/Source/WebCore/html/HTMLButtonElement.cpp +++ b/Source/WebCore/html/HTMLButtonElement.cpp @@ -79,6 +79,17 @@ const AtomicString& HTMLButtonElement::formControlType() const return emptyAtom; } +bool HTMLButtonElement::isPresentationAttribute(Attribute* attr) const +{ + 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 + return false; + } + + return HTMLFormControlElement::isPresentationAttribute(attr); +} + void HTMLButtonElement::parseAttribute(Attribute* attr) { if (attr->name() == typeAttr) { @@ -89,9 +100,6 @@ void HTMLButtonElement::parseAttribute(Attribute* attr) else m_type = SUBMIT; setNeedsWillValidateCheck(); - } 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 HTMLFormControlElement::parseAttribute(attr); } diff --git a/Source/WebCore/html/HTMLButtonElement.h b/Source/WebCore/html/HTMLButtonElement.h index 9699bef0e..00518ea4c 100644 --- a/Source/WebCore/html/HTMLButtonElement.h +++ b/Source/WebCore/html/HTMLButtonElement.h @@ -44,6 +44,7 @@ private: virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; virtual void defaultEventHandler(Event*); virtual bool appendFormData(FormDataList&, bool); diff --git a/Source/WebCore/html/HTMLButtonElement.idl b/Source/WebCore/html/HTMLButtonElement.idl index b8b8621f9..b9eafb0d5 100644 --- a/Source/WebCore/html/HTMLButtonElement.idl +++ b/Source/WebCore/html/HTMLButtonElement.idl @@ -30,6 +30,9 @@ module html { attribute [Reflect] DOMString formTarget; readonly attribute ValidityState validity; +#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C + attribute [Reflect] DOMString accessKey; +#endif attribute [Reflect] boolean disabled; attribute [Reflect] boolean autofocus; attribute [Reflect] DOMString name; @@ -41,7 +44,9 @@ module html { boolean checkValidity(); void setCustomValidity(in [TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString error); +#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C void click(); +#endif readonly attribute NodeList labels; }; diff --git a/Source/WebCore/html/HTMLCanvasElement.cpp b/Source/WebCore/html/HTMLCanvasElement.cpp index 9cf78d403..7ed6e3d11 100644 --- a/Source/WebCore/html/HTMLCanvasElement.cpp +++ b/Source/WebCore/html/HTMLCanvasElement.cpp @@ -45,6 +45,7 @@ #include "MIMETypeRegistry.h" #include "Page.h" #include "RenderHTMLCanvas.h" +#include "RenderLayer.h" #include "Settings.h" #include <math.h> #include <stdio.h> @@ -79,7 +80,12 @@ HTMLCanvasElement::HTMLCanvasElement(const QualifiedName& tagName, Document* doc , m_size(DefaultWidth, DefaultHeight) , m_rendererIsCanvas(false) , m_ignoreReset(false) +#if ENABLE(HIGH_DPI_CANVAS) + // FIXME: Make this the default once https://bugs.webkit.org/show_bug.cgi?id=73645 has been fixed. , m_deviceScaleFactor(document->frame() ? document->frame()->page()->deviceScaleFactor() : 1) +#else + , m_deviceScaleFactor(1) +#endif , m_originClean(true) , m_hasCreatedImageBuffer(false) { @@ -264,6 +270,25 @@ void HTMLCanvasElement::reset() (*it)->canvasResized(this); } +bool HTMLCanvasElement::paintsIntoCanvasBuffer() const +{ + ASSERT(m_context); +#if USE(IOSURFACE_CANVAS_BACKING_STORE) + if (m_context->is2d()) + return true; +#endif + +#if USE(ACCELERATED_COMPOSITING) + if (!m_context->isAccelerated()) + return true; + + if (renderBox() && renderBox()->hasLayer() && renderBox()->layer()->hasAcceleratedCompositing()) + return false; +#endif + return true; +} + + void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r, bool useLowQualityScale) { // Clear the dirty rect @@ -273,7 +298,7 @@ void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r, boo return; if (m_context) { - if (!m_context->paintsIntoCanvasBuffer() && !document()->printing()) + if (!paintsIntoCanvasBuffer() && !document()->printing()) return; m_context->paintRenderingResultsToCanvas(); } @@ -282,9 +307,9 @@ void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r, boo ImageBuffer* imageBuffer = buffer(); if (imageBuffer) { if (m_presentedImage) - context->drawImage(m_presentedImage.get(), ColorSpaceDeviceRGB, r, CompositeSourceOver, useLowQualityScale); + context->drawImage(m_presentedImage.get(), ColorSpaceDeviceRGB, pixelSnappedIntRect(r), CompositeSourceOver, useLowQualityScale); else - context->drawImageBuffer(imageBuffer, ColorSpaceDeviceRGB, r, CompositeSourceOver, useLowQualityScale); + context->drawImageBuffer(imageBuffer, ColorSpaceDeviceRGB, pixelSnappedIntRect(r), CompositeSourceOver, useLowQualityScale); } } diff --git a/Source/WebCore/html/HTMLCanvasElement.h b/Source/WebCore/html/HTMLCanvasElement.h index 967444d0c..e2c4888e5 100644 --- a/Source/WebCore/html/HTMLCanvasElement.h +++ b/Source/WebCore/html/HTMLCanvasElement.h @@ -148,6 +148,8 @@ private: bool shouldDefer() const; + bool paintsIntoCanvasBuffer() const; + HashSet<CanvasObserver*> m_observers; IntSize m_size; diff --git a/Source/WebCore/html/HTMLCanvasElement.idl b/Source/WebCore/html/HTMLCanvasElement.idl index 35a806c65..2be96a556 100644 --- a/Source/WebCore/html/HTMLCanvasElement.idl +++ b/Source/WebCore/html/HTMLCanvasElement.idl @@ -33,13 +33,13 @@ module html { attribute long width; attribute long height; - [Custom] DOMString toDataURL(in [TreatNullAs=NullString, TreatUndefinedAs=NullString,Optional=CallWithDefaultValue] DOMString type) + [Custom] DOMString toDataURL(in [TreatNullAs=NullString, TreatUndefinedAs=NullString,Optional=DefaultIsUndefined] DOMString type) raises(DOMException); #if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP #if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C // The custom binding is needed to handle context creation attributes. - [Custom] DOMObject getContext(in [Optional=CallWithDefaultValue] DOMString contextId); + [Custom] DOMObject getContext(in [Optional=DefaultIsUndefined] DOMString contextId); #endif #endif diff --git a/Source/WebCore/html/HTMLCollection.cpp b/Source/WebCore/html/HTMLCollection.cpp index e6f2eac0a..7d06308fc 100644 --- a/Source/WebCore/html/HTMLCollection.cpp +++ b/Source/WebCore/html/HTMLCollection.cpp @@ -254,7 +254,7 @@ bool HTMLCollection::checkForNameMatch(Element* element, bool checkName, const A if (m_type == DocAll && !nameShouldBeVisibleInDocumentAll(e)) return false; - return e->getAttribute(nameAttr) == name && e->getIdAttribute() != name; + return e->getNameAttribute() == name && e->getIdAttribute() != name; } Node* HTMLCollection::namedItem(const AtomicString& name) const @@ -294,7 +294,7 @@ void HTMLCollection::updateNameCache() const continue; HTMLElement* e = toHTMLElement(element); const AtomicString& idAttrVal = e->getIdAttribute(); - const AtomicString& nameAttrVal = e->getAttribute(nameAttr); + const AtomicString& nameAttrVal = e->getNameAttribute(); if (!idAttrVal.isEmpty()) append(m_cache.idCache, idAttrVal, e); if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (m_type != DocAll || nameShouldBeVisibleInDocumentAll(e))) diff --git a/Source/WebCore/html/HTMLCollection.idl b/Source/WebCore/html/HTMLCollection.idl index a4d172d1a..778377626 100644 --- a/Source/WebCore/html/HTMLCollection.idl +++ b/Source/WebCore/html/HTMLCollection.idl @@ -23,16 +23,16 @@ module html { interface [ IndexedGetter, NamedGetter, - JSCustomToJS, + CustomToJSObject, JSGenerateIsReachable, ObjCPolymorphic ] HTMLCollection { readonly attribute unsigned long length; - Node item(in [Optional=CallWithDefaultValue] unsigned long index); - [Custom] Node namedItem(in [Optional=CallWithDefaultValue] DOMString name); + Node item(in [Optional=DefaultIsUndefined] unsigned long index); + [Custom] Node namedItem(in [Optional=DefaultIsUndefined] DOMString name); #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C - NodeList tags(in [Optional=CallWithDefaultValue] DOMString name); + NodeList tags(in [Optional=DefaultIsUndefined] DOMString name); #endif }; diff --git a/Source/WebCore/html/HTMLDetailsElement.cpp b/Source/WebCore/html/HTMLDetailsElement.cpp index 015cf61ce..d49daa4c6 100644 --- a/Source/WebCore/html/HTMLDetailsElement.cpp +++ b/Source/WebCore/html/HTMLDetailsElement.cpp @@ -28,8 +28,10 @@ #include "HTMLSummaryElement.h" #include "LocalizedStrings.h" #include "MouseEvent.h" +#include "NodeRenderingContext.h" #include "RenderDetails.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include "Text.h" namespace WebCore { @@ -108,7 +110,7 @@ RenderObject* HTMLDetailsElement::createRenderer(RenderArena* arena, RenderStyle void HTMLDetailsElement::createShadowSubtree() { - ASSERT(!shadowRoot()); + ASSERT(!hasShadowRoot()); RefPtr<ShadowRoot> root = ShadowRoot::create(this, ShadowRoot::CreatingUserAgentShadowRoot); root->appendChild(DetailsSummaryElement::create(document()), ASSERT_NO_EXCEPTION, true); @@ -122,7 +124,7 @@ Element* HTMLDetailsElement::findMainSummary() const return toElement(child); } - return static_cast<DetailsSummaryElement*>(shadowRoot()->firstChild())->fallbackSummary(); + return static_cast<DetailsSummaryElement*>(shadowRootList()->oldestShadowRoot()->firstChild())->fallbackSummary(); } void HTMLDetailsElement::parseAttribute(Attribute* attr) @@ -136,15 +138,18 @@ void HTMLDetailsElement::parseAttribute(Attribute* attr) HTMLElement::parseAttribute(attr); } -bool HTMLDetailsElement::childShouldCreateRenderer(Node* child) const +bool HTMLDetailsElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const { + if (!childContext.isOnEncapsulationBoundary()) + return false; + if (m_isOpen) - return true; + return HTMLElement::childShouldCreateRenderer(childContext); - if (!child->hasTagName(summaryTag)) + if (!childContext.node()->hasTagName(summaryTag)) return false; - return child == findMainSummary(); + return childContext.node() == findMainSummary() && HTMLElement::childShouldCreateRenderer(childContext); } void HTMLDetailsElement::toggleOpen() diff --git a/Source/WebCore/html/HTMLDetailsElement.h b/Source/WebCore/html/HTMLDetailsElement.h index a86a365c6..94e88334d 100644 --- a/Source/WebCore/html/HTMLDetailsElement.h +++ b/Source/WebCore/html/HTMLDetailsElement.h @@ -36,9 +36,8 @@ private: HTMLDetailsElement(const QualifiedName&, Document*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); - + virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE; virtual void parseAttribute(Attribute*) OVERRIDE; - bool childShouldCreateRenderer(Node*) const; void createShadowSubtree(); diff --git a/Source/WebCore/html/HTMLDivElement.cpp b/Source/WebCore/html/HTMLDivElement.cpp index da2785c1f..bd15ae239 100644 --- a/Source/WebCore/html/HTMLDivElement.cpp +++ b/Source/WebCore/html/HTMLDivElement.cpp @@ -48,21 +48,26 @@ PassRefPtr<HTMLDivElement> HTMLDivElement::create(const QualifiedName& tagName, return adoptRef(new HTMLDivElement(tagName, document)); } -void HTMLDivElement::parseAttribute(Attribute* attr) +bool HTMLDivElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == alignAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLDivElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == alignAttr) { - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyTextAlign); if (equalIgnoringCase(attr->value(), "middle") || equalIgnoringCase(attr->value(), "center")) - addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitCenter); + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, CSSValueWebkitCenter); else if (equalIgnoringCase(attr->value(), "left")) - addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitLeft); + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, CSSValueWebkitLeft); else if (equalIgnoringCase(attr->value(), "right")) - addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitRight); + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, CSSValueWebkitRight); else - addCSSProperty(CSSPropertyTextAlign, attr->value()); + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, attr->value()); } else - HTMLElement::parseAttribute(attr); + HTMLElement::collectStyleForAttribute(attr, style); } } diff --git a/Source/WebCore/html/HTMLDivElement.h b/Source/WebCore/html/HTMLDivElement.h index cd90d8728..f8f4f7101 100644 --- a/Source/WebCore/html/HTMLDivElement.h +++ b/Source/WebCore/html/HTMLDivElement.h @@ -36,7 +36,8 @@ protected: HTMLDivElement(const QualifiedName&, Document*); private: - virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; }; } // namespace WebCore diff --git a/Source/WebCore/html/HTMLDocument.idl b/Source/WebCore/html/HTMLDocument.idl index dd020e2c5..19420ee3d 100644 --- a/Source/WebCore/html/HTMLDocument.idl +++ b/Source/WebCore/html/HTMLDocument.idl @@ -21,12 +21,13 @@ module html { interface [ - CustomNamedGetter + CustomNamedGetter, + V8CustomToJSObject ] HTMLDocument : Document { [JSCustom, V8Custom] void open(); void close(); - [Custom] void write(in [Optional=CallWithDefaultValue] DOMString text); - [Custom] void writeln(in [Optional=CallWithDefaultValue] DOMString text); + [Custom] void write(in [Optional=DefaultIsUndefined] DOMString text); + [Custom] void writeln(in [Optional=DefaultIsUndefined] DOMString text); readonly attribute HTMLCollection embeds; readonly attribute HTMLCollection plugins; diff --git a/Source/WebCore/html/HTMLElement.cpp b/Source/WebCore/html/HTMLElement.cpp index a018fe23b..4e8da5c7d 100644 --- a/Source/WebCore/html/HTMLElement.cpp +++ b/Source/WebCore/html/HTMLElement.cpp @@ -29,6 +29,7 @@ #include "CSSParser.h" #include "CSSPropertyNames.h" #include "CSSValueKeywords.h" +#include "CSSValuePool.h" #include "ChildListMutationScope.h" #include "DocumentFragment.h" #include "Event.h" @@ -140,51 +141,85 @@ static unsigned parseBorderWidthAttribute(Attribute* attr) return borderWidth; } -void HTMLElement::applyBorderAttribute(Attribute* attr) +void HTMLElement::applyBorderAttributeToStyle(Attribute* attr, StylePropertySet* style) { - addCSSLength(CSSPropertyBorderWidth, String::number(parseBorderWidthAttribute(attr))); - addCSSProperty(CSSPropertyBorderTopStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderRightStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderBottomStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderLeftStyle, CSSValueSolid); + addPropertyToAttributeStyle(style, CSSPropertyBorderWidth, parseBorderWidthAttribute(attr), CSSPrimitiveValue::CSS_PX); + addPropertyToAttributeStyle(style, CSSPropertyBorderStyle, CSSValueSolid); } -void HTMLElement::mapLanguageAttributeToLocale(Attribute* attribute) +void HTMLElement::mapLanguageAttributeToLocale(Attribute* attribute, StylePropertySet* style) { ASSERT(attribute && (attribute->name() == langAttr || attribute->name().matches(XMLNames::langAttr))); - const AtomicString& value = attribute->value(); - if (value.isNull()) - removeCSSProperty(CSSPropertyWebkitLocale); - else if (!value.isEmpty()) { + if (!attribute->isEmpty()) { // Have to quote so the locale id is treated as a string instead of as a CSS keyword. - addCSSProperty(CSSPropertyWebkitLocale, quoteCSSString(value)); + addPropertyToAttributeStyle(style, CSSPropertyWebkitLocale, quoteCSSString(attribute->value())); } else { // The empty string means the language is explicitly unknown. - addCSSProperty(CSSPropertyWebkitLocale, CSSValueAuto); + addPropertyToAttributeStyle(style, CSSPropertyWebkitLocale, CSSValueAuto); } - setNeedsStyleRecalc(); } -void HTMLElement::parseAttribute(Attribute* attr) +bool HTMLElement::isPresentationAttribute(Attribute* attr) const { - if (isIdAttributeName(attr->name()) || attr->name() == classAttr || attr->name() == styleAttr) - return StyledElement::parseAttribute(attr); + if (attr->name() == alignAttr || attr->name() == contenteditableAttr || attr->name() == hiddenAttr || attr->name() == langAttr || attr->name().matches(XMLNames::langAttr) || attr->name() == draggableAttr || attr->name() == dirAttr) + return true; + return StyledElement::isPresentationAttribute(attr); +} +void HTMLElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ if (attr->name() == alignAttr) { - if (attr->isNull()) - removeCSSProperty(CSSPropertyTextAlign); - else if (equalIgnoringCase(attr->value(), "middle")) - addCSSProperty(CSSPropertyTextAlign, "center"); + if (equalIgnoringCase(attr->value(), "middle")) + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, "center"); else - addCSSProperty(CSSPropertyTextAlign, attr->value()); + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, attr->value()); } else if (attr->name() == contenteditableAttr) { - setContentEditable(attr); + if (attr->isEmpty() || equalIgnoringCase(attr->value(), "true")) { + addPropertyToAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadWrite); + addPropertyToAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord); + addPropertyToAttributeStyle(style, CSSPropertyWebkitNbspMode, CSSValueSpace); + addPropertyToAttributeStyle(style, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace); + } else if (equalIgnoringCase(attr->value(), "plaintext-only")) { + addPropertyToAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly); + addPropertyToAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord); + addPropertyToAttributeStyle(style, CSSPropertyWebkitNbspMode, CSSValueSpace); + addPropertyToAttributeStyle(style, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace); + } else if (equalIgnoringCase(attr->value(), "false")) + addPropertyToAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadOnly); } else if (attr->name() == hiddenAttr) { - if (attr->isNull()) - removeCSSProperty(CSSPropertyDisplay); - else - addCSSProperty(CSSPropertyDisplay, CSSValueNone); - } else if (attr->name() == tabindexAttr) { + addPropertyToAttributeStyle(style, CSSPropertyDisplay, CSSValueNone); + } else if (attr->name() == draggableAttr) { + if (equalIgnoringCase(attr->value(), "true")) { + addPropertyToAttributeStyle(style, CSSPropertyWebkitUserDrag, CSSValueElement); + addPropertyToAttributeStyle(style, CSSPropertyWebkitUserSelect, CSSValueNone); + } else if (equalIgnoringCase(attr->value(), "false")) + addPropertyToAttributeStyle(style, CSSPropertyWebkitUserDrag, CSSValueNone); + } else if (attr->name() == dirAttr) { + if (equalIgnoringCase(attr->value(), "auto")) + addPropertyToAttributeStyle(style, CSSPropertyUnicodeBidi, unicodeBidiAttributeForDirAuto(this)); + else { + addPropertyToAttributeStyle(style, CSSPropertyDirection, attr->value()); + if (!hasTagName(bdiTag) && !hasTagName(bdoTag) && !hasTagName(outputTag)) + addPropertyToAttributeStyle(style, CSSPropertyUnicodeBidi, CSSValueEmbed); + } + } else if (attr->name().matches(XMLNames::langAttr)) { + mapLanguageAttributeToLocale(attr, style); + } else if (attr->name() == langAttr) { + // xml:lang has a higher priority than lang. + if (!fastHasAttribute(XMLNames::langAttr)) + mapLanguageAttributeToLocale(attr, style); + } else + StyledElement::collectStyleForAttribute(attr, style); +} + +void HTMLElement::parseAttribute(Attribute* attr) +{ + if (isIdAttributeName(attr->name()) || attr->name() == classAttr || attr->name() == styleAttr) + return StyledElement::parseAttribute(attr); + + if (attr->name() == dirAttr) + dirAttributeChanged(attr); + else if (attr->name() == tabindexAttr) { int tabindex = 0; if (attr->isEmpty()) clearTabIndexExplicitly(); @@ -192,40 +227,6 @@ void HTMLElement::parseAttribute(Attribute* attr) // 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().matches(XMLNames::langAttr)) { - mapLanguageAttributeToLocale(attr); - } else if (attr->name() == langAttr) { - // xml:lang has a higher priority than lang. - if (!fastHasAttribute(XMLNames::langAttr)) - mapLanguageAttributeToLocale(attr); - } else if (attr->name() == dirAttr) { - if (attr->isNull()) - removeCSSProperties(CSSPropertyDirection, CSSPropertyUnicodeBidi); - else { - bool dirIsAuto = equalIgnoringCase(attr->value(), "auto"); - if (!dirIsAuto) - addCSSProperty(CSSPropertyDirection, attr->value()); - else - removeCSSProperty(CSSPropertyDirection); - - dirAttributeChanged(attr); - if (dirIsAuto) - addCSSProperty(CSSPropertyUnicodeBidi, unicodeBidiAttributeForDirAuto(this)); - else if (!hasTagName(bdiTag) && !hasTagName(bdoTag) && !hasTagName(outputTag)) - addCSSProperty(CSSPropertyUnicodeBidi, CSSValueEmbed); - else - removeCSSProperty(CSSPropertyUnicodeBidi); - } - } else if (attr->name() == draggableAttr) { - const AtomicString& value = attr->value(); - if (equalIgnoringCase(value, "true")) { - addCSSProperty(CSSPropertyWebkitUserDrag, CSSValueElement); - addCSSProperty(CSSPropertyWebkitUserSelect, CSSValueNone); - } else if (equalIgnoringCase(value, "false")) { - addCSSProperty(CSSPropertyWebkitUserDrag, CSSValueNone); - removeCSSProperty(CSSPropertyWebkitUserSelect); - } else - removeCSSProperties(CSSPropertyWebkitUserDrag, CSSPropertyWebkitUserSelect); #if ENABLE(MICRODATA) } else if (attr->name() == itempropAttr) { setItemProp(attr->value()); @@ -365,7 +366,7 @@ static void replaceChildrenWithFragment(HTMLElement* element, PassRefPtr<Documen } if (hasOneTextChild(element) && hasOneTextChild(fragment.get())) { - static_cast<Text*>(element->firstChild())->setData(static_cast<Text*>(fragment->firstChild())->data(), ec); + toText(element->firstChild())->setData(toText(fragment->firstChild())->data(), ec); return; } @@ -385,7 +386,7 @@ static void replaceChildrenWithText(HTMLElement* element, const String& text, Ex #endif if (hasOneTextChild(element)) { - static_cast<Text*>(element->firstChild())->setData(text, ec); + toText(element->firstChild())->setData(text, ec); return; } @@ -434,8 +435,8 @@ static void mergeWithNextTextNode(PassRefPtr<Node> node, ExceptionCode& ec) if (!next || !next->isTextNode()) return; - RefPtr<Text> textNode = static_cast<Text*>(node.get()); - RefPtr<Text> textNext = static_cast<Text*>(next); + RefPtr<Text> textNode = toText(node.get()); + RefPtr<Text> textNext = toText(next); textNode->appendData(textNext->data(), ec); if (ec) return; @@ -678,17 +679,7 @@ void HTMLElement::insertAdjacentText(const String& where, const String& text, Ex insertAdjacent(where, textNode.get(), ec); } -void HTMLElement::addHTMLAlignment(Attribute* attr) -{ - addHTMLAlignmentToStyledElement(this, attr); -} - -void HTMLElement::removeHTMLAlignment() -{ - removeCSSProperties(CSSPropertyFloat, CSSPropertyVerticalAlign); -} - -void HTMLElement::addHTMLAlignmentToStyledElement(StyledElement* element, Attribute* attr) +void HTMLElement::applyAlignmentAttributeToStyle(Attribute* attr, StylePropertySet* style) { // Vertical alignment with respect to the current baseline of the text // right or left means floating images. @@ -718,14 +709,10 @@ void HTMLElement::addHTMLAlignmentToStyledElement(StyledElement* element, Attrib verticalAlignValue = CSSValueTextTop; if (floatValue != CSSValueInvalid) - element->addCSSProperty(CSSPropertyFloat, floatValue); - else - element->removeCSSProperty(CSSPropertyFloat); + addPropertyToAttributeStyle(style, CSSPropertyFloat, floatValue); if (verticalAlignValue != CSSValueInvalid) - element->addCSSProperty(CSSPropertyVerticalAlign, verticalAlignValue); - else - element->removeCSSProperty(CSSPropertyVerticalAlign); + addPropertyToAttributeStyle(style, CSSPropertyVerticalAlign, verticalAlignValue); } bool HTMLElement::supportsFocus() const @@ -749,27 +736,6 @@ String HTMLElement::contentEditable() const return "inherit"; } -void HTMLElement::setContentEditable(Attribute* attr) -{ - const AtomicString& enabled = attr->value(); - if (enabled.isNull()) - removeCSSProperties(CSSPropertyWebkitUserModify, CSSPropertyWordWrap, CSSPropertyWebkitNbspMode, CSSPropertyWebkitLineBreak); - else if (enabled.isEmpty() || equalIgnoringCase(enabled, "true")) { - addCSSProperty(CSSPropertyWebkitUserModify, CSSValueReadWrite); - addCSSProperty(CSSPropertyWordWrap, CSSValueBreakWord); - addCSSProperty(CSSPropertyWebkitNbspMode, CSSValueSpace); - addCSSProperty(CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace); - } else if (equalIgnoringCase(enabled, "false")) { - addCSSProperty(CSSPropertyWebkitUserModify, CSSValueReadOnly); - removeCSSProperties(CSSPropertyWordWrap, CSSPropertyWebkitNbspMode, CSSPropertyWebkitLineBreak); - } else if (equalIgnoringCase(enabled, "plaintext-only")) { - addCSSProperty(CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly); - addCSSProperty(CSSPropertyWordWrap, CSSValueBreakWord); - addCSSProperty(CSSPropertyWebkitNbspMode, CSSValueSpace); - addCSSProperty(CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace); - } -} - void HTMLElement::setContentEditable(const String& enabled, ExceptionCode& ec) { if (equalIgnoringCase(enabled, "true")) @@ -832,6 +798,42 @@ void HTMLElement::setTabIndex(int value) setAttribute(tabindexAttr, String::number(value)); } +TranslateAttributeMode HTMLElement::translateAttributeMode() const +{ + const AtomicString& value = getAttribute(translateAttr); + + if (value == nullAtom) + return TranslateAttributeInherit; + if (equalIgnoringCase(value, "yes") || equalIgnoringCase(value, "")) + return TranslateAttributeYes; + if (equalIgnoringCase(value, "no")) + return TranslateAttributeNo; + + return TranslateAttributeInherit; +} + +bool HTMLElement::translate() const +{ + for (const Node* n = this; n; n = n->parentNode()) { + if (n->isHTMLElement()) { + TranslateAttributeMode mode = static_cast<const HTMLElement*>(n)->translateAttributeMode(); + if (mode != TranslateAttributeInherit) { + ASSERT(mode == TranslateAttributeYes || mode == TranslateAttributeNo); + return mode == TranslateAttributeYes; + } + } + } + + // Default on the root element is translate=yes. + return true; +} + +void HTMLElement::setTranslate(bool enable) +{ + setAttribute(translateAttr, enable ? "yes" : "no"); +} + + HTMLCollection* HTMLElement::children() { return ensureCachedHTMLCollection(NodeChildren); @@ -1065,6 +1067,137 @@ void HTMLElement::setItemValueText(const String& value, ExceptionCode& ec) } #endif +void HTMLElement::addHTMLLengthToStyle(StylePropertySet* style, int propertyID, const String& value) +{ + // FIXME: This function should not spin up the CSS parser, but should instead just figure out the correct + // length unit and make the appropriate parsed value. + + // strip attribute garbage.. + StringImpl* v = value.impl(); + if (v) { + unsigned int l = 0; + + while (l < v->length() && (*v)[l] <= ' ') + l++; + + for (; l < v->length(); l++) { + UChar cc = (*v)[l]; + if (cc > '9') + break; + if (cc < '0') { + if (cc == '%' || cc == '*') + l++; + if (cc != '.') + break; + } + } + + if (l != v->length()) { + addPropertyToAttributeStyle(style, propertyID, v->substring(0, l)); + return; + } + } + + addPropertyToAttributeStyle(style, propertyID, value); +} + +static RGBA32 parseColorStringWithCrazyLegacyRules(const String& colorString) +{ + // Per spec, only look at the first 128 digits of the string. + const size_t maxColorLength = 128; + // We'll pad the buffer with two extra 0s later, so reserve two more than the max. + Vector<char, maxColorLength+2> digitBuffer; + + size_t i = 0; + // Skip a leading #. + if (colorString[0] == '#') + i = 1; + + // Grab the first 128 characters, replacing non-hex characters with 0. + // Non-BMP characters are replaced with "00" due to them appearing as two "characters" in the String. + for (; i < colorString.length() && digitBuffer.size() < maxColorLength; i++) { + if (!isASCIIHexDigit(colorString[i])) + digitBuffer.append('0'); + else + digitBuffer.append(colorString[i]); + } + + if (!digitBuffer.size()) + return Color::black; + + // Pad the buffer out to at least the next multiple of three in size. + digitBuffer.append('0'); + digitBuffer.append('0'); + + if (digitBuffer.size() < 6) + return makeRGB(toASCIIHexValue(digitBuffer[0]), toASCIIHexValue(digitBuffer[1]), toASCIIHexValue(digitBuffer[2])); + + // Split the digits into three components, then search the last 8 digits of each component. + ASSERT(digitBuffer.size() >= 6); + size_t componentLength = digitBuffer.size() / 3; + size_t componentSearchWindowLength = min<size_t>(componentLength, 8); + size_t redIndex = componentLength - componentSearchWindowLength; + size_t greenIndex = componentLength * 2 - componentSearchWindowLength; + size_t blueIndex = componentLength * 3 - componentSearchWindowLength; + // Skip digits until one of them is non-zero, or we've only got two digits left in the component. + while (digitBuffer[redIndex] == '0' && digitBuffer[greenIndex] == '0' && digitBuffer[blueIndex] == '0' && (componentLength - redIndex) > 2) { + redIndex++; + greenIndex++; + blueIndex++; + } + ASSERT(redIndex + 1 < componentLength); + ASSERT(greenIndex >= componentLength); + ASSERT(greenIndex + 1 < componentLength * 2); + ASSERT(blueIndex >= componentLength * 2); + ASSERT(blueIndex + 1 < digitBuffer.size()); + + int redValue = toASCIIHexValue(digitBuffer[redIndex], digitBuffer[redIndex + 1]); + int greenValue = toASCIIHexValue(digitBuffer[greenIndex], digitBuffer[greenIndex + 1]); + int blueValue = toASCIIHexValue(digitBuffer[blueIndex], digitBuffer[blueIndex + 1]); + return makeRGB(redValue, greenValue, blueValue); +} + +// Color parsing that matches HTML's "rules for parsing a legacy color value" +void HTMLElement::addHTMLColorToStyle(StylePropertySet* style, int propertyID, const String& attributeValue) +{ + // An empty string doesn't apply a color. (One containing only whitespace does, which is why this check occurs before stripping.) + if (attributeValue.isEmpty()) + return; + + String colorString = attributeValue.stripWhiteSpace(); + + // "transparent" doesn't apply a color either. + if (equalIgnoringCase(colorString, "transparent")) + return; + + // If the string is a named CSS color or a 3/6-digit hex color, use that. + Color parsedColor(colorString); + if (!parsedColor.isValid()) + parsedColor.setRGB(parseColorStringWithCrazyLegacyRules(colorString)); + + style->setProperty(propertyID, document()->cssValuePool()->createColorValue(parsedColor.rgb())); +} + +void StyledElement::copyNonAttributeProperties(const Element* sourceElement) +{ + ASSERT(sourceElement); + ASSERT(sourceElement->isStyledElement()); + + const StyledElement* source = static_cast<const StyledElement*>(sourceElement); + if (!source->inlineStyleDecl()) + return; + + StylePropertySet* inlineStyle = ensureInlineStyleDecl(); + inlineStyle->copyPropertiesFrom(*source->inlineStyleDecl()); + inlineStyle->setStrictParsing(source->inlineStyleDecl()->useStrictParsing()); + + setIsStyleAttributeValid(source->isStyleAttributeValid()); + setIsSynchronizingStyleAttribute(source->isSynchronizingStyleAttribute()); + + Element::copyNonAttributeProperties(sourceElement); +} + + } // namespace WebCore #ifndef NDEBUG diff --git a/Source/WebCore/html/HTMLElement.h b/Source/WebCore/html/HTMLElement.h index 47197261a..9d463cd77 100644 --- a/Source/WebCore/html/HTMLElement.h +++ b/Source/WebCore/html/HTMLElement.h @@ -35,6 +35,12 @@ class HTMLFormElement; class MicroDataItemValue; #endif +enum TranslateAttributeMode { + TranslateAttributeYes, + TranslateAttributeNo, + TranslateAttributeInherit +}; + class HTMLElement : public StyledElement { public: static PassRefPtr<HTMLElement> create(const QualifiedName& tagName, Document*); @@ -68,6 +74,9 @@ public: bool spellcheck() const; void setSpellcheck(bool); + bool translate() const; + void setTranslate(bool); + void click(); virtual void accessKeyAction(bool sendMouseEvents); @@ -79,8 +88,6 @@ public: HTMLFormElement* form() const { return virtualForm(); } - static void addHTMLAlignmentToStyledElement(StyledElement*, Attribute*); - HTMLFormElement* findFormAncestor() const; TextDirection directionalityIfhasDirAutoAttribute(bool& isAuto) const; @@ -93,11 +100,15 @@ public: protected: HTMLElement(const QualifiedName& tagName, Document*); - void addHTMLAlignment(Attribute*); - void removeHTMLAlignment(); + void addHTMLLengthToStyle(StylePropertySet*, int propertyID, const String& value); + void addHTMLColorToStyle(StylePropertySet*, int propertyID, const String& color); + + void applyAlignmentAttributeToStyle(Attribute*, StylePropertySet*); + void applyBorderAttributeToStyle(Attribute*, StylePropertySet*); virtual void parseAttribute(Attribute*) OVERRIDE; - void applyBorderAttribute(Attribute*); + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); void calculateAndAdjustDirectionality(); @@ -107,9 +118,7 @@ protected: private: virtual String nodeName() const; - void mapLanguageAttributeToLocale(Attribute*); - - void setContentEditable(Attribute*); + void mapLanguageAttributeToLocale(Attribute*, StylePropertySet*); virtual HTMLFormElement* virtualForm() const; @@ -121,6 +130,8 @@ private: void adjustDirectionalityIfNeededAfterChildrenChanged(Node* beforeChange, int childCountDelta); TextDirection directionality(Node** strongDirectionalityTextNode= 0) const; + TranslateAttributeMode translateAttributeMode() const; + #if ENABLE(MICRODATA) virtual String itemValueText() const; virtual void setItemValueText(const String&, ExceptionCode&); diff --git a/Source/WebCore/html/HTMLElement.idl b/Source/WebCore/html/HTMLElement.idl index 308010f40..8d5a0688d 100644 --- a/Source/WebCore/html/HTMLElement.idl +++ b/Source/WebCore/html/HTMLElement.idl @@ -22,13 +22,15 @@ module html { interface [ JSGenerateToNativeObject, - JSCustomPushEventHandlerScope + JSCustomPushEventHandlerScope, + V8CustomToJSObject ] HTMLElement : Element { // iht.com relies on id returning the empty string when no id is present. // Other browsers do this as well. So we don't convert null to JS null. attribute [Reflect] DOMString id; attribute [Reflect] DOMString title; attribute [Reflect] DOMString lang; + attribute boolean translate; attribute [Reflect] DOMString dir; attribute [Reflect=class] DOMString className; readonly attribute DOMTokenList classList; @@ -49,14 +51,14 @@ module html { attribute [TreatNullAs=NullString] DOMString outerText setter raises(DOMException); - Element insertAdjacentElement(in [Optional=CallWithDefaultValue] DOMString where, - in [Optional=CallWithDefaultValue] Element element) + Element insertAdjacentElement(in [Optional=DefaultIsUndefined] DOMString where, + in [Optional=DefaultIsUndefined] Element element) raises(DOMException); - void insertAdjacentHTML(in [Optional=CallWithDefaultValue] DOMString where, - in [Optional=CallWithDefaultValue] DOMString html) + void insertAdjacentHTML(in [Optional=DefaultIsUndefined] DOMString where, + in [Optional=DefaultIsUndefined] DOMString html) raises(DOMException); - void insertAdjacentText(in [Optional=CallWithDefaultValue] DOMString where, - in [Optional=CallWithDefaultValue] DOMString text) + void insertAdjacentText(in [Optional=DefaultIsUndefined] DOMString where, + in [Optional=DefaultIsUndefined] DOMString text) raises(DOMException); readonly attribute HTMLCollection children; @@ -88,6 +90,8 @@ module html { #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C readonly attribute DOMString titleDisplayString; #endif + + void click(); }; } diff --git a/Source/WebCore/html/HTMLEmbedElement.cpp b/Source/WebCore/html/HTMLEmbedElement.cpp index 1d64ecaae..06cb9b1e9 100644 --- a/Source/WebCore/html/HTMLEmbedElement.cpp +++ b/Source/WebCore/html/HTMLEmbedElement.cpp @@ -74,6 +74,24 @@ RenderWidget* HTMLEmbedElement::renderWidgetForJSBindings() return findWidgetRenderer(this); } +bool HTMLEmbedElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == hiddenAttr) + return true; + return HTMLPlugInImageElement::isPresentationAttribute(attr); +} + +void HTMLEmbedElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == hiddenAttr) { + if (equalIgnoringCase(attr->value(), "yes") || equalIgnoringCase(attr->value(), "true")) { + addPropertyToAttributeStyle(style, CSSPropertyWidth, 0, CSSPrimitiveValue::CSS_PX); + addPropertyToAttributeStyle(style, CSSPropertyHeight, 0, CSSPrimitiveValue::CSS_PX); + } + } else + HTMLPlugInImageElement::collectStyleForAttribute(attr, style); +} + void HTMLEmbedElement::parseAttribute(Attribute* attr) { const AtomicString& value = attr->value(); @@ -94,14 +112,6 @@ void HTMLEmbedElement::parseAttribute(Attribute* attr) m_imageLoader = adoptPtr(new HTMLImageLoader(this)); m_imageLoader->updateFromElementIgnoringPreviousError(); } - } else if (attr->name() == hiddenAttr) { - 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(CSSPropertyWidth, "0"); - addCSSLength(CSSPropertyHeight, "0"); - } else - removeCSSProperties(CSSPropertyWidth, CSSPropertyHeight); } else HTMLPlugInImageElement::parseAttribute(attr); } @@ -164,7 +174,7 @@ void HTMLEmbedElement::updateWidget(PluginCreationOption pluginCreationOption) SubframeLoader* loader = document()->frame()->loader()->subframeLoader(); // FIXME: beforeLoad could have detached the renderer! Just like in the <object> case above. - loader->requestObject(this, m_url, getAttribute(nameAttr), m_serviceType, paramNames, paramValues); + loader->requestObject(this, m_url, getNameAttribute(), m_serviceType, paramNames, paramValues); } bool HTMLEmbedElement::rendererIsNeeded(const NodeRenderingContext& context) diff --git a/Source/WebCore/html/HTMLEmbedElement.h b/Source/WebCore/html/HTMLEmbedElement.h index f37760361..f0fca2224 100644 --- a/Source/WebCore/html/HTMLEmbedElement.h +++ b/Source/WebCore/html/HTMLEmbedElement.h @@ -35,6 +35,8 @@ private: HTMLEmbedElement(const QualifiedName&, Document*, bool createdByParser); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual bool rendererIsNeeded(const NodeRenderingContext&); virtual void insertedIntoDocument(); diff --git a/Source/WebCore/html/HTMLEmbedElement.idl b/Source/WebCore/html/HTMLEmbedElement.idl index 8ccc38830..b6e3c166a 100644 --- a/Source/WebCore/html/HTMLEmbedElement.idl +++ b/Source/WebCore/html/HTMLEmbedElement.idl @@ -22,7 +22,7 @@ module html { interface [ CustomNamedSetter, - JSCustomGetOwnPropertySlotDelegate, + JSCustomGetOwnPropertySlotAndDescriptor, CustomCall ] HTMLEmbedElement : HTMLElement { attribute [Reflect] DOMString align; @@ -42,7 +42,7 @@ module html { #if defined(ENABLE_SVG) && ENABLE_SVG #if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C || defined(ENABLE_SVG_DOM_OBJC_BINDINGS) && ENABLE_SVG_DOM_OBJC_BINDINGS - [CheckAccessToNode] SVGDocument getSVGDocument() raises(DOMException); + [CheckSecurityForNode] SVGDocument getSVGDocument() raises(DOMException); #endif #endif }; diff --git a/Source/WebCore/html/HTMLFontElement.cpp b/Source/WebCore/html/HTMLFontElement.cpp index 86f52984a..a7c2e950b 100644 --- a/Source/WebCore/html/HTMLFontElement.cpp +++ b/Source/WebCore/html/HTMLFontElement.cpp @@ -26,6 +26,8 @@ #include "Attribute.h" #include "CSSPropertyNames.h" #include "CSSValueKeywords.h" +#include "CSSValueList.h" +#include "CSSValuePool.h" #include "HTMLNames.h" #include "HTMLParserIdioms.h" #include <wtf/text/StringBuilder.h> @@ -158,26 +160,26 @@ bool HTMLFontElement::cssValueFromFontSizeNumber(const String& s, int& size) return true; } -void HTMLFontElement::parseAttribute(Attribute* attr) +bool HTMLFontElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == sizeAttr || attr->name() == colorAttr || attr->name() == faceAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLFontElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == sizeAttr) { int size = 0; if (cssValueFromFontSizeNumber(attr->value(), size)) - addCSSProperty(CSSPropertyFontSize, size); - else - removeCSSProperty(CSSPropertyFontSize); - } else if (attr->name() == colorAttr) { - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyColor); - else - addCSSColor(CSSPropertyColor, attr->value()); - } else if (attr->name() == faceAttr) { - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyFontFamily); - else - addCSSProperty(CSSPropertyFontFamily, attr->value()); + addPropertyToAttributeStyle(style, CSSPropertyFontSize, size); + } else if (attr->name() == colorAttr) + addHTMLColorToStyle(style, CSSPropertyColor, attr->value()); + else if (attr->name() == faceAttr) { + if (RefPtr<CSSValueList> fontFaceValue = document()->cssValuePool()->createFontFaceValue(attr->value(), document()->elementSheet())) + style->setProperty(CSSProperty(CSSPropertyFontFamily, fontFaceValue.release())); } else - HTMLElement::parseAttribute(attr); + HTMLElement::collectStyleForAttribute(attr, style); } } diff --git a/Source/WebCore/html/HTMLFontElement.h b/Source/WebCore/html/HTMLFontElement.h index eea8b44fb..f24332c31 100644 --- a/Source/WebCore/html/HTMLFontElement.h +++ b/Source/WebCore/html/HTMLFontElement.h @@ -37,7 +37,8 @@ public: private: HTMLFontElement(const QualifiedName&, Document*); - virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; }; } // namespace diff --git a/Source/WebCore/html/HTMLFormCollection.cpp b/Source/WebCore/html/HTMLFormCollection.cpp index 919e09c01..684e3a5aa 100644 --- a/Source/WebCore/html/HTMLFormCollection.cpp +++ b/Source/WebCore/html/HTMLFormCollection.cpp @@ -164,7 +164,7 @@ void HTMLFormCollection::updateNameCache() const if (associatedElement->isEnumeratable()) { HTMLElement* element = toHTMLElement(associatedElement); const AtomicString& idAttrVal = element->getIdAttribute(); - const AtomicString& nameAttrVal = element->getAttribute(nameAttr); + const AtomicString& nameAttrVal = element->getNameAttribute(); if (!idAttrVal.isEmpty()) { append(m_cache.idCache, idAttrVal, element); foundInputElements.add(idAttrVal.impl()); @@ -179,7 +179,7 @@ void HTMLFormCollection::updateNameCache() const for (unsigned i = 0; i < f->m_imageElements.size(); ++i) { HTMLImageElement* element = f->m_imageElements[i]; const AtomicString& idAttrVal = element->getIdAttribute(); - const AtomicString& nameAttrVal = element->getAttribute(nameAttr); + const AtomicString& nameAttrVal = element->getNameAttribute(); if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl())) append(m_cache.idCache, idAttrVal, element); if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl())) diff --git a/Source/WebCore/html/HTMLFormControlElement.cpp b/Source/WebCore/html/HTMLFormControlElement.cpp index c092f617a..8a72df061 100644 --- a/Source/WebCore/html/HTMLFormControlElement.cpp +++ b/Source/WebCore/html/HTMLFormControlElement.cpp @@ -227,7 +227,7 @@ void HTMLFormControlElement::removedFromDocument() const AtomicString& HTMLFormControlElement::formControlName() const { - const AtomicString& name = fastGetAttribute(nameAttr); + const AtomicString& name = getNameAttribute(); return name.isNull() ? emptyAtom : name; } diff --git a/Source/WebCore/html/HTMLFormElement.cpp b/Source/WebCore/html/HTMLFormElement.cpp index 89f1e7b9b..213b336d9 100644 --- a/Source/WebCore/html/HTMLFormElement.cpp +++ b/Source/WebCore/html/HTMLFormElement.cpp @@ -500,7 +500,7 @@ HTMLCollection* HTMLFormElement::elements() String HTMLFormElement::name() const { - return getAttribute(nameAttr); + return getNameAttribute(); } bool HTMLFormElement::noValidate() const diff --git a/Source/WebCore/html/HTMLFrameElement.idl b/Source/WebCore/html/HTMLFrameElement.idl index 51a471621..f40f7b1c5 100644 --- a/Source/WebCore/html/HTMLFrameElement.idl +++ b/Source/WebCore/html/HTMLFrameElement.idl @@ -32,14 +32,14 @@ module html { attribute [Reflect, URL] DOMString src; // Introduced in DOM Level 2: - readonly attribute [CheckAccessToNode] Document contentDocument; + readonly attribute [CheckSecurityForNode] Document contentDocument; // Extensions readonly attribute DOMWindow contentWindow; #if defined(ENABLE_SVG) && ENABLE_SVG #if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C || defined(ENABLE_SVG_DOM_OBJC_BINDINGS) && ENABLE_SVG_DOM_OBJC_BINDINGS - [CheckAccessToNode] SVGDocument getSVGDocument() + [CheckSecurityForNode] SVGDocument getSVGDocument() raises(DOMException); #endif #endif diff --git a/Source/WebCore/html/HTMLFrameElementBase.cpp b/Source/WebCore/html/HTMLFrameElementBase.cpp index 727173bb9..0841230da 100644 --- a/Source/WebCore/html/HTMLFrameElementBase.cpp +++ b/Source/WebCore/html/HTMLFrameElementBase.cpp @@ -174,7 +174,7 @@ void HTMLFrameElementBase::parseAttribute(Attribute* attr) void HTMLFrameElementBase::setNameAndOpenURL() { - m_frameName = getAttribute(nameAttr); + m_frameName = getNameAttribute(); if (m_frameName.isNull()) m_frameName = getIdAttribute(); openURL(); diff --git a/Source/WebCore/html/HTMLFrameSetElement.cpp b/Source/WebCore/html/HTMLFrameSetElement.cpp index 4af6342bd..d3fdb97a4 100644 --- a/Source/WebCore/html/HTMLFrameSetElement.cpp +++ b/Source/WebCore/html/HTMLFrameSetElement.cpp @@ -64,6 +64,21 @@ PassRefPtr<HTMLFrameSetElement> HTMLFrameSetElement::create(const QualifiedName& return adoptRef(new HTMLFrameSetElement(tagName, document)); } +bool HTMLFrameSetElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == bordercolorAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLFrameSetElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == bordercolorAttr) + addHTMLColorToStyle(style, CSSPropertyBorderColor, attr->value()); + else + HTMLElement::collectStyleForAttribute(attr, style); +} + void HTMLFrameSetElement::parseAttribute(Attribute* attr) { if (attr->name() == rowsAttr) { @@ -98,13 +113,9 @@ void HTMLFrameSetElement::parseAttribute(Attribute* attr) m_borderSet = true; } else m_borderSet = false; - } else if (attr->name() == bordercolorAttr) { + } else if (attr->name() == bordercolorAttr) m_borderColorSet = !attr->isEmpty(); - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyBorderColor); - else - addCSSColor(CSSPropertyBorderColor, attr->value()); - } else if (attr->name() == onloadAttr) + else if (attr->name() == onloadAttr) document()->setWindowAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(document()->frame(), attr)); else if (attr->name() == onbeforeunloadAttr) document()->setWindowAttributeEventListener(eventNames().beforeunloadEvent, createAttributeEventListener(document()->frame(), attr)); diff --git a/Source/WebCore/html/HTMLFrameSetElement.h b/Source/WebCore/html/HTMLFrameSetElement.h index 187902396..1cd40a290 100644 --- a/Source/WebCore/html/HTMLFrameSetElement.h +++ b/Source/WebCore/html/HTMLFrameSetElement.h @@ -68,6 +68,8 @@ private: HTMLFrameSetElement(const QualifiedName&, Document*); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual void attach(); virtual bool rendererIsNeeded(const NodeRenderingContext&); diff --git a/Source/WebCore/html/HTMLHRElement.cpp b/Source/WebCore/html/HTMLHRElement.cpp index 5534b929f..8f8b6e140 100644 --- a/Source/WebCore/html/HTMLHRElement.cpp +++ b/Source/WebCore/html/HTMLHRElement.cpp @@ -26,6 +26,7 @@ #include "Attribute.h" #include "CSSPropertyNames.h" #include "CSSValueKeywords.h" +#include "CSSValuePool.h" #include "HTMLNames.h" namespace WebCore { @@ -48,70 +49,52 @@ PassRefPtr<HTMLHRElement> HTMLHRElement::create(const QualifiedName& tagName, Do return adoptRef(new HTMLHRElement(tagName, document)); } -void HTMLHRElement::parseAttribute(Attribute* attr) +bool HTMLHRElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == alignAttr || attr->name() == widthAttr || attr->name() == colorAttr || attr->name() == noshadeAttr || attr->name() == sizeAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLHRElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == alignAttr) { - if (attr->value().isNull()) { - removeCSSProperties(CSSPropertyMarginLeft, CSSPropertyMarginRight); - } else if (equalIgnoringCase(attr->value(), "left")) { - addCSSProperty(CSSPropertyMarginLeft, "0"); - addCSSProperty(CSSPropertyMarginRight, CSSValueAuto); + if (equalIgnoringCase(attr->value(), "left")) { + addPropertyToAttributeStyle(style, CSSPropertyMarginLeft, 0, CSSPrimitiveValue::CSS_PX); + addPropertyToAttributeStyle(style, CSSPropertyMarginRight, CSSValueAuto); } else if (equalIgnoringCase(attr->value(), "right")) { - addCSSProperty(CSSPropertyMarginLeft, CSSValueAuto); - addCSSProperty(CSSPropertyMarginRight, "0"); + addPropertyToAttributeStyle(style, CSSPropertyMarginLeft, CSSValueAuto); + addPropertyToAttributeStyle(style, CSSPropertyMarginRight, 0, CSSPrimitiveValue::CSS_PX); } else { - addCSSProperty(CSSPropertyMarginLeft, CSSValueAuto); - addCSSProperty(CSSPropertyMarginRight, CSSValueAuto); + addPropertyToAttributeStyle(style, CSSPropertyMarginLeft, CSSValueAuto); + addPropertyToAttributeStyle(style, CSSPropertyMarginRight, CSSValueAuto); } } else if (attr->name() == widthAttr) { - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyWidth); - else { - bool ok; - int v = attr->value().toInt(&ok); - if (ok && !v) - addCSSLength(CSSPropertyWidth, "1"); - else - addCSSLength(CSSPropertyWidth, attr->value()); - } + bool ok; + int v = attr->value().toInt(&ok); + if (ok && !v) + addPropertyToAttributeStyle(style, CSSPropertyWidth, 1, CSSPrimitiveValue::CSS_PX); + else + addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value()); } else if (attr->name() == colorAttr) { - if (attr->value().isNull()) - removeCSSProperties(CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle, CSSPropertyBorderColor, CSSPropertyBackgroundColor); - else { - addCSSProperty(CSSPropertyBorderTopStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderRightStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderBottomStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderLeftStyle, CSSValueSolid); - addCSSColor(CSSPropertyBorderColor, attr->value()); - addCSSColor(CSSPropertyBackgroundColor, attr->value()); - } + addPropertyToAttributeStyle(style, CSSPropertyBorderStyle, CSSValueSolid); + addHTMLColorToStyle(style, CSSPropertyBorderColor, attr->value()); + addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attr->value()); } else if (attr->name() == noshadeAttr) { - if (attr->value().isNull()) - removeCSSProperties(CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle, CSSPropertyBorderColor, CSSPropertyBackgroundColor); - else { - addCSSProperty(CSSPropertyBorderTopStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderRightStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderBottomStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderLeftStyle, CSSValueSolid); - addCSSColor(CSSPropertyBorderColor, String("grey")); - addCSSColor(CSSPropertyBackgroundColor, String("grey")); - } + addPropertyToAttributeStyle(style, CSSPropertyBorderStyle, CSSValueSolid); + + RefPtr<CSSPrimitiveValue> darkGrayValue = document()->cssValuePool()->createColorValue(Color::darkGray); + style->setProperty(CSSPropertyBorderColor, darkGrayValue); + style->setProperty(CSSPropertyBackgroundColor, darkGrayValue); } else if (attr->name() == sizeAttr) { - if (attr->value().isNull()) - removeCSSProperties(CSSPropertyBorderBottomWidth, CSSPropertyHeight); - else { - StringImpl* si = attr->value().impl(); - int size = si->toInt(); - if (size <= 1) { - addCSSProperty(CSSPropertyBorderBottomWidth, String("0")); - removeCSSProperty(CSSPropertyHeight); - } else { - addCSSLength(CSSPropertyHeight, String::number(size-2)); - removeCSSProperty(CSSPropertyBorderBottomWidth); - } - } + StringImpl* si = attr->value().impl(); + int size = si->toInt(); + if (size <= 1) + addPropertyToAttributeStyle(style, CSSPropertyBorderBottomWidth, 0, CSSPrimitiveValue::CSS_PX); + else + addPropertyToAttributeStyle(style, CSSPropertyHeight, size - 2, CSSPrimitiveValue::CSS_PX); } else - HTMLElement::parseAttribute(attr); + HTMLElement::collectStyleForAttribute(attr, style); } } diff --git a/Source/WebCore/html/HTMLHRElement.h b/Source/WebCore/html/HTMLHRElement.h index f05085b29..728619ac5 100644 --- a/Source/WebCore/html/HTMLHRElement.h +++ b/Source/WebCore/html/HTMLHRElement.h @@ -37,7 +37,8 @@ public: private: HTMLHRElement(const QualifiedName&, Document*); - virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; }; } // namespace WebCore diff --git a/Source/WebCore/html/HTMLIFrameElement.cpp b/Source/WebCore/html/HTMLIFrameElement.cpp index 5cba88842..a846fa432 100644 --- a/Source/WebCore/html/HTMLIFrameElement.cpp +++ b/Source/WebCore/html/HTMLIFrameElement.cpp @@ -48,15 +48,35 @@ PassRefPtr<HTMLIFrameElement> HTMLIFrameElement::create(const QualifiedName& tag return adoptRef(new HTMLIFrameElement(tagName, document)); } -void HTMLIFrameElement::parseAttribute(Attribute* attr) +bool HTMLIFrameElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == widthAttr || attr->name() == heightAttr || attr->name() == alignAttr || attr->name() == frameborderAttr) + return true; + return HTMLFrameElementBase::isPresentationAttribute(attr); +} + +void HTMLIFrameElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == widthAttr) - addCSSLength(CSSPropertyWidth, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value()); else if (attr->name() == heightAttr) - addCSSLength(CSSPropertyHeight, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value()); else if (attr->name() == alignAttr) - addHTMLAlignment(attr); - else if (attr->name() == nameAttr) { + applyAlignmentAttributeToStyle(attr, style); + 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. + addPropertyToAttributeStyle(style, CSSPropertyBorderWidth, 0, CSSPrimitiveValue::CSS_PX); + } + } else + HTMLFrameElementBase::collectStyleForAttribute(attr, style); +} + +void HTMLIFrameElement::parseAttribute(Attribute* attr) +{ + if (attr->name() == nameAttr) { const AtomicString& newName = attr->value(); if (inDocument() && document()->isHTMLDocument()) { HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); @@ -64,14 +84,6 @@ void HTMLIFrameElement::parseAttribute(Attribute* attr) document->addExtraNamedItem(newName); } 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(CSSPropertyBorderWidth, "0"); - } else - removeCSSProperty(CSSPropertyBorderWidth); } else if (attr->name() == sandboxAttr) setSandboxFlags(attr->isNull() ? SandboxNone : SecurityContext::parseSandboxPolicy(attr->value())); else diff --git a/Source/WebCore/html/HTMLIFrameElement.h b/Source/WebCore/html/HTMLIFrameElement.h index bcba2a257..075841091 100644 --- a/Source/WebCore/html/HTMLIFrameElement.h +++ b/Source/WebCore/html/HTMLIFrameElement.h @@ -36,6 +36,8 @@ private: HTMLIFrameElement(const QualifiedName&, Document*); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual void insertedIntoDocument(); virtual void removedFromDocument(); diff --git a/Source/WebCore/html/HTMLIFrameElement.idl b/Source/WebCore/html/HTMLIFrameElement.idl index 1e88269e0..25f9cb14b 100644 --- a/Source/WebCore/html/HTMLIFrameElement.idl +++ b/Source/WebCore/html/HTMLIFrameElement.idl @@ -34,14 +34,14 @@ module html { attribute [Reflect] DOMString width; // Introduced in DOM Level 2: - readonly attribute [CheckAccessToNode] Document contentDocument; + readonly attribute [CheckSecurityForNode] Document contentDocument; // Extensions readonly attribute DOMWindow contentWindow; #if defined(ENABLE_SVG) && ENABLE_SVG #if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C || defined(ENABLE_SVG_DOM_OBJC_BINDINGS) && ENABLE_SVG_DOM_OBJC_BINDINGS - [CheckAccessToNode] SVGDocument getSVGDocument() + [CheckSecurityForNode] SVGDocument getSVGDocument() raises(DOMException); #endif #endif diff --git a/Source/WebCore/html/HTMLImageElement.cpp b/Source/WebCore/html/HTMLImageElement.cpp index 6c22edc12..583a23fc8 100644 --- a/Source/WebCore/html/HTMLImageElement.cpp +++ b/Source/WebCore/html/HTMLImageElement.cpp @@ -78,6 +78,35 @@ PassRefPtr<HTMLImageElement> HTMLImageElement::createForJSConstructor(Document* return image.release(); } +bool HTMLImageElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == widthAttr || attr->name() == heightAttr || attr->name() == borderAttr || attr->name() == vspaceAttr || attr->name() == hspaceAttr || attr->name() == alignAttr || attr->name() == valignAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLImageElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == widthAttr) + addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value()); + else if (attr->name() == heightAttr) + addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value()); + else if (attr->name() == borderAttr) + applyBorderAttributeToStyle(attr, style); + else if (attr->name() == vspaceAttr) { + addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value()); + } else if (attr->name() == hspaceAttr) { + addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value()); + } else if (attr->name() == alignAttr) + applyAlignmentAttributeToStyle(attr, style); + else if (attr->name() == valignAttr) + addPropertyToAttributeStyle(style, CSSPropertyVerticalAlign, attr->value()); + else + HTMLElement::collectStyleForAttribute(attr, style); +} + void HTMLImageElement::parseAttribute(Attribute* attr) { const QualifiedName& attrName = attr->name(); @@ -86,40 +115,6 @@ void HTMLImageElement::parseAttribute(Attribute* attr) toRenderImage(renderer())->updateAltText(); } else if (attrName == srcAttr) m_imageLoader.updateFromElementIgnoringPreviousError(); - else if (attrName == widthAttr) - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyWidth); - else - addCSSLength(CSSPropertyWidth, attr->value()); - else if (attrName == heightAttr) - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyHeight); - else - addCSSLength(CSSPropertyHeight, attr->value()); - else if (attrName == borderAttr) { - // border="noborder" -> border="0" - applyBorderAttribute(attr); - } else if (attrName == vspaceAttr) { - if (attr->value().isNull()) - removeCSSProperties(CSSPropertyMarginTop, CSSPropertyMarginBottom); - else { - addCSSLength(CSSPropertyMarginTop, attr->value()); - addCSSLength(CSSPropertyMarginBottom, attr->value()); - } - } else if (attrName == hspaceAttr) { - if (attr->value().isNull()) - removeCSSProperties(CSSPropertyMarginLeft, CSSPropertyMarginRight); - else { - addCSSLength(CSSPropertyMarginLeft, attr->value()); - addCSSLength(CSSPropertyMarginRight, attr->value()); - } - } else if (attrName == alignAttr) - addHTMLAlignment(attr); - else if (attrName == valignAttr) - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyVerticalAlign); - else - addCSSProperty(CSSPropertyVerticalAlign, attr->value()); else if (attrName == usemapAttr) setIsLink(!attr->isNull()); else if (attrName == onabortAttr) diff --git a/Source/WebCore/html/HTMLImageElement.h b/Source/WebCore/html/HTMLImageElement.h index b24d348bb..37a23775a 100644 --- a/Source/WebCore/html/HTMLImageElement.h +++ b/Source/WebCore/html/HTMLImageElement.h @@ -84,6 +84,8 @@ protected: private: virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual void attach(); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); diff --git a/Source/WebCore/html/HTMLInputElement.cpp b/Source/WebCore/html/HTMLInputElement.cpp index 960040fdd..422ac8513 100644 --- a/Source/WebCore/html/HTMLInputElement.cpp +++ b/Source/WebCore/html/HTMLInputElement.cpp @@ -51,6 +51,7 @@ #include "RenderTextControlSingleLine.h" #include "RenderTheme.h" #include "SearchInputType.h" +#include "ShadowRoot.h" #include "ScriptEventListener.h" #include "WheelEvent.h" #include <wtf/MathExtras.h> @@ -108,6 +109,9 @@ PassRefPtr<HTMLInputElement> HTMLInputElement::create(const QualifiedName& tagNa void HTMLInputElement::createShadowSubtree() { + ASSERT(!hasShadowRoot()); + ShadowRoot::create(this, ShadowRoot::CreatingUserAgentShadowRoot, ASSERT_NO_EXCEPTION); + m_inputType->createShadowSubtree(); } @@ -349,7 +353,7 @@ bool HTMLInputElement::getAllowedValueStepWithDecimalPlaces(AnyStepHandling anyS return true; } -void HTMLInputElement::applyStep(double count, AnyStepHandling anyStepHandling, bool sendChangeEvent, ExceptionCode& ec) +void HTMLInputElement::applyStep(double count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionCode& ec) { double step; unsigned stepDecimalPlaces, currentDecimalPlaces; @@ -389,7 +393,7 @@ void HTMLInputElement::applyStep(double count, AnyStepHandling anyStepHandling, if (newValue > m_inputType->maximum()) newValue = m_inputType->maximum(); - setValueAsNumber(newValue, ec, sendChangeEvent); + setValueAsNumber(newValue, ec, eventBehavior); if (AXObjectCache::accessibilityEnabled()) document()->axObjectCache()->postNotification(renderer(), AXObjectCache::AXValueChanged, true); @@ -416,14 +420,12 @@ double HTMLInputElement::alignValueForStep(double newValue, double step, unsigne void HTMLInputElement::stepUp(int n, ExceptionCode& ec) { - bool sendChangeEvent = false; - applyStep(n, RejectAny, sendChangeEvent, ec); + applyStep(n, RejectAny, DispatchNoEvent, ec); } void HTMLInputElement::stepDown(int n, ExceptionCode& ec) { - bool sendChangeEvent = false; - applyStep(-n, RejectAny, sendChangeEvent, ec); + applyStep(-n, RejectAny, DispatchNoEvent, ec); } bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const @@ -545,7 +547,7 @@ void HTMLInputElement::updateType() registerForSuspensionCallbackIfNeeded(); if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) { - ASSERT(attributeMap()); + ASSERT(attributeData()); if (Attribute* height = getAttributeItem(heightAttr)) attributeChanged(height); if (Attribute* width = getAttributeItem(widthAttr)) @@ -658,6 +660,36 @@ void HTMLInputElement::accessKeyAction(bool sendMouseEvents) m_inputType->accessKeyAction(sendMouseEvents); } +bool HTMLInputElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == vspaceAttr || attr->name() == hspaceAttr || attr->name() == alignAttr || attr->name() == widthAttr || attr->name() == heightAttr || (attr->name() == borderAttr && isImageButton())) + return true; + return HTMLTextFormControlElement::isPresentationAttribute(attr); +} + +void HTMLInputElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == vspaceAttr) { + addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value()); + } else if (attr->name() == hspaceAttr) { + addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value()); + } else if (attr->name() == alignAttr) { + if (m_inputType->shouldRespectAlignAttribute()) + applyAlignmentAttributeToStyle(attr, style); + } else if (attr->name() == widthAttr) { + if (m_inputType->shouldRespectHeightAndWidthAttributes()) + addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value()); + } else if (attr->name() == heightAttr) { + if (m_inputType->shouldRespectHeightAndWidthAttributes()) + addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value()); + } else if (attr->name() == borderAttr && isImageButton()) + applyBorderAttributeToStyle(attr, style); + else + return HTMLTextFormControlElement::collectStyleForAttribute(attr, style); +} + void HTMLInputElement::parseAttribute(Attribute* attr) { if (attr->name() == nameAttr) { @@ -713,29 +745,6 @@ void HTMLInputElement::parseAttribute(Attribute* attr) m_inputType->srcAttributeChanged(); else if (attr->name() == usemapAttr || attr->name() == accesskeyAttr) { // FIXME: ignore for the moment - } else if (attr->name() == vspaceAttr) { - addCSSLength(CSSPropertyMarginTop, attr->value()); - addCSSLength(CSSPropertyMarginBottom, attr->value()); - } else if (attr->name() == hspaceAttr) { - addCSSLength(CSSPropertyMarginLeft, attr->value()); - addCSSLength(CSSPropertyMarginRight, attr->value()); - } else if (attr->name() == alignAttr) { - if (m_inputType->shouldRespectAlignAttribute()) - addHTMLAlignment(attr); - else - removeHTMLAlignment(); - } else if (attr->name() == widthAttr) { - if (m_inputType->shouldRespectHeightAndWidthAttributes()) - addCSSLength(CSSPropertyWidth, attr->value()); - else - removeCSSProperty(CSSPropertyWidth); - } else if (attr->name() == heightAttr) { - if (m_inputType->shouldRespectHeightAndWidthAttributes()) - addCSSLength(CSSPropertyHeight, attr->value()); - else - removeCSSProperty(CSSPropertyHeight); - } else if (attr->name() == borderAttr && isImageButton()) { - applyBorderAttribute(attr); } else if (attr->name() == onsearchAttr) { // Search field and slider attributes all just cause updateFromElement to be called through style recalcing. setAttributeEventListener(eventNames().searchEvent, createAttributeEventListener(this, attr)); @@ -900,7 +909,7 @@ bool HTMLInputElement::isTextType() const return m_inputType->isTextType(); } -void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent) +void HTMLInputElement::setChecked(bool nowChecked, TextFieldEventBehavior eventBehavior) { if (checked() == nowChecked) return; @@ -925,7 +934,7 @@ void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent) // unchecked to match other browsers. DOM is not a useful standard for this // because it says only to fire change events at "lose focus" time, which is // definitely wrong in practice for these types of elements. - if (sendChangeEvent && inDocument() && m_inputType->shouldSendChangeEventAfterCheckedChanged()) { + if (eventBehavior != DispatchNoEvent && inDocument() && m_inputType->shouldSendChangeEventAfterCheckedChanged()) { setTextAsOfLastFormControlChangeEvent(String()); dispatchFormControlChangeEvent(); } @@ -999,7 +1008,7 @@ String HTMLInputElement::valueWithDefault() const void HTMLInputElement::setValueForUser(const String& value) { // Call setValue and make it send a change event. - setValue(value, true); + setValue(value, DispatchChangeEvent); } const String& HTMLInputElement::suggestedValue() const @@ -1017,7 +1026,7 @@ void HTMLInputElement::setSuggestedValue(const String& value) updateInnerTextValue(); } -void HTMLInputElement::setValue(const String& value, bool sendChangeEvent) +void HTMLInputElement::setValue(const String& value, TextFieldEventBehavior eventBehavior) { if (!m_inputType->canSetValue(value)) return; @@ -1029,25 +1038,18 @@ void HTMLInputElement::setValue(const String& value, bool sendChangeEvent) setLastChangeWasNotUserEdit(); setFormControlValueMatchesRenderer(false); m_suggestedValue = String(); // Prevent TextFieldInputType::setValue from using the suggested value. - m_inputType->setValue(sanitizedValue, valueChanged, sendChangeEvent); + m_inputType->setValue(sanitizedValue, valueChanged, eventBehavior); if (!valueChanged) return; - if (sendChangeEvent) - m_inputType->dispatchChangeEventInResponseToSetValue(); - - // FIXME: Why do we do this when !sendChangeEvent? - if (isTextField() && (!focused() || !sendChangeEvent)) - setTextAsOfLastFormControlChangeEvent(value); - notifyFormStateChanged(); } -void HTMLInputElement::setValueInternal(const String& sanitizedValue, bool sendChangeEvent) +void HTMLInputElement::setValueInternal(const String& sanitizedValue, TextFieldEventBehavior eventBehavior) { m_valueIfDirty = sanitizedValue; - m_wasModifiedByUser = sendChangeEvent; + m_wasModifiedByUser = eventBehavior != DispatchNoEvent; setNeedsValidityCheck(); } @@ -1066,13 +1068,13 @@ double HTMLInputElement::valueAsNumber() const return m_inputType->valueAsNumber(); } -void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec, bool sendChangeEvent) +void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec, TextFieldEventBehavior eventBehavior) { if (!isfinite(newValue)) { ec = NOT_SUPPORTED_ERR; return; } - m_inputType->setValueAsNumber(newValue, sendChangeEvent, ec); + m_inputType->setValueAsNumber(newValue, eventBehavior, ec); } String HTMLInputElement::placeholder() const @@ -1626,7 +1628,6 @@ void HTMLInputElement::stepUpFromRenderer(int n) const double nan = numeric_limits<double>::quiet_NaN(); String currentStringValue = value(); double current = m_inputType->parseToDouble(currentStringValue, nan); - const bool sendChangeEvent = true; if (!isfinite(current)) { ExceptionCode ec; current = m_inputType->defaultValueForStepUp(); @@ -1635,10 +1636,10 @@ void HTMLInputElement::stepUpFromRenderer(int n) current = m_inputType->minimum() - nextDiff; if (current > m_inputType->maximum() - nextDiff) current = m_inputType->maximum() - nextDiff; - setValueAsNumber(current, ec, sendChangeEvent); + setValueAsNumber(current, ec, DispatchInputAndChangeEvent); } if ((sign > 0 && current < m_inputType->minimum()) || (sign < 0 && current > m_inputType->maximum())) - setValue(m_inputType->serialize(sign > 0 ? m_inputType->minimum() : m_inputType->maximum()), sendChangeEvent); + setValue(m_inputType->serialize(sign > 0 ? m_inputType->minimum() : m_inputType->maximum()), DispatchInputAndChangeEvent); else { ExceptionCode ec; if (stepMismatch(value())) { @@ -1658,14 +1659,14 @@ void HTMLInputElement::stepUpFromRenderer(int n) if (newValue > m_inputType->maximum()) newValue = m_inputType->maximum(); - setValueAsNumber(newValue, ec, n == 1 || n == -1); + setValueAsNumber(newValue, ec, n == 1 || n == -1 ? DispatchInputAndChangeEvent : DispatchNoEvent); current = newValue; if (n > 1) - applyStep(n - 1, AnyIsDefaultStep, sendChangeEvent, ec); + applyStep(n - 1, AnyIsDefaultStep, DispatchInputAndChangeEvent, ec); else if (n < -1) - applyStep(n + 1, AnyIsDefaultStep, sendChangeEvent, ec); + applyStep(n + 1, AnyIsDefaultStep, DispatchInputAndChangeEvent, ec); } else - applyStep(n, AnyIsDefaultStep, sendChangeEvent, ec); + applyStep(n, AnyIsDefaultStep, DispatchInputAndChangeEvent, ec); } } diff --git a/Source/WebCore/html/HTMLInputElement.h b/Source/WebCore/html/HTMLInputElement.h index b6fa0f623..39cb48ba6 100644 --- a/Source/WebCore/html/HTMLInputElement.h +++ b/Source/WebCore/html/HTMLInputElement.h @@ -121,7 +121,7 @@ public: virtual HTMLElement* placeholderElement() const; bool checked() const { return m_isChecked; } - void setChecked(bool, bool sendChangeEvent = false); + void setChecked(bool, TextFieldEventBehavior = DispatchNoEvent); // 'indeterminate' is a state independent of the checked state that causes the control to draw in a way that hides the actual state. bool indeterminate() const { return m_isIndeterminate; } @@ -136,7 +136,7 @@ public: void setType(const String&); String value() const; - void setValue(const String&, bool sendChangeEvent = false); + void setValue(const String&, TextFieldEventBehavior = DispatchNoEvent); void setValueForUser(const String&); // Checks if the specified string would be a valid value. // We should not call this for types with no string value such as CHECKBOX and RADIO. @@ -160,7 +160,7 @@ public: void setValueAsDate(double, ExceptionCode&); double valueAsNumber() const; - void setValueAsNumber(double, ExceptionCode&, bool sendChangeEvent = false); + void setValueAsNumber(double, ExceptionCode&, TextFieldEventBehavior = DispatchNoEvent); virtual String placeholder() const; virtual void setPlaceholder(const String&); @@ -225,7 +225,7 @@ public: // Otherwise, they would be private. CheckedRadioButtons& checkedRadioButtons() const; void updateCheckedRadioButtons(); - void setValueInternal(const String&, bool sendChangeEvent); + void setValueInternal(const String&, TextFieldEventBehavior); void cacheSelectionInResponseToSetValue(int caretOffset) { cacheSelection(caretOffset, caretOffset, SelectionHasNoDirection); } @@ -276,6 +276,8 @@ private: virtual void accessKeyAction(bool sendMouseEvents); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual void finishParsingChildren(); virtual void copyNonAttributeProperties(const Element* source); @@ -328,7 +330,7 @@ private: bool getAllowedValueStepWithDecimalPlaces(AnyStepHandling, double*, unsigned*) const; // Helper for stepUp()/stepDown(). Adds step value * count to the current value. - void applyStep(double count, AnyStepHandling, bool sendChangeEvent, ExceptionCode&); + void applyStep(double count, AnyStepHandling, TextFieldEventBehavior, ExceptionCode&); double alignValueForStep(double value, double step, unsigned currentDecimalPlaces, unsigned stepDecimalPlaces); #if ENABLE(DATALIST) diff --git a/Source/WebCore/html/HTMLInputElement.idl b/Source/WebCore/html/HTMLInputElement.idl index 4e218b96c..84beb8ac5 100644 --- a/Source/WebCore/html/HTMLInputElement.idl +++ b/Source/WebCore/html/HTMLInputElement.idl @@ -50,6 +50,7 @@ module html { attribute [Reflect] boolean readOnly; attribute [Reflect] boolean required; #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C + attribute [Reflect] DOMString accessKey; attribute [ObjCImplementedAsUnsignedLong] DOMString size; // DOM level 2 changed this to a long, but ObjC API is a string #else attribute unsigned long size; // Changed string -> long -> unsigned long @@ -74,7 +75,10 @@ module html { boolean checkValidity(); void setCustomValidity(in [TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString error); void select(); + +#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C void click(); +#endif #if !defined(LANGUAGE_JAVASCRIPT) || !LANGUAGE_JAVASCRIPT void setValueForUser(in [TreatNullAs=NullString] DOMString value); @@ -90,8 +94,8 @@ module html { #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C [Custom] void setSelectionRange(in long start, in long end); #else - [Custom] void setSelectionRange(in [Optional=CallWithDefaultValue] long start, - in [Optional=CallWithDefaultValue] long end, + [Custom] void setSelectionRange(in [Optional=DefaultIsUndefined] long start, + in [Optional=DefaultIsUndefined] long end, in [Optional] DOMString direction); #endif diff --git a/Source/WebCore/html/HTMLKeygenElement.cpp b/Source/WebCore/html/HTMLKeygenElement.cpp index 85252819a..e10079f64 100644 --- a/Source/WebCore/html/HTMLKeygenElement.cpp +++ b/Source/WebCore/html/HTMLKeygenElement.cpp @@ -33,6 +33,7 @@ #include "HTMLOptionElement.h" #include "SSLKeyGenerator.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include "Text.h" #include <wtf/StdLibExtras.h> @@ -85,7 +86,7 @@ inline HTMLKeygenElement::HTMLKeygenElement(const QualifiedName& tagName, Docume option->appendChild(Text::create(document, keys[i]), ec); } - ASSERT(!shadowRoot()); + ASSERT(!hasShadowRoot()); RefPtr<ShadowRoot> root = ShadowRoot::create(this, ShadowRoot::CreatingUserAgentShadowRoot); root->appendChild(select, ec); } @@ -130,8 +131,8 @@ void HTMLKeygenElement::reset() HTMLSelectElement* HTMLKeygenElement::shadowSelect() const { - ShadowRoot* shadow = shadowRoot(); - ASSERT(shadow); + ASSERT(hasShadowRoot()); + ShadowRoot* shadow = shadowRootList()->oldestShadowRoot(); return shadow ? toHTMLSelectElement(shadow->firstChild()) : 0; } diff --git a/Source/WebCore/html/HTMLLIElement.cpp b/Source/WebCore/html/HTMLLIElement.cpp index f789d32fe..ec7824ea4 100644 --- a/Source/WebCore/html/HTMLLIElement.cpp +++ b/Source/WebCore/html/HTMLLIElement.cpp @@ -49,26 +49,37 @@ PassRefPtr<HTMLLIElement> HTMLLIElement::create(const QualifiedName& tagName, Do return adoptRef(new HTMLLIElement(tagName, document)); } -void HTMLLIElement::parseAttribute(Attribute* attr) +bool HTMLLIElement::isPresentationAttribute(Attribute* attr) const { - if (attr->name() == valueAttr) { - if (renderer() && renderer()->isListItem()) - parseValue(attr->value()); - } else if (attr->name() == typeAttr) { - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyListStyleType); - else if (attr->value() == "a") - addCSSProperty(CSSPropertyListStyleType, CSSValueLowerAlpha); + if (attr->name() == typeAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLLIElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == typeAttr) { + if (attr->value() == "a") + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, CSSValueLowerAlpha); else if (attr->value() == "A") - addCSSProperty(CSSPropertyListStyleType, CSSValueUpperAlpha); + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, CSSValueUpperAlpha); else if (attr->value() == "i") - addCSSProperty(CSSPropertyListStyleType, CSSValueLowerRoman); + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, CSSValueLowerRoman); else if (attr->value() == "I") - addCSSProperty(CSSPropertyListStyleType, CSSValueUpperRoman); + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, CSSValueUpperRoman); else if (attr->value() == "1") - addCSSProperty(CSSPropertyListStyleType, CSSValueDecimal); + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, CSSValueDecimal); else - addCSSProperty(CSSPropertyListStyleType, attr->value()); + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, attr->value()); + } else + HTMLElement::collectStyleForAttribute(attr, style); +} + +void HTMLLIElement::parseAttribute(Attribute* attr) +{ + if (attr->name() == valueAttr) { + if (renderer() && renderer()->isListItem()) + parseValue(attr->value()); } else HTMLElement::parseAttribute(attr); } diff --git a/Source/WebCore/html/HTMLLIElement.h b/Source/WebCore/html/HTMLLIElement.h index 77a90e801..c730408a7 100644 --- a/Source/WebCore/html/HTMLLIElement.h +++ b/Source/WebCore/html/HTMLLIElement.h @@ -36,6 +36,8 @@ private: HTMLLIElement(const QualifiedName&, Document*); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual void attach(); diff --git a/Source/WebCore/html/HTMLLabelElement.idl b/Source/WebCore/html/HTMLLabelElement.idl index 9460418cd..bf79680f8 100644 --- a/Source/WebCore/html/HTMLLabelElement.idl +++ b/Source/WebCore/html/HTMLLabelElement.idl @@ -24,6 +24,9 @@ module html { readonly attribute HTMLFormElement form; attribute [Reflect=for] DOMString htmlFor; readonly attribute HTMLElement control; +#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C + attribute [Reflect] DOMString accessKey; +#endif }; } diff --git a/Source/WebCore/html/HTMLLegendElement.idl b/Source/WebCore/html/HTMLLegendElement.idl index 8cda34f58..bf755a5bb 100644 --- a/Source/WebCore/html/HTMLLegendElement.idl +++ b/Source/WebCore/html/HTMLLegendElement.idl @@ -23,6 +23,9 @@ module html { interface HTMLLegendElement : HTMLElement { readonly attribute HTMLFormElement form; attribute [Reflect] DOMString align; +#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C + attribute [Reflect] DOMString accessKey; +#endif }; } diff --git a/Source/WebCore/html/HTMLMarqueeElement.cpp b/Source/WebCore/html/HTMLMarqueeElement.cpp index 1d883b409..a1445ad55 100644 --- a/Source/WebCore/html/HTMLMarqueeElement.cpp +++ b/Source/WebCore/html/HTMLMarqueeElement.cpp @@ -35,83 +35,78 @@ namespace WebCore { using namespace HTMLNames; -// WinIE uses 60ms as the minimum delay by default. -const int defaultMinimumDelay = 60; - inline HTMLMarqueeElement::HTMLMarqueeElement(const QualifiedName& tagName, Document* document) : HTMLElement(tagName, document) , ActiveDOMObject(document, this) - , m_minimumDelay(defaultMinimumDelay) { ASSERT(hasTagName(marqueeTag)); } PassRefPtr<HTMLMarqueeElement> HTMLMarqueeElement::create(const QualifiedName& tagName, Document* document) { - return adoptRef(new HTMLMarqueeElement(tagName, document)); + RefPtr<HTMLMarqueeElement> marqueeElement(adoptRef(new HTMLMarqueeElement(tagName, document))); + marqueeElement->suspendIfNeeded(); + return marqueeElement.release(); +} + +int HTMLMarqueeElement::minimumDelay() const +{ + if (fastGetAttribute(truespeedAttr).isEmpty()) { + // WinIE uses 60ms as the minimum delay by default. + return 60; + } + return 0; +} + +bool HTMLMarqueeElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == widthAttr || attr->name() == heightAttr || attr->name() == bgcolorAttr || attr->name() == vspaceAttr || attr->name() == hspaceAttr || attr->name() == scrollamountAttr || attr->name() == scrolldelayAttr || attr->name() == loopAttr || attr->name() == behaviorAttr || attr->name() == directionAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); } -void HTMLMarqueeElement::parseAttribute(Attribute* attr) +void HTMLMarqueeElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == widthAttr) { - if (!attr->value().isEmpty()) - addCSSLength(CSSPropertyWidth, attr->value()); - else - removeCSSProperty(CSSPropertyWidth); + if (!attr->isEmpty()) + addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value()); } else if (attr->name() == heightAttr) { if (!attr->value().isEmpty()) - addCSSLength(CSSPropertyHeight, attr->value()); - else - removeCSSProperty(CSSPropertyHeight); + addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value()); } else if (attr->name() == bgcolorAttr) { if (!attr->value().isEmpty()) - addCSSColor(CSSPropertyBackgroundColor, attr->value()); - else - removeCSSProperty(CSSPropertyBackgroundColor); + addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attr->value()); } else if (attr->name() == vspaceAttr) { if (!attr->value().isEmpty()) { - addCSSLength(CSSPropertyMarginTop, attr->value()); - addCSSLength(CSSPropertyMarginBottom, attr->value()); - } else - removeCSSProperties(CSSPropertyMarginTop, CSSPropertyMarginBottom); + addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value()); + } } else if (attr->name() == hspaceAttr) { if (!attr->value().isEmpty()) { - addCSSLength(CSSPropertyMarginLeft, attr->value()); - addCSSLength(CSSPropertyMarginRight, attr->value()); - } else - removeCSSProperties(CSSPropertyMarginLeft, CSSPropertyMarginRight); + addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value()); + } } else if (attr->name() == scrollamountAttr) { if (!attr->value().isEmpty()) - addCSSLength(CSSPropertyWebkitMarqueeIncrement, attr->value()); - else - removeCSSProperty(CSSPropertyWebkitMarqueeIncrement); + addHTMLLengthToStyle(style, CSSPropertyWebkitMarqueeIncrement, attr->value()); } else if (attr->name() == scrolldelayAttr) { if (!attr->value().isEmpty()) - addCSSLength(CSSPropertyWebkitMarqueeSpeed, attr->value()); - else - removeCSSProperty(CSSPropertyWebkitMarqueeSpeed); + addHTMLLengthToStyle(style, CSSPropertyWebkitMarqueeSpeed, attr->value()); } else if (attr->name() == loopAttr) { if (!attr->value().isEmpty()) { if (attr->value() == "-1" || equalIgnoringCase(attr->value(), "infinite")) - addCSSProperty(CSSPropertyWebkitMarqueeRepetition, CSSValueInfinite); + addPropertyToAttributeStyle(style, CSSPropertyWebkitMarqueeRepetition, CSSValueInfinite); else - addCSSLength(CSSPropertyWebkitMarqueeRepetition, attr->value()); - } else - removeCSSProperty(CSSPropertyWebkitMarqueeRepetition); + addHTMLLengthToStyle(style, CSSPropertyWebkitMarqueeRepetition, attr->value()); + } } else if (attr->name() == behaviorAttr) { if (!attr->value().isEmpty()) - addCSSProperty(CSSPropertyWebkitMarqueeStyle, attr->value()); - else - removeCSSProperty(CSSPropertyWebkitMarqueeStyle); + addPropertyToAttributeStyle(style, CSSPropertyWebkitMarqueeStyle, attr->value()); } else if (attr->name() == directionAttr) { if (!attr->value().isEmpty()) - addCSSProperty(CSSPropertyWebkitMarqueeDirection, attr->value()); - else - removeCSSProperty(CSSPropertyWebkitMarqueeDirection); - } else if (attr->name() == truespeedAttr) - m_minimumDelay = !attr->isEmpty() ? 0 : defaultMinimumDelay; - else - HTMLElement::parseAttribute(attr); + addPropertyToAttributeStyle(style, CSSPropertyWebkitMarqueeDirection, attr->value()); + } else + HTMLElement::collectStyleForAttribute(attr, style); } void HTMLMarqueeElement::start() diff --git a/Source/WebCore/html/HTMLMarqueeElement.h b/Source/WebCore/html/HTMLMarqueeElement.h index d1e3070d2..8ababa1d9 100644 --- a/Source/WebCore/html/HTMLMarqueeElement.h +++ b/Source/WebCore/html/HTMLMarqueeElement.h @@ -34,7 +34,7 @@ class HTMLMarqueeElement : public HTMLElement, private ActiveDOMObject { public: static PassRefPtr<HTMLMarqueeElement> create(const QualifiedName&, Document*); - int minimumDelay() const { return m_minimumDelay; } + int minimumDelay() const; // DOM Functions @@ -53,7 +53,8 @@ public: private: HTMLMarqueeElement(const QualifiedName&, Document*); - virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; // ActiveDOMObject virtual bool canSuspend() const; @@ -61,8 +62,6 @@ private: virtual void resume(); RenderMarquee* renderMarquee() const; - - int m_minimumDelay; }; } // namespace WebCore diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp index 7e664840b..b956d66d9 100644 --- a/Source/WebCore/html/HTMLMediaElement.cpp +++ b/Source/WebCore/html/HTMLMediaElement.cpp @@ -63,19 +63,23 @@ #include "MediaQueryEvaluator.h" #include "MouseEvent.h" #include "MIMETypeRegistry.h" +#include "NodeRenderingContext.h" #include "Page.h" #include "RenderVideo.h" #include "RenderView.h" #include "ScriptController.h" #include "ScriptEventListener.h" #include "SecurityOrigin.h" +#include "SecurityPolicy.h" #include "Settings.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include "TimeRanges.h" #include "UUID.h" #include <limits> #include <wtf/CurrentTime.h> #include <wtf/MathExtras.h> +#include <wtf/NonCopyingSort.h> #include <wtf/Uint8Array.h> #include <wtf/text/CString.h> @@ -235,6 +239,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* docum #if ENABLE(VIDEO_TRACK) , m_tracksAreReady(true) , m_haveVisibleTextTrack(false) + , m_lastTextTrackUpdateTime(-1) , m_textTracks(0) , m_ignoreTrackDisplayUpdate(0) #endif @@ -320,14 +325,13 @@ bool HTMLMediaElement::isMouseFocusable() const return false; } -void HTMLMediaElement::attributeChanged(Attribute* attr) +void HTMLMediaElement::parseAttribute(Attribute* attr) { - HTMLElement::attributeChanged(attr); - const QualifiedName& attrName = attr->name(); + if (attrName == srcAttr) { // Trigger a reload, as long as the 'src' attribute is present. - if (!getAttribute(srcAttr).isEmpty()) + if (fastHasAttribute(srcAttr)) scheduleLoad(MediaResource); } else if (attrName == controlsAttr) configureMediaControls(); @@ -335,13 +339,7 @@ void HTMLMediaElement::attributeChanged(Attribute* attr) else if (attrName == loopAttr) updateDisableSleep(); #endif -} - -void HTMLMediaElement::parseAttribute(Attribute* attr) -{ - const QualifiedName& attrName = attr->name(); - - if (attrName == preloadAttr) { + else if (attrName == preloadAttr) { String value = attr->value(); if (equalIgnoringCase(value, "none")) @@ -467,7 +465,12 @@ RenderObject* HTMLMediaElement::createRenderer(RenderArena* arena, RenderStyle*) return new (arena) RenderMedia(this); #endif } - + +bool HTMLMediaElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const +{ + return childContext.isOnEncapsulationBoundary() && HTMLElement::childShouldCreateRenderer(childContext); +} + void HTMLMediaElement::insertedIntoDocument() { LOG(Media, "HTMLMediaElement::insertedIntoDocument"); @@ -554,6 +557,11 @@ void HTMLMediaElement::scheduleEvent(const AtomicString& eventName) void HTMLMediaElement::loadTimerFired(Timer<HTMLMediaElement>*) { +#if ENABLE(VIDEO_TRACK) + if (m_pendingLoadFlags & TextTrackResource) + configureNewTextTracks(); +#endif + if (m_pendingLoadFlags & MediaResource) { if (m_loadState == LoadingFromSourceElement) loadNextSourceChild(); @@ -561,11 +569,6 @@ void HTMLMediaElement::loadTimerFired(Timer<HTMLMediaElement>*) loadInternal(); } -#if ENABLE(VIDEO_TRACK) - if (m_pendingLoadFlags & TextTrackResource) - configureNewTextTracks(); -#endif - m_pendingLoadFlags = 0; } @@ -674,6 +677,9 @@ void HTMLMediaElement::prepareForLoad() invalidateCachedTime(); scheduleEvent(eventNames().emptiedEvent); updateMediaController(); +#if ENABLE(VIDEO_TRACK) + updateActiveTextTrackCues(0); +#endif } // 5 - Set the playbackRate attribute to the value of the defaultPlaybackRate attribute. @@ -702,19 +708,6 @@ void HTMLMediaElement::prepareForLoad() // event may have already fired by then. setShouldDelayLoadEvent(true); -#if ENABLE(VIDEO_TRACK) - // HTMLMediaElement::textTracksAreReady will need "... the text tracks whose mode was not in the - // disabled state when the element's resource selection algorithm last started". - m_textTracksWhenResourceSelectionBegan.clear(); - if (m_textTracks) { - for (unsigned i = 0; i < m_textTracks->length(); ++i) { - TextTrack* track = m_textTracks->item(i); - if (track->mode() != TextTrack::DISABLED) - m_textTracksWhenResourceSelectionBegan.append(track); - } - } -#endif - configureMediaControls(); } @@ -735,6 +728,19 @@ void HTMLMediaElement::loadInternal() // put in the the background. removeBehaviorRestriction(RequirePageConsentToLoadMediaRestriction); +#if ENABLE(VIDEO_TRACK) + // HTMLMediaElement::textTracksAreReady will need "... the text tracks whose mode was not in the + // disabled state when the element's resource selection algorithm last started". + m_textTracksWhenResourceSelectionBegan.clear(); + if (m_textTracks) { + for (unsigned i = 0; i < m_textTracks->length(); ++i) { + TextTrack* track = m_textTracks->item(i); + if (track->mode() != TextTrack::DISABLED) + m_textTracksWhenResourceSelectionBegan.append(track); + } + } +#endif + selectMediaResource(); } @@ -937,33 +943,237 @@ void HTMLMediaElement::loadResource(const KURL& initialURL, ContentType& content } #if ENABLE(VIDEO_TRACK) +static bool trackIndexCompare(TextTrack* a, + TextTrack* b) +{ + return a->trackIndex() - b->trackIndex() < 0; +} + +static bool eventTimeCueCompare(const std::pair<double, TextTrackCue*>& a, + const std::pair<double, TextTrackCue*>& b) +{ + // 12 - Sort the tasks in events in ascending time order (tasks with earlier + // times first). + if (a.first != b.first) + return a.first - b.first < 0; + + // If the cues belong to different text tracks, it doesn't make sense to + // compare the two tracks by the relative cue order, so return the relative + // track order. + if (a.second->track() != b.second->track()) + return trackIndexCompare(a.second->track(), b.second->track()); + + // 12 - Further sort tasks in events that have the same time by the + // relative text track cue order of the text track cues associated + // with these tasks. + return a.second->cueIndex() - b.second->cueIndex() < 0; +} + + void HTMLMediaElement::updateActiveTextTrackCues(float movieTime) { + LOG(Media, "HTMLMediaElement::updateActiveTextTracks"); + + // 4.8.10.8 Playing the media resource + + // If the current playback position changes while the steps are running, + // then the user agent must wait for the steps to complete, and then must + // immediately rerun the steps. if (ignoreTrackDisplayUpdateRequests()) return; - - CueList previouslyActiveCues = m_currentlyActiveCues; - bool activeSetChanged = false; - m_currentlyActiveCues = m_cueTree.allOverlaps(m_cueTree.createInterval(movieTime, movieTime)); - - // FIXME(72171): Events need to be sorted and filtered before dispatching. - - for (size_t i = 0; i < previouslyActiveCues.size(); ++i) { - if (!m_currentlyActiveCues.contains(previouslyActiveCues[i])) { - previouslyActiveCues[i].data()->setIsActive(false); - activeSetChanged = true; + // 1 - Let current cues be a list of cues, initialized to contain all the + // cues of all the hidden, showing, or showing by default text tracks of the + // media element (not the disabled ones) whose start times are less than or + // equal to the current playback position and whose end times are greater + // than the current playback position. + Vector<CueIntervalTree::IntervalType> currentCues; + + // The user agent must synchronously unset [the text track cue active] flag + // whenever ... the media element's readyState is changed back to HAVE_NOTHING. + if (m_readyState != HAVE_NOTHING && m_player) + currentCues = m_cueTree.allOverlaps(m_cueTree.createInterval(movieTime, movieTime)); + + Vector<CueIntervalTree::IntervalType> affectedCues; + Vector<CueIntervalTree::IntervalType> previousCues; + Vector<CueIntervalTree::IntervalType> missedCues; + + // 2 - Let other cues be a list of cues, initialized to contain all the cues + // of hidden, showing, and showing by default text tracks of the media + // element that are not present in current cues. + previousCues = m_currentlyActiveCues; + + // 3 - Let last time be the current playback position at the time this + // algorithm was last run for this media element, if this is not the first + // time it has run. + float lastTime = m_lastTextTrackUpdateTime; + + // 4 - If the current playback position has, since the last time this + // algorithm was run, only changed through its usual monotonic increase + // during normal playback, then let missed cues be the list of cues in other + // cues whose start times are greater than or equal to last time and whose + // end times are less than or equal to the current playback position. + // Otherwise, let missed cues be an empty list. + if (lastTime >= 0 && m_lastSeekTime < movieTime) { + Vector<CueIntervalTree::IntervalType> potentiallySkippedCues = + m_cueTree.allOverlaps(m_cueTree.createInterval(lastTime, movieTime)); + + for (size_t i = 0; i < potentiallySkippedCues.size(); ++i) { + float cueStartTime = potentiallySkippedCues[i].low(); + float cueEndTime = potentiallySkippedCues[i].high(); + + // Consider cues that may have been missed since the last seek time. + if (cueStartTime > max(m_lastSeekTime, lastTime) && cueEndTime < movieTime) + missedCues.append(potentiallySkippedCues[i]); } } - for (size_t i = 0; i < m_currentlyActiveCues.size(); ++i) { - if (!previouslyActiveCues.contains(m_currentlyActiveCues[i])) { - m_currentlyActiveCues[i].data()->setIsActive(true); + + m_lastTextTrackUpdateTime = movieTime; + + // 5 - If the time was reached through the usual monotonic increase of the + // current playback position during normal playback, and if the user agent + // has not fired a timeupdate event at the element in the past 15 to 250ms + // and is not still running event handlers for such an event, then the user + // agent must queue a task to fire a simple event named timeupdate at the + // element. (In the other cases, such as explicit seeks, relevant events get + // fired as part of the overall process of changing the current playback + // position.) + if (m_lastSeekTime <= lastTime) + scheduleTimeupdateEvent(false); + + // Explicitly cache vector sizes, as their content is constant from here. + size_t currentCuesSize = currentCues.size(); + size_t missedCuesSize = missedCues.size(); + size_t previousCuesSize = previousCues.size(); + + // 6 - If all of the cues in current cues have their text track cue active + // flag set, none of the cues in other cues have their text track cue active + // flag set, and missed cues is empty, then abort these steps. + bool activeSetChanged = missedCuesSize; + + for (size_t i = 0; !activeSetChanged && i < previousCuesSize; ++i) + if (!currentCues.contains(previousCues[i]) && previousCues[i].data()->isActive()) + activeSetChanged = true; + + for (size_t i = 0; !activeSetChanged && i < currentCuesSize; ++i) { + if (!currentCues[i].data()->isActive()) activeSetChanged = true; - } } - - // FIXME(72173): Pause the media element for cues going past their endTime - // during a monotonic time increase. + + if (!activeSetChanged) + return; + + // 7 - If the time was reached through the usual monotonic increase of the + // current playback position during normal playback, and there are cues in + // other cues that have their text track cue pause-on-exi flag set and that + // either have their text track cue active flag set or are also in missed + // cues, then immediately pause the media element. + for (size_t i = 0; !m_paused && i < previousCuesSize; ++i) { + if (previousCues[i].data()->pauseOnExit() + && previousCues[i].data()->isActive() + && !currentCues.contains(previousCues[i])) + pause(); + } + + for (size_t i = 0; !m_paused && i < missedCuesSize; ++i) { + if (missedCues[i].data()->pauseOnExit()) + pause(); + } + + // 8 - Let events be a list of tasks, initially empty. Each task in this + // list will be associated with a text track, a text track cue, and a time, + // which are used to sort the list before the tasks are queued. + Vector<std::pair<double, TextTrackCue*> > eventTasks; + + // 8 - Let affected tracks be a list of text tracks, initially empty. + Vector<TextTrack*> affectedTracks; + + for (size_t i = 0; i < missedCuesSize; ++i) { + // 9 - For each text track cue in missed cues, prepare an event named enter + // for the TextTrackCue object with the text track cue start time. + eventTasks.append(std::make_pair(missedCues[i].data()->startTime(), + missedCues[i].data())); + + // 10 - For each text track in missed cues, prepare an event + // named exit for the TextTrackCue object with the text track cue end + // time. + eventTasks.append(std::make_pair(missedCues[i].data()->endTime(), + missedCues[i].data())); + } + + for (size_t i = 0; i < previousCuesSize; ++i) { + // 10 - For each text track cue in other cues that has its text + // track cue active flag set prepare an event named exit for the + // TextTrackCue object with the text track cue end time. + if (!currentCues.contains(previousCues[i])) + eventTasks.append(std::make_pair(previousCues[i].data()->endTime(), + previousCues[i].data())); + } + + for (size_t i = 0; i < currentCuesSize; ++i) { + // 11 - For each text track cue in current cues that does not have its + // text track cue active flag set, prepare an event named enter for the + // TextTrackCue object with the text track cue start time. + if (!previousCues.contains(currentCues[i])) + eventTasks.append(std::make_pair(currentCues[i].data()->startTime(), + currentCues[i].data())); + } + + // 12 - Sort the tasks in events in ascending time order (tasks with earlier + // times first). + nonCopyingSort(eventTasks.begin(), eventTasks.end(), eventTimeCueCompare); + + for (size_t i = 0; i < eventTasks.size(); ++i) { + if (!affectedTracks.contains(eventTasks[i].second->track())) + affectedTracks.append(eventTasks[i].second->track()); + + // 13 - Queue each task in events, in list order. + RefPtr<Event> event; + + // Each event in eventTasks may be either an enterEvent or an exitEvent, + // depending on the time that is associated with the event. This + // correctly identifies the type of the event, since the startTime is + // always less than the endTime. + if (eventTasks[i].first == eventTasks[i].second->startTime()) + event = Event::create(eventNames().enterEvent, false, false); + else + event = Event::create(eventNames().exitEvent, false, false); + + event->setTarget(eventTasks[i].second); + m_asyncEventQueue.enqueueEvent(event.release()); + } + + // 14 - Sort affected tracks in the same order as the text tracks appear in + // the media element's list of text tracks, and remove duplicates. + nonCopyingSort(affectedTracks.begin(), affectedTracks.end(), trackIndexCompare); + + // 15 - For each text track in affected tracks, in the list order, queue a + // task to fire a simple event named cuechange at the TextTrack object, and, + // if the text track has a corresponding track element, to then fire a + // simple event named cuechange at the track element as well. + for (size_t i = 0; i < affectedTracks.size(); ++i) { + RefPtr<Event> event = Event::create(eventNames().cuechangeEvent, false, false); + event->setTarget(affectedTracks[i]); + + m_asyncEventQueue.enqueueEvent(event.release()); + + // Fire syncronous cue change event for track elements. + if (affectedTracks[i]->trackType() == TextTrack::TrackElement) + affectedTracks[i]->fireCueChangeEvent(); + } + + // 16 - Set the text track cue active flag of all the cues in the current + // cues, and unset the text track cue active flag of all the cues in the + // other cues. + for (size_t i = 0; i < currentCuesSize; ++i) + currentCues[i].data()->setIsActive(true); + + for (size_t i = 0; i < previousCuesSize; ++i) + if (!currentCues.contains(previousCues[i])) + previousCues[i].data()->setIsActive(false); + + // Update the current active cues. + m_currentlyActiveCues = currentCues; if (activeSetChanged && hasMediaControls()) mediaControls()->updateTextTrackDisplay(); @@ -1313,21 +1523,32 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) bool wasPotentiallyPlaying = potentiallyPlaying(); ReadyState oldState = m_readyState; - m_readyState = static_cast<ReadyState>(state); + ReadyState newState = static_cast<ReadyState>(state); #if ENABLE(VIDEO_TRACK) bool tracksAreReady = textTracksAreReady(); - if (m_readyState == oldState && m_tracksAreReady == tracksAreReady) + if (newState == oldState && m_tracksAreReady == tracksAreReady) return; m_tracksAreReady = tracksAreReady; #else - if (m_readyState == oldState) + if (newState == oldState) return; bool tracksAreReady = true; #endif + if (tracksAreReady) + m_readyState = newState; + else { + // If a media file has text tracks the readyState may not progress beyond HAVE_FUTURE_DATA until + // the text tracks are ready, regardless of the state of the media file. + if (newState <= HAVE_METADATA) + m_readyState = newState; + else + m_readyState = HAVE_CURRENT_DATA; + } + if (oldState > m_readyStateMaximum) m_readyStateMaximum = oldState; @@ -1350,7 +1571,7 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) } } - if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA && tracksAreReady) { + if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { prepareMediaFragmentURI(); scheduleEvent(eventNames().durationchangeEvent); scheduleEvent(eventNames().loadedmetadataEvent); @@ -1362,7 +1583,7 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) bool shouldUpdateDisplayState = false; - if (m_readyState >= HAVE_CURRENT_DATA && oldState < HAVE_CURRENT_DATA && !m_haveFiredLoadedData && tracksAreReady) { + if (m_readyState >= HAVE_CURRENT_DATA && oldState < HAVE_CURRENT_DATA && !m_haveFiredLoadedData) { m_haveFiredLoadedData = true; shouldUpdateDisplayState = true; scheduleEvent(eventNames().loadeddataEvent); @@ -1405,6 +1626,9 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) updatePlayState(); updateMediaController(); +#if ENABLE(VIDEO_TRACK) + updateActiveTextTrackCues(currentTime()); +#endif } #if ENABLE(MEDIA_SOURCE) @@ -2680,6 +2904,10 @@ void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*) { LOG(Media, "HTMLMediaElement::mediaPlayerTimeChanged"); +#if ENABLE(VIDEO_TRACK) + updateActiveTextTrackCues(currentTime()); +#endif + beginProcessingMediaPlayerCallback(); invalidateCachedTime(); @@ -2728,9 +2956,6 @@ void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*) m_sentEndEvent = false; updatePlayState(); -#if ENABLE(VIDEO_TRACK) - updateActiveTextTrackCues(now); -#endif endProcessingMediaPlayerCallback(); } @@ -3143,6 +3368,9 @@ void HTMLMediaElement::userCancelledLoad() // Reset m_readyState since m_player is gone. m_readyState = HAVE_NOTHING; updateMediaController(); +#if ENABLE(VIDEO_TRACK) + updateActiveTextTrackCues(0); +#endif } bool HTMLMediaElement::canSuspend() const @@ -3519,15 +3747,15 @@ void HTMLMediaElement::privateBrowsingStateDidChange() MediaControls* HTMLMediaElement::mediaControls() { - return toMediaControls(shadowRoot()->firstChild()); + return toMediaControls(shadowRootList()->oldestShadowRoot()->firstChild()); } bool HTMLMediaElement::hasMediaControls() { - if (!shadowRoot()) + if (!hasShadowRoot()) return false; - Node* node = shadowRoot()->firstChild(); + Node* node = shadowRootList()->oldestShadowRoot()->firstChild(); return node && node->isMediaControls(); } @@ -3816,6 +4044,14 @@ bool HTMLMediaElement::shouldDisableSleep() const } #endif +String HTMLMediaElement::mediaPlayerReferrer() const +{ + Frame* frame = document()->frame(); + if (!frame) + return String(); + + return SecurityPolicy::generateReferrerHeader(document()->referrerPolicy(), m_currentSrc, frame->loader()->outgoingReferrer()); } +} #endif diff --git a/Source/WebCore/html/HTMLMediaElement.h b/Source/WebCore/html/HTMLMediaElement.h index 76c24cbab..126b78f57 100644 --- a/Source/WebCore/html/HTMLMediaElement.h +++ b/Source/WebCore/html/HTMLMediaElement.h @@ -337,9 +337,9 @@ private: virtual bool supportsFocus() const; virtual bool isMouseFocusable() const; - virtual void attributeChanged(Attribute*) OVERRIDE; virtual bool rendererIsNeeded(const NodeRenderingContext&); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE; virtual void insertedIntoDocument(); virtual void removedFromDocument(); virtual void didRecalcStyle(StyleChange); @@ -389,6 +389,8 @@ private: virtual String mediaPlayerSourceURL() const; #endif + virtual String mediaPlayerReferrer() const OVERRIDE; + void loadTimerFired(Timer<HTMLMediaElement>*); void progressEventTimerFired(Timer<HTMLMediaElement>*); void playbackProgressTimerFired(Timer<HTMLMediaElement>*); @@ -595,10 +597,13 @@ private: #if ENABLE(VIDEO_TRACK) bool m_tracksAreReady : 1; bool m_haveVisibleTextTrack : 1; + float m_lastTextTrackUpdateTime; RefPtr<TextTrackList> m_textTracks; Vector<RefPtr<TextTrack> > m_textTracksWhenResourceSelectionBegan; + CueIntervalTree m_cueTree; + CueList m_currentlyActiveCues; int m_ignoreTrackDisplayUpdate; #endif diff --git a/Source/WebCore/html/HTMLMediaElement.idl b/Source/WebCore/html/HTMLMediaElement.idl index 4260c2025..55d06f3ca 100644 --- a/Source/WebCore/html/HTMLMediaElement.idl +++ b/Source/WebCore/html/HTMLMediaElement.idl @@ -46,7 +46,7 @@ module html { readonly attribute TimeRanges buffered; void load() raises (DOMException); - DOMString canPlayType(in [Optional=CallWithDefaultValue] DOMString type); + DOMString canPlayType(in [Optional=DefaultIsUndefined] DOMString type); // ready state const unsigned short HAVE_NOTHING = 0; @@ -117,7 +117,7 @@ module html { readonly attribute [V8EnabledAtRuntime=webkitVideoTrack] TextTrackList textTracks; #endif - attribute [Reflect, TreatNullAs=NullString, ConvertNullStringToNull] DOMString mediaGroup; + attribute [Reflect, TreatNullAs=NullString] DOMString mediaGroup; attribute [CustomSetter] MediaController controller; }; } diff --git a/Source/WebCore/html/HTMLMetaElement.cpp b/Source/WebCore/html/HTMLMetaElement.cpp index fd1f40392..820ad4471 100644 --- a/Source/WebCore/html/HTMLMetaElement.cpp +++ b/Source/WebCore/html/HTMLMetaElement.cpp @@ -94,7 +94,7 @@ String HTMLMetaElement::httpEquiv() const String HTMLMetaElement::name() const { - return getAttribute(nameAttr); + return getNameAttribute(); } #if ENABLE(MICRODATA) diff --git a/Source/WebCore/html/HTMLMeterElement.cpp b/Source/WebCore/html/HTMLMeterElement.cpp index a1fdaf6c7..3be84e33d 100644 --- a/Source/WebCore/html/HTMLMeterElement.cpp +++ b/Source/WebCore/html/HTMLMeterElement.cpp @@ -26,6 +26,7 @@ #include "EventNames.h" #include "ExceptionCode.h" #include "FormDataList.h" +#include "NodeRenderingContext.h" #include "HTMLFormElement.h" #include "HTMLNames.h" #include "HTMLParserIdioms.h" @@ -60,6 +61,11 @@ RenderObject* HTMLMeterElement::createRenderer(RenderArena* arena, RenderStyle*) return new (arena) RenderMeter(this); } +bool HTMLMeterElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const +{ + return childContext.isOnEncapsulationBoundary() && HTMLElement::childShouldCreateRenderer(childContext); +} + const AtomicString& HTMLMeterElement::formControlType() const { DEFINE_STATIC_LOCAL(const AtomicString, meter, ("meter")); @@ -234,7 +240,7 @@ void HTMLMeterElement::didElementStateChange() void HTMLMeterElement::createShadowSubtree() { - ASSERT(!shadowRoot()); + ASSERT(!hasShadowRoot()); RefPtr<MeterBarElement> bar = MeterBarElement::create(document()); m_value = MeterValueElement::create(document()); diff --git a/Source/WebCore/html/HTMLMeterElement.h b/Source/WebCore/html/HTMLMeterElement.h index fb71bc922..dc5e7ccf5 100644 --- a/Source/WebCore/html/HTMLMeterElement.h +++ b/Source/WebCore/html/HTMLMeterElement.h @@ -70,6 +70,7 @@ private: virtual bool recalcWillValidate() const { return false; } virtual const AtomicString& formControlType() const; virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE; virtual void parseAttribute(Attribute*) OVERRIDE; virtual void attach(); diff --git a/Source/WebCore/html/HTMLNameCollection.cpp b/Source/WebCore/html/HTMLNameCollection.cpp index aaf5b4d02..280c800a7 100644 --- a/Source/WebCore/html/HTMLNameCollection.cpp +++ b/Source/WebCore/html/HTMLNameCollection.cpp @@ -61,7 +61,7 @@ Element* HTMLNameCollection::itemAfter(Element* previous) const e->hasTagName(appletTag) || e->hasTagName(embedTag) || e->hasTagName(objectTag)) - if (e->getAttribute(nameAttr) == m_name) + if (e->getNameAttribute() == m_name) return e; if (e->getIdAttribute() == m_name) return e; @@ -71,17 +71,17 @@ Element* HTMLNameCollection::itemAfter(Element* previous) const // applets and object by id, and images by id but only if they have // a name attribute (this very strange rule matches IE) if (e->hasTagName(formTag) || e->hasTagName(embedTag) || e->hasTagName(iframeTag)) { - if (e->getAttribute(nameAttr) == m_name) + if (e->getNameAttribute() == m_name) return e; } else if (e->hasTagName(appletTag)) { - if (e->getAttribute(nameAttr) == m_name || e->getIdAttribute() == m_name) + if (e->getNameAttribute() == m_name || e->getIdAttribute() == m_name) return e; } else if (e->hasTagName(objectTag)) { - if ((e->getAttribute(nameAttr) == m_name || e->getIdAttribute() == m_name) + if ((e->getNameAttribute() == m_name || e->getIdAttribute() == m_name) && static_cast<HTMLObjectElement*>(e)->isDocNamedItem()) return e; } else if (e->hasTagName(imgTag)) { - if (e->getAttribute(nameAttr) == m_name || (e->getIdAttribute() == m_name && e->hasAttribute(nameAttr))) + if (e->getNameAttribute() == m_name || (e->getIdAttribute() == m_name && e->hasName())) return e; } break; diff --git a/Source/WebCore/html/HTMLOListElement.cpp b/Source/WebCore/html/HTMLOListElement.cpp index 2bfa2ff43..1f7e28dfe 100644 --- a/Source/WebCore/html/HTMLOListElement.cpp +++ b/Source/WebCore/html/HTMLOListElement.cpp @@ -54,22 +54,33 @@ PassRefPtr<HTMLOListElement> HTMLOListElement::create(const QualifiedName& tagNa return adoptRef(new HTMLOListElement(tagName, document)); } -void HTMLOListElement::parseAttribute(Attribute* attr) +bool HTMLOListElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == typeAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLOListElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == typeAttr) { if (attr->value() == "a") - addCSSProperty(CSSPropertyListStyleType, CSSValueLowerAlpha); + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, CSSValueLowerAlpha); else if (attr->value() == "A") - addCSSProperty(CSSPropertyListStyleType, CSSValueUpperAlpha); + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, CSSValueUpperAlpha); else if (attr->value() == "i") - addCSSProperty(CSSPropertyListStyleType, CSSValueLowerRoman); + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, CSSValueLowerRoman); else if (attr->value() == "I") - addCSSProperty(CSSPropertyListStyleType, CSSValueUpperRoman); + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, CSSValueUpperRoman); else if (attr->value() == "1") - addCSSProperty(CSSPropertyListStyleType, CSSValueDecimal); - else - removeCSSProperty(CSSPropertyListStyleType); - } else if (attr->name() == startAttr) { + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, CSSValueDecimal); + } else + HTMLElement::collectStyleForAttribute(attr, style); +} + +void HTMLOListElement::parseAttribute(Attribute* attr) +{ + if (attr->name() == startAttr) { int oldStart = start(); bool canParse; int parsedStart = attr->value().toInt(&canParse); diff --git a/Source/WebCore/html/HTMLOListElement.h b/Source/WebCore/html/HTMLOListElement.h index 0731fb007..9f0eafb0b 100644 --- a/Source/WebCore/html/HTMLOListElement.h +++ b/Source/WebCore/html/HTMLOListElement.h @@ -54,6 +54,8 @@ private: void recalculateItemCount(); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; int m_start; unsigned m_itemCount; diff --git a/Source/WebCore/html/HTMLObjectElement.cpp b/Source/WebCore/html/HTMLObjectElement.cpp index e2bef0157..406a3eb3e 100644 --- a/Source/WebCore/html/HTMLObjectElement.cpp +++ b/Source/WebCore/html/HTMLObjectElement.cpp @@ -77,6 +77,21 @@ RenderWidget* HTMLObjectElement::renderWidgetForJSBindings() return renderPart(); // This will return 0 if the renderer is not a RenderPart. } +bool HTMLObjectElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == borderAttr) + return true; + return HTMLPlugInImageElement::isPresentationAttribute(attr); +} + +void HTMLObjectElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == borderAttr) + applyBorderAttributeToStyle(attr, style); + else + HTMLPlugInImageElement::collectStyleForAttribute(attr, style); +} + void HTMLObjectElement::parseAttribute(Attribute* attr) { if (attr->name() == formAttr) @@ -108,8 +123,6 @@ void HTMLObjectElement::parseAttribute(Attribute* attr) setAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(this, attr)); else if (attr->name() == onbeforeloadAttr) setAttributeEventListener(eventNames().beforeloadEvent, createAttributeEventListener(this, attr)); - else if (attr->name() == borderAttr) - applyBorderAttribute(attr); else HTMLPlugInImageElement::parseAttribute(attr); } @@ -207,7 +220,7 @@ bool HTMLObjectElement::hasFallbackContent() const for (Node* child = firstChild(); child; child = child->nextSibling()) { // Ignore whitespace-only text, and <param> tags, any other content is fallback content. if (child->isTextNode()) { - if (!static_cast<Text*>(child)->containsOnlyWhitespace()) + if (!toText(child)->containsOnlyWhitespace()) return true; } else if (!child->hasTagName(paramTag)) return true; @@ -300,7 +313,7 @@ void HTMLObjectElement::updateWidget(PluginCreationOption pluginCreationOption) return; SubframeLoader* loader = document()->frame()->loader()->subframeLoader(); - bool success = beforeLoadAllowedLoad && hasValidClassId() && loader->requestObject(this, url, getAttribute(nameAttr), serviceType, paramNames, paramValues); + bool success = beforeLoadAllowedLoad && hasValidClassId() && loader->requestObject(this, url, getNameAttribute(), serviceType, paramNames, paramValues); if (!success && fallbackContent) renderFallbackContent(); } @@ -414,7 +427,7 @@ void HTMLObjectElement::updateDocNamedItem() if (isRecognizedTagName(element->tagQName()) && !element->hasTagName(paramTag)) isNamedItem = false; } else if (child->isTextNode()) { - if (!static_cast<Text*>(child)->containsOnlyWhitespace()) + if (!toText(child)->containsOnlyWhitespace()) isNamedItem = false; } else isNamedItem = false; @@ -423,10 +436,10 @@ void HTMLObjectElement::updateDocNamedItem() if (isNamedItem != wasNamedItem && document()->isHTMLDocument()) { HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); if (isNamedItem) { - document->addNamedItem(fastGetAttribute(nameAttr)); + document->addNamedItem(getNameAttribute()); document->addExtraNamedItem(getIdAttribute()); } else { - document->removeNamedItem(fastGetAttribute(nameAttr)); + document->removeNamedItem(getNameAttribute()); document->removeExtraNamedItem(getIdAttribute()); } } @@ -440,7 +453,7 @@ bool HTMLObjectElement::containsJavaApplet() const for (Element* child = firstElementChild(); child; child = child->nextElementSibling()) { if (child->hasTagName(paramTag) - && equalIgnoringCase(child->getAttribute(nameAttr), "type") + && equalIgnoringCase(child->getNameAttribute(), "type") && MIMETypeRegistry::isJavaAppletMIMEType(child->getAttribute(valueAttr).string())) return true; if (child->hasTagName(objectTag) @@ -501,7 +514,7 @@ bool HTMLObjectElement::appendFormData(FormDataList& encoding, bool) const AtomicString& HTMLObjectElement::formControlName() const { - const AtomicString& name = fastGetAttribute(nameAttr); + const AtomicString& name = getNameAttribute(); return name.isNull() ? emptyAtom : name; } diff --git a/Source/WebCore/html/HTMLObjectElement.h b/Source/WebCore/html/HTMLObjectElement.h index 85bf16f8b..112dcc6af 100644 --- a/Source/WebCore/html/HTMLObjectElement.h +++ b/Source/WebCore/html/HTMLObjectElement.h @@ -67,6 +67,9 @@ private: HTMLObjectElement(const QualifiedName&, Document*, HTMLFormElement*, bool createdByParser); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; + virtual void insertedIntoTree(bool deep); virtual void removedFromTree(bool deep); diff --git a/Source/WebCore/html/HTMLObjectElement.idl b/Source/WebCore/html/HTMLObjectElement.idl index 4553fbc06..f1055fdb8 100644 --- a/Source/WebCore/html/HTMLObjectElement.idl +++ b/Source/WebCore/html/HTMLObjectElement.idl @@ -22,7 +22,7 @@ module html { interface [ CustomNamedSetter, - JSCustomGetOwnPropertySlotDelegate, + JSCustomGetOwnPropertySlotAndDescriptor, CustomCall ] HTMLObjectElement : HTMLElement { readonly attribute HTMLFormElement form; @@ -49,11 +49,11 @@ module html { void setCustomValidity(in [TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString error); // Introduced in DOM Level 2: - readonly attribute [CheckAccessToNode] Document contentDocument; + readonly attribute [CheckSecurityForNode] Document contentDocument; #if defined(ENABLE_SVG) && ENABLE_SVG #if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C || defined(ENABLE_SVG_DOM_OBJC_BINDINGS) && ENABLE_SVG_DOM_OBJC_BINDINGS - [CheckAccessToNode] SVGDocument getSVGDocument() raises(DOMException); + [CheckSecurityForNode] SVGDocument getSVGDocument() raises(DOMException); #endif #endif diff --git a/Source/WebCore/html/HTMLOptionElement.cpp b/Source/WebCore/html/HTMLOptionElement.cpp index 73f6ffa91..9fef31841 100644 --- a/Source/WebCore/html/HTMLOptionElement.cpp +++ b/Source/WebCore/html/HTMLOptionElement.cpp @@ -147,7 +147,7 @@ void HTMLOptionElement::setText(const String &text, ExceptionCode& ec) // Handle the common special case where there's exactly 1 child node, and it's a text node. Node* child = firstChild(); if (child && child->isTextNode() && !child->nextSibling()) - static_cast<Text *>(child)->setData(text, ec); + toText(child)->setData(text, ec); else { removeChildren(); appendChild(Text::create(document(), text), ec); diff --git a/Source/WebCore/html/HTMLOptionElement.idl b/Source/WebCore/html/HTMLOptionElement.idl index 73e9c3bdf..99681f2c1 100644 --- a/Source/WebCore/html/HTMLOptionElement.idl +++ b/Source/WebCore/html/HTMLOptionElement.idl @@ -22,7 +22,7 @@ module html { interface [ JSGenerateToNativeObject, - NamedConstructor=Option(in [Optional=CallWithNullValue] DOMString data, in [Optional=CallWithNullValue] DOMString value, in [Optional=CallWithDefaultValue] boolean defaultSelected, in [Optional=CallWithDefaultValue] boolean selected), + NamedConstructor=Option(in [Optional=DefaultIsNullString] DOMString data, in [Optional=DefaultIsNullString] DOMString value, in [Optional=DefaultIsUndefined] boolean defaultSelected, in [Optional=DefaultIsUndefined] boolean selected), ConstructorRaisesException ] HTMLOptionElement : HTMLElement { readonly attribute HTMLFormElement form; diff --git a/Source/WebCore/html/HTMLOptionsCollection.idl b/Source/WebCore/html/HTMLOptionsCollection.idl index b28643994..0476e65fc 100644 --- a/Source/WebCore/html/HTMLOptionsCollection.idl +++ b/Source/WebCore/html/HTMLOptionsCollection.idl @@ -28,10 +28,10 @@ module html { attribute [Custom] unsigned long length setter raises (DOMException); - [Custom] void add(in [Optional=CallWithDefaultValue] HTMLOptionElement option, + [Custom] void add(in [Optional=DefaultIsUndefined] HTMLOptionElement option, in [Optional] unsigned long index) raises (DOMException); - [Custom] void remove(in [Optional=CallWithDefaultValue] unsigned long index); + [Custom] void remove(in [Optional=DefaultIsUndefined] unsigned long index); #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C Node item(in unsigned long index); diff --git a/Source/WebCore/html/HTMLParagraphElement.cpp b/Source/WebCore/html/HTMLParagraphElement.cpp index 6cc9f51b8..c8f6ad3ee 100644 --- a/Source/WebCore/html/HTMLParagraphElement.cpp +++ b/Source/WebCore/html/HTMLParagraphElement.cpp @@ -44,21 +44,26 @@ PassRefPtr<HTMLParagraphElement> HTMLParagraphElement::create(const QualifiedNam return adoptRef(new HTMLParagraphElement(tagName, document)); } -void HTMLParagraphElement::parseAttribute(Attribute* attr) +bool HTMLParagraphElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == alignAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLParagraphElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == alignAttr) { - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyTextAlign); - else if (equalIgnoringCase(attr->value(), "middle") || equalIgnoringCase(attr->value(), "center")) - addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitCenter); + if (equalIgnoringCase(attr->value(), "middle") || equalIgnoringCase(attr->value(), "center")) + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, CSSValueWebkitCenter); else if (equalIgnoringCase(attr->value(), "left")) - addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitLeft); + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, CSSValueWebkitLeft); else if (equalIgnoringCase(attr->value(), "right")) - addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitRight); + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, CSSValueWebkitRight); else - addCSSProperty(CSSPropertyTextAlign, attr->value()); + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, attr->value()); } else - HTMLElement::parseAttribute(attr); + HTMLElement::collectStyleForAttribute(attr, style); } } diff --git a/Source/WebCore/html/HTMLParagraphElement.h b/Source/WebCore/html/HTMLParagraphElement.h index 0c8c290bb..86a85a63a 100644 --- a/Source/WebCore/html/HTMLParagraphElement.h +++ b/Source/WebCore/html/HTMLParagraphElement.h @@ -34,7 +34,8 @@ public: private: HTMLParagraphElement(const QualifiedName&, Document*); - virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; }; } // namespace WebCore diff --git a/Source/WebCore/html/HTMLPlugInElement.cpp b/Source/WebCore/html/HTMLPlugInElement.cpp index 66d60922c..8c0f302a2 100644 --- a/Source/WebCore/html/HTMLPlugInElement.cpp +++ b/Source/WebCore/html/HTMLPlugInElement.cpp @@ -140,36 +140,29 @@ Widget* HTMLPlugInElement::pluginWidget() return renderWidget->widget(); } -void HTMLPlugInElement::parseAttribute(Attribute* attr) +bool HTMLPlugInElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == widthAttr || attr->name() == heightAttr || attr->name() == vspaceAttr || attr->name() == hspaceAttr || attr->name() == alignAttr) + return true; + return HTMLFrameOwnerElement::isPresentationAttribute(attr); +} + +void HTMLPlugInElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == widthAttr) - if (attr->isNull()) - removeCSSProperty(CSSPropertyWidth); - else - addCSSLength(CSSPropertyWidth, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value()); else if (attr->name() == heightAttr) - if (attr->isNull()) - removeCSSProperty(CSSPropertyHeight); - else - addCSSLength(CSSPropertyHeight, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value()); else if (attr->name() == vspaceAttr) { - if (attr->isNull()) - removeCSSProperties(CSSPropertyMarginTop, CSSPropertyMarginBottom); - else { - addCSSLength(CSSPropertyMarginTop, attr->value()); - addCSSLength(CSSPropertyMarginBottom, attr->value()); - } + addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value()); } else if (attr->name() == hspaceAttr) { - if (attr->isNull()) - removeCSSProperties(CSSPropertyMarginLeft, CSSPropertyMarginRight); - else { - addCSSLength(CSSPropertyMarginLeft, attr->value()); - addCSSLength(CSSPropertyMarginRight, attr->value()); - } + addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value()); } else if (attr->name() == alignAttr) - addHTMLAlignment(attr); + applyAlignmentAttributeToStyle(attr, style); else - HTMLFrameOwnerElement::parseAttribute(attr); + HTMLFrameOwnerElement::collectStyleForAttribute(attr, style); } void HTMLPlugInElement::defaultEventHandler(Event* event) diff --git a/Source/WebCore/html/HTMLPlugInElement.h b/Source/WebCore/html/HTMLPlugInElement.h index 8c2214167..10c1ea791 100644 --- a/Source/WebCore/html/HTMLPlugInElement.h +++ b/Source/WebCore/html/HTMLPlugInElement.h @@ -58,7 +58,8 @@ protected: virtual void detach(); virtual void removedFromDocument(); - virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; bool m_inBeforeLoadEventHandler; // Subclasses should use guardedDispatchBeforeLoadEvent instead of calling dispatchBeforeLoadEvent directly. diff --git a/Source/WebCore/html/HTMLPreElement.cpp b/Source/WebCore/html/HTMLPreElement.cpp index 7ed85fccd..09c08977a 100644 --- a/Source/WebCore/html/HTMLPreElement.cpp +++ b/Source/WebCore/html/HTMLPreElement.cpp @@ -42,20 +42,19 @@ PassRefPtr<HTMLPreElement> HTMLPreElement::create(const QualifiedName& tagName, return adoptRef(new HTMLPreElement(tagName, document)); } -void HTMLPreElement::parseAttribute(Attribute* attr) +bool HTMLPreElement::isPresentationAttribute(Attribute* attr) const { - if (attr->name() == widthAttr) { - // FIXME: Implement this some day. Width on a <pre> is the # of characters that - // we should size the pre to. We basically need to take the width of a space, - // multiply by the value of the attribute and then set that as the width CSS - // property. - } else if (attr->name() == wrapAttr) { - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyWhiteSpace); - else - addCSSProperty(CSSPropertyWhiteSpace, CSSValuePreWrap); - } else - return HTMLElement::parseAttribute(attr); + if (attr->name() == wrapAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLPreElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == wrapAttr) + style->setProperty(CSSPropertyWhiteSpace, CSSValuePreWrap); + else + HTMLElement::collectStyleForAttribute(attr, style); } } diff --git a/Source/WebCore/html/HTMLPreElement.h b/Source/WebCore/html/HTMLPreElement.h index 3ad3152f1..778204898 100644 --- a/Source/WebCore/html/HTMLPreElement.h +++ b/Source/WebCore/html/HTMLPreElement.h @@ -34,7 +34,8 @@ public: private: HTMLPreElement(const QualifiedName&, Document*); - virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; }; } // namespace WebCore diff --git a/Source/WebCore/html/HTMLProgressElement.cpp b/Source/WebCore/html/HTMLProgressElement.cpp index 0c2372581..78bbde32b 100644 --- a/Source/WebCore/html/HTMLProgressElement.cpp +++ b/Source/WebCore/html/HTMLProgressElement.cpp @@ -26,6 +26,7 @@ #include "EventNames.h" #include "ExceptionCode.h" #include "FormDataList.h" +#include "NodeRenderingContext.h" #include "HTMLDivElement.h" #include "HTMLFormElement.h" #include "HTMLNames.h" @@ -64,6 +65,11 @@ RenderObject* HTMLProgressElement::createRenderer(RenderArena* arena, RenderStyl return new (arena) RenderProgress(this); } +bool HTMLProgressElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const +{ + return childContext.isOnEncapsulationBoundary() && HTMLElement::childShouldCreateRenderer(childContext); +} + bool HTMLProgressElement::supportsFocus() const { return Node::supportsFocus() && !disabled(); @@ -153,7 +159,7 @@ void HTMLProgressElement::didElementStateChange() void HTMLProgressElement::createShadowSubtree() { - ASSERT(!shadowRoot()); + ASSERT(!hasShadowRoot()); RefPtr<ProgressBarElement> bar = ProgressBarElement::create(document()); m_value = ProgressValueElement::create(document()); diff --git a/Source/WebCore/html/HTMLProgressElement.h b/Source/WebCore/html/HTMLProgressElement.h index 731f80b4a..dfd006799 100644 --- a/Source/WebCore/html/HTMLProgressElement.h +++ b/Source/WebCore/html/HTMLProgressElement.h @@ -58,6 +58,7 @@ private: virtual const AtomicString& formControlType() const; virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE; virtual void parseAttribute(Attribute*) OVERRIDE; diff --git a/Source/WebCore/html/HTMLScriptElement.cpp b/Source/WebCore/html/HTMLScriptElement.cpp index 1df19a63b..cabc21374 100644 --- a/Source/WebCore/html/HTMLScriptElement.cpp +++ b/Source/WebCore/html/HTMLScriptElement.cpp @@ -58,19 +58,14 @@ void HTMLScriptElement::childrenChanged(bool changedByParser, Node* beforeChange HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); } -void HTMLScriptElement::attributeChanged(Attribute* attr) -{ - if (attr->name() == asyncAttr) - handleAsyncAttribute(); - HTMLElement::attributeChanged(attr); -} - void HTMLScriptElement::parseAttribute(Attribute* attr) { const QualifiedName& attrName = attr->name(); if (attrName == srcAttr) handleSourceAttribute(attr->value()); + else if (attr->name() == asyncAttr) + handleAsyncAttribute(); else if (attrName == onloadAttr) setAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(this, attr)); else if (attrName == onbeforeloadAttr) @@ -91,7 +86,7 @@ void HTMLScriptElement::setText(const String &value) int numChildren = childNodeCount(); if (numChildren == 1 && firstChild()->isTextNode()) { - static_cast<Text*>(firstChild())->setData(value, ec); + toText(firstChild())->setData(value, ec); return; } diff --git a/Source/WebCore/html/HTMLScriptElement.h b/Source/WebCore/html/HTMLScriptElement.h index 61d9de094..07c89abf6 100644 --- a/Source/WebCore/html/HTMLScriptElement.h +++ b/Source/WebCore/html/HTMLScriptElement.h @@ -47,7 +47,6 @@ private: virtual void parseAttribute(Attribute*) OVERRIDE; virtual void insertedIntoDocument(); virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); - virtual void attributeChanged(Attribute*) OVERRIDE; virtual bool isURLAttribute(Attribute*) const; diff --git a/Source/WebCore/html/HTMLSelectElement.cpp b/Source/WebCore/html/HTMLSelectElement.cpp index 1b96d226f..a2c31dcda 100644 --- a/Source/WebCore/html/HTMLSelectElement.cpp +++ b/Source/WebCore/html/HTMLSelectElement.cpp @@ -42,6 +42,7 @@ #include "HTMLOptionsCollection.h" #include "KeyboardEvent.h" #include "MouseEvent.h" +#include "NodeRenderingContext.h" #include "Page.h" #include "RenderListBox.h" #include "RenderMenuList.h" @@ -256,6 +257,17 @@ void HTMLSelectElement::setValue(const String &value) setSelectedIndex(-1); } +bool HTMLSelectElement::isPresentationAttribute(Attribute* attr) const +{ + 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=12072 + return false; + } + + return HTMLFormControlElementWithState::isPresentationAttribute(attr); +} + void HTMLSelectElement::parseAttribute(Attribute* attr) { if (attr->name() == sizeAttr) { @@ -282,9 +294,6 @@ void HTMLSelectElement::parseAttribute(Attribute* attr) parseMultipleAttribute(attr); else if (attr->name() == accesskeyAttr) { // FIXME: 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=12072 } else if (attr->name() == onchangeAttr) setAttributeEventListener(eventNames().changeEvent, createAttributeEventListener(this, attr)); else @@ -317,6 +326,11 @@ RenderObject* HTMLSelectElement::createRenderer(RenderArena* arena, RenderStyle* return new (arena) RenderListBox(this); } +bool HTMLSelectElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const +{ + return childContext.isOnEncapsulationBoundary() && HTMLFormControlElementWithState::childShouldCreateRenderer(childContext); +} + HTMLOptionsCollection* HTMLSelectElement::options() { if (!m_optionsCollection) diff --git a/Source/WebCore/html/HTMLSelectElement.h b/Source/WebCore/html/HTMLSelectElement.h index 8d9b738a4..77c081e6f 100644 --- a/Source/WebCore/html/HTMLSelectElement.h +++ b/Source/WebCore/html/HTMLSelectElement.h @@ -122,7 +122,9 @@ private: virtual void restoreFormControlState(const String&); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE; virtual RenderObject* createRenderer(RenderArena*, RenderStyle *); virtual bool appendFormData(FormDataList&, bool); diff --git a/Source/WebCore/html/HTMLSelectElement.idl b/Source/WebCore/html/HTMLSelectElement.idl index 5d60ef4f8..4f0b82662 100644 --- a/Source/WebCore/html/HTMLSelectElement.idl +++ b/Source/WebCore/html/HTMLSelectElement.idl @@ -52,8 +52,8 @@ module html { attribute [Reflect] boolean required; attribute long size; - [ObjCLegacyUnnamedParameters] void add(in [Optional=CallWithDefaultValue] HTMLElement element, - in [Optional=CallWithDefaultValue] HTMLElement before) raises(DOMException); + [ObjCLegacyUnnamedParameters] void add(in [Optional=DefaultIsUndefined] HTMLElement element, + in [Optional=DefaultIsUndefined] HTMLElement before) raises(DOMException); #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT // In JavaScript, we support both option index and option object parameters. @@ -65,8 +65,8 @@ module html { // 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." - Node item(in [IsIndex,Optional=CallWithDefaultValue] unsigned long index); - Node namedItem(in [Optional=CallWithDefaultValue] DOMString name); + Node item(in [IsIndex,Optional=DefaultIsUndefined] unsigned long index); + Node namedItem(in [Optional=DefaultIsUndefined] DOMString name); readonly attribute NodeList labels; }; diff --git a/Source/WebCore/html/HTMLStyleElement.cpp b/Source/WebCore/html/HTMLStyleElement.cpp index 4156ce5f1..2070d56ce 100644 --- a/Source/WebCore/html/HTMLStyleElement.cpp +++ b/Source/WebCore/html/HTMLStyleElement.cpp @@ -27,6 +27,7 @@ #include "Attribute.h" #include "Document.h" #include "HTMLNames.h" +#include "RuntimeEnabledFeatures.h" #include "ScriptEventListener.h" #include "ScriptableDocumentParser.h" @@ -87,38 +88,50 @@ void HTMLStyleElement::registerWithScopingNode() // Therefore we cannot rely on scoped()! ASSERT(!m_isRegisteredWithScopingNode); ASSERT(inDocument()); - if (!m_isRegisteredWithScopingNode) { - Element* scope = parentElement(); - if (!scope) - return; + if (m_isRegisteredWithScopingNode) + return; + if (!RuntimeEnabledFeatures::styleScopedEnabled()) + return; + + ContainerNode* scope = parentNode(); + if (!scope) + return; + if (!scope->isElementNode() && !scope->isShadowRoot()) { + // DocumentFragment nodes should never be inDocument, + // <style> should not be a child of Document, PI or some such. + ASSERT_NOT_REACHED(); + return; + } - scope->registerScopedHTMLStyleChild(); - scope->setNeedsStyleRecalc(); - if (inDocument() && !document()->parsing() && document()->renderer()) - document()->styleSelectorChanged(DeferRecalcStyle); + scope->registerScopedHTMLStyleChild(); + scope->setNeedsStyleRecalc(); + if (inDocument() && !document()->parsing() && document()->renderer()) + document()->styleSelectorChanged(DeferRecalcStyle); - m_isRegisteredWithScopingNode = true; - } + m_isRegisteredWithScopingNode = true; } void HTMLStyleElement::unregisterWithScopingNode() { // Note: We cannot rely on the 'scoped' element still being present when this method is invoked. // Therefore we cannot rely on scoped()! - ASSERT(m_isRegisteredWithScopingNode); - if (m_isRegisteredWithScopingNode) { - Element* scope = parentElement(); - ASSERT(scope); - if (scope) { - ASSERT(scope->hasScopedHTMLStyleChild()); - scope->unregisterScopedHTMLStyleChild(); - scope->setNeedsStyleRecalc(); - } - if (inDocument() && !document()->parsing() && document()->renderer()) - document()->styleSelectorChanged(DeferRecalcStyle); - - m_isRegisteredWithScopingNode = false; + ASSERT(m_isRegisteredWithScopingNode || !RuntimeEnabledFeatures::styleScopedEnabled()); + if (!m_isRegisteredWithScopingNode) + return; + if (!RuntimeEnabledFeatures::styleScopedEnabled()) + return; + + ContainerNode* scope = parentNode(); + ASSERT(scope); + if (scope) { + ASSERT(scope->hasScopedHTMLStyleChild()); + scope->unregisterScopedHTMLStyleChild(); + scope->setNeedsStyleRecalc(); } + if (inDocument() && !document()->parsing() && document()->renderer()) + document()->styleSelectorChanged(DeferRecalcStyle); + + m_isRegisteredWithScopingNode = false; } #endif @@ -149,7 +162,7 @@ void HTMLStyleElement::willRemove() // That is, because willRemove() is also called if an ancestor is removed from the document. // Now, if we want to register <style scoped> even if it's not inDocument, // we'd need to find a way to discern whether that is the case, or whether <style scoped> itself is about to be removed. - ASSERT(!scoped() || !inDocument() || m_isRegisteredWithScopingNode); + ASSERT(!scoped() || !inDocument() || m_isRegisteredWithScopingNode || !RuntimeEnabledFeatures::styleScopedEnabled()); if (m_isRegisteredWithScopingNode) unregisterWithScopingNode(); HTMLElement::willRemove(); diff --git a/Source/WebCore/html/HTMLStyleElement.h b/Source/WebCore/html/HTMLStyleElement.h index 9c50ee240..39d140067 100644 --- a/Source/WebCore/html/HTMLStyleElement.h +++ b/Source/WebCore/html/HTMLStyleElement.h @@ -74,7 +74,9 @@ private: void registerWithScopingNode(); void unregisterWithScopingNode(); +#if ENABLE(STYLE_SCOPED) bool m_isRegisteredWithScopingNode; +#endif }; } //namespace diff --git a/Source/WebCore/html/HTMLStyleElement.idl b/Source/WebCore/html/HTMLStyleElement.idl index 7a1b62295..1b9abd47a 100644 --- a/Source/WebCore/html/HTMLStyleElement.idl +++ b/Source/WebCore/html/HTMLStyleElement.idl @@ -22,7 +22,7 @@ module html { interface HTMLStyleElement : HTMLElement { attribute boolean disabled; - attribute [Conditional=STYLE_SCOPED] boolean scoped; + attribute [Conditional=STYLE_SCOPED, V8EnabledAtRuntime=styleScoped] boolean scoped; attribute [Reflect] DOMString media; attribute [Reflect] DOMString type; diff --git a/Source/WebCore/html/HTMLSummaryElement.cpp b/Source/WebCore/html/HTMLSummaryElement.cpp index f57a5db23..a3494af81 100644 --- a/Source/WebCore/html/HTMLSummaryElement.cpp +++ b/Source/WebCore/html/HTMLSummaryElement.cpp @@ -27,11 +27,13 @@ #include "HTMLContentElement.h" #include "HTMLDetailsElement.h" #include "HTMLNames.h" +#include "KeyboardEvent.h" #include "MouseEvent.h" +#include "NodeRenderingContext.h" #include "PlatformMouseEvent.h" #include "RenderSummary.h" - #include "ShadowRoot.h" +#include "ShadowRootList.h" namespace WebCore { @@ -71,9 +73,14 @@ RenderObject* HTMLSummaryElement::createRenderer(RenderArena* arena, RenderStyle return new (arena) RenderSummary(this); } +bool HTMLSummaryElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const +{ + return childContext.isOnEncapsulationBoundary() && HTMLElement::childShouldCreateRenderer(childContext); +} + void HTMLSummaryElement::createShadowSubtree() { - ASSERT(!shadowRoot()); + ASSERT(!hasShadowRoot()); RefPtr<ShadowRoot> root = ShadowRoot::create(this, ShadowRoot::CreatingUserAgentShadowRoot); root->appendChild(DetailsMarkerControl::create(document()), ASSERT_NO_EXCEPTION, true); root->appendChild(SummaryContentElement::create(document()), ASSERT_NO_EXCEPTION, true); @@ -106,20 +113,49 @@ static bool isClickableControl(Node* node) return host && host->isFormControlElement(); } +bool HTMLSummaryElement::supportsFocus() const +{ + return isMainSummary(); +} + void HTMLSummaryElement::defaultEventHandler(Event* event) { - HTMLElement::defaultEventHandler(event); - if (!isMainSummary() || !renderer() || !renderer()->isSummary() || !event->isMouseEvent() || event->type() != eventNames().clickEvent || event->defaultHandled()) - return; - MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); - if (mouseEvent->button() != LeftButton) - return; - if (isClickableControl(event->target()->toNode())) - return; + if (isMainSummary() && renderer() && renderer()->isSummary()) { + if (event->type() == eventNames().DOMActivateEvent && !isClickableControl(event->target()->toNode())) { + if (HTMLDetailsElement* details = detailsElement()) + details->toggleOpen(); + event->setDefaultHandled(); + return; + } + + if (event->isKeyboardEvent()) { + if (event->type() == eventNames().keydownEvent && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "U+0020") { + setActive(true, true); + // No setDefaultHandled() - IE dispatches a keypress in this case. + return; + } + if (event->type() == eventNames().keypressEvent) { + switch (static_cast<KeyboardEvent*>(event)->charCode()) { + case '\r': + dispatchSimulatedClick(event); + event->setDefaultHandled(); + return; + case ' ': + // Prevent scrolling down the page. + event->setDefaultHandled(); + return; + } + } + if (event->type() == eventNames().keyupEvent && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "U+0020") { + if (active()) + dispatchSimulatedClick(event); + event->setDefaultHandled(); + return; + } + } + } - if (HTMLDetailsElement* details = detailsElement()) - details->toggleOpen(); - event->setDefaultHandled(); + HTMLElement::defaultEventHandler(event); } } diff --git a/Source/WebCore/html/HTMLSummaryElement.h b/Source/WebCore/html/HTMLSummaryElement.h index 43ab73fad..49a2d0bac 100644 --- a/Source/WebCore/html/HTMLSummaryElement.h +++ b/Source/WebCore/html/HTMLSummaryElement.h @@ -36,10 +36,13 @@ private: HTMLSummaryElement(const QualifiedName&, Document*); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE; virtual void defaultEventHandler(Event*); void createShadowSubtree(); HTMLDetailsElement* detailsElement() const; + + bool supportsFocus() const OVERRIDE; }; } diff --git a/Source/WebCore/html/HTMLTableCaptionElement.cpp b/Source/WebCore/html/HTMLTableCaptionElement.cpp index 88450d43a..c327d0f85 100644 --- a/Source/WebCore/html/HTMLTableCaptionElement.cpp +++ b/Source/WebCore/html/HTMLTableCaptionElement.cpp @@ -34,7 +34,7 @@ namespace WebCore { using namespace HTMLNames; inline HTMLTableCaptionElement::HTMLTableCaptionElement(const QualifiedName& tagName, Document* document) - : HTMLTablePartElement(tagName, document) + : HTMLElement(tagName, document) { ASSERT(hasTagName(captionTag)); } @@ -44,15 +44,20 @@ PassRefPtr<HTMLTableCaptionElement> HTMLTableCaptionElement::create(const Qualif return adoptRef(new HTMLTableCaptionElement(tagName, document)); } -void HTMLTableCaptionElement::parseAttribute(Attribute* attr) +bool HTMLTableCaptionElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == alignAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLTableCaptionElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == alignAttr) { - if (!attr->value().isEmpty()) - addCSSProperty(CSSPropertyCaptionSide, attr->value()); - else - removeCSSProperty(CSSPropertyCaptionSide); + if (!attr->isEmpty()) + addPropertyToAttributeStyle(style, CSSPropertyCaptionSide, attr->value()); } else - HTMLElement::parseAttribute(attr); + HTMLElement::collectStyleForAttribute(attr, style); } } diff --git a/Source/WebCore/html/HTMLTableCaptionElement.h b/Source/WebCore/html/HTMLTableCaptionElement.h index da40e821d..a43141f40 100644 --- a/Source/WebCore/html/HTMLTableCaptionElement.h +++ b/Source/WebCore/html/HTMLTableCaptionElement.h @@ -26,18 +26,19 @@ #ifndef HTMLTableCaptionElement_h #define HTMLTableCaptionElement_h -#include "HTMLTablePartElement.h" +#include "HTMLElement.h" namespace WebCore { -class HTMLTableCaptionElement : public HTMLTablePartElement { +class HTMLTableCaptionElement : public HTMLElement { public: static PassRefPtr<HTMLTableCaptionElement> create(const QualifiedName&, Document*); private: HTMLTableCaptionElement(const QualifiedName&, Document*); - virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; }; } // namespace diff --git a/Source/WebCore/html/HTMLTableCellElement.cpp b/Source/WebCore/html/HTMLTableCellElement.cpp index 84a1c9654..7664673f3 100644 --- a/Source/WebCore/html/HTMLTableCellElement.cpp +++ b/Source/WebCore/html/HTMLTableCellElement.cpp @@ -75,46 +75,50 @@ int HTMLTableCellElement::cellIndex() const return index; } -void HTMLTableCellElement::parseAttribute(Attribute* attr) +bool HTMLTableCellElement::isPresentationAttribute(Attribute* attr) const { - if (attr->name() == rowspanAttr) { - if (renderer() && renderer()->isTableCell()) - toRenderTableCell(renderer())->colSpanOrRowSpanChanged(); - } else if (attr->name() == colspanAttr) { - if (renderer() && renderer()->isTableCell()) - toRenderTableCell(renderer())->colSpanOrRowSpanChanged(); - } else if (attr->name() == nowrapAttr) { - if (attr->isNull()) - removeCSSProperty(CSSPropertyWhiteSpace); - else - addCSSProperty(CSSPropertyWhiteSpace, CSSValueWebkitNowrap); + if (attr->name() == nowrapAttr || attr->name() == widthAttr || attr->name() == heightAttr) + return true; + return HTMLTablePartElement::isPresentationAttribute(attr); +} +void HTMLTableCellElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == nowrapAttr) { + addPropertyToAttributeStyle(style, 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(CSSPropertyWidth, attr->value()); - } else - removeCSSProperty(CSSPropertyWidth); + addHTMLLengthToStyle(style, 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(CSSPropertyHeight, attr->value()); - } else - removeCSSProperty(CSSPropertyHeight); + addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value()); + } + } else + HTMLTablePartElement::collectStyleForAttribute(attr, style); +} + +void HTMLTableCellElement::parseAttribute(Attribute* attr) +{ + if (attr->name() == rowspanAttr) { + if (renderer() && renderer()->isTableCell()) + toRenderTableCell(renderer())->colSpanOrRowSpanChanged(); + } else if (attr->name() == colspanAttr) { + if (renderer() && renderer()->isTableCell()) + toRenderTableCell(renderer())->colSpanOrRowSpanChanged(); } else HTMLTablePartElement::parseAttribute(attr); } StylePropertySet* HTMLTableCellElement::additionalAttributeStyle() { - ContainerNode* p = parentNode(); - while (p && !p->hasTagName(tableTag)) - p = p->parentNode(); - if (!p) - return 0; - return static_cast<HTMLTableElement*>(p)->additionalCellStyle(); + if (HTMLTableElement* table = findParentTable()) + return table->additionalCellStyle(); + return 0; } bool HTMLTableCellElement::isURLAttribute(Attribute *attr) const diff --git a/Source/WebCore/html/HTMLTableCellElement.h b/Source/WebCore/html/HTMLTableCellElement.h index 5c32d6a9d..7ca11271f 100644 --- a/Source/WebCore/html/HTMLTableCellElement.h +++ b/Source/WebCore/html/HTMLTableCellElement.h @@ -54,6 +54,8 @@ private: HTMLTableCellElement(const QualifiedName&, Document*); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual StylePropertySet* additionalAttributeStyle() OVERRIDE; diff --git a/Source/WebCore/html/HTMLTableColElement.cpp b/Source/WebCore/html/HTMLTableColElement.cpp index 0c83e781c..db75b2544 100644 --- a/Source/WebCore/html/HTMLTableColElement.cpp +++ b/Source/WebCore/html/HTMLTableColElement.cpp @@ -47,6 +47,21 @@ PassRefPtr<HTMLTableColElement> HTMLTableColElement::create(const QualifiedName& return adoptRef(new HTMLTableColElement(tagName, document)); } +bool HTMLTableColElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == widthAttr) + return true; + return HTMLTablePartElement::isPresentationAttribute(attr); +} + +void HTMLTableColElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == widthAttr) + addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value()); + else + HTMLTablePartElement::collectStyleForAttribute(attr, style); +} + void HTMLTableColElement::parseAttribute(Attribute* attr) { if (attr->name() == spanAttr) { @@ -55,15 +70,13 @@ void HTMLTableColElement::parseAttribute(Attribute* attr) renderer()->updateFromElement(); } else if (attr->name() == widthAttr) { if (!attr->value().isEmpty()) { - addCSSLength(CSSPropertyWidth, attr->value()); if (renderer() && renderer()->isTableCol()) { RenderTableCol* col = toRenderTableCol(renderer()); int newWidth = width().toInt(); if (newWidth != col->width()) col->setNeedsLayoutAndPrefWidthsRecalc(); } - } else - removeCSSProperty(CSSPropertyWidth); + } } else HTMLTablePartElement::parseAttribute(attr); } @@ -72,12 +85,9 @@ StylePropertySet* HTMLTableColElement::additionalAttributeStyle() { if (!hasLocalName(colgroupTag)) return 0; - ContainerNode* p = parentNode(); - while (p && !p->hasTagName(tableTag)) - p = p->parentNode(); - if (!p) - return 0; - return static_cast<HTMLTableElement*>(p)->additionalGroupStyle(false); + if (HTMLTableElement* table = findParentTable()) + return table->additionalGroupStyle(false); + return 0; } void HTMLTableColElement::setSpan(int n) diff --git a/Source/WebCore/html/HTMLTableColElement.h b/Source/WebCore/html/HTMLTableColElement.h index 01cea8e1b..960ee8448 100644 --- a/Source/WebCore/html/HTMLTableColElement.h +++ b/Source/WebCore/html/HTMLTableColElement.h @@ -43,6 +43,8 @@ private: HTMLTableColElement(const QualifiedName& tagName, Document*); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual StylePropertySet* additionalAttributeStyle() OVERRIDE; int m_span; diff --git a/Source/WebCore/html/HTMLTableElement.cpp b/Source/WebCore/html/HTMLTableElement.cpp index be3aaa2ce..9420d9518 100644 --- a/Source/WebCore/html/HTMLTableElement.cpp +++ b/Source/WebCore/html/HTMLTableElement.cpp @@ -26,6 +26,7 @@ #include "HTMLTableElement.h" #include "Attribute.h" +#include "CSSImageValue.h" #include "CSSPropertyNames.h" #include "CSSStyleSheet.h" #include "CSSValueKeywords.h" @@ -266,102 +267,118 @@ static bool setTableCellsChanged(Node* n) return cellChanged; } +static bool getBordersFromFrameAttributeValue(const AtomicString& value, bool& borderTop, bool& borderRight, bool& borderBottom, bool& borderLeft) +{ + borderTop = false; + borderRight = false; + borderBottom = false; + borderLeft = false; + + if (equalIgnoringCase(value, "above")) + borderTop = true; + else if (equalIgnoringCase(value, "below")) + borderBottom = true; + else if (equalIgnoringCase(value, "hsides")) + borderTop = borderBottom = true; + else if (equalIgnoringCase(value, "vsides")) + borderLeft = borderRight = true; + else if (equalIgnoringCase(value, "lhs")) + borderLeft = true; + else if (equalIgnoringCase(value, "rhs")) + borderRight = true; + else if (equalIgnoringCase(value, "box") || equalIgnoringCase(value, "border")) + borderTop = borderBottom = borderLeft = borderRight = true; + else if (!equalIgnoringCase(value, "void")) + return false; + return true; +} + +void HTMLTableElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == widthAttr) + addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value()); + else if (attr->name() == heightAttr) + addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value()); + else if (attr->name() == borderAttr) { + int borderWidth = attr->isEmpty() ? 1 : attr->value().toInt(); + addPropertyToAttributeStyle(style, CSSPropertyBorderWidth, borderWidth, CSSPrimitiveValue::CSS_PX); + } else if (attr->name() == bordercolorAttr) { + if (!attr->isEmpty()) + addHTMLColorToStyle(style, CSSPropertyBorderColor, attr->value()); + } else if (attr->name() == bgcolorAttr) + addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attr->value()); + else if (attr->name() == backgroundAttr) { + String url = stripLeadingAndTrailingHTMLSpaces(attr->value()); + if (!url.isEmpty()) + style->setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document()->completeURL(url).string()))); + } else if (attr->name() == valignAttr) { + if (!attr->isEmpty()) + addPropertyToAttributeStyle(style, CSSPropertyVerticalAlign, attr->value()); + } else if (attr->name() == cellspacingAttr) { + if (!attr->isEmpty()) + addHTMLLengthToStyle(style, CSSPropertyBorderSpacing, attr->value()); + } else if (attr->name() == vspaceAttr) { + addHTMLLengthToStyle(style, CSSPropertyMarginTop, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginBottom, attr->value()); + } else if (attr->name() == hspaceAttr) { + addHTMLLengthToStyle(style, CSSPropertyMarginLeft, attr->value()); + addHTMLLengthToStyle(style, CSSPropertyMarginRight, attr->value()); + } else if (attr->name() == alignAttr) { + if (!attr->value().isEmpty()) { + if (equalIgnoringCase(attr->value(), "center")) { + addPropertyToAttributeStyle(style, CSSPropertyWebkitMarginStart, CSSValueAuto); + addPropertyToAttributeStyle(style, CSSPropertyWebkitMarginEnd, CSSValueAuto); + } else + addPropertyToAttributeStyle(style, CSSPropertyFloat, attr->value()); + } + } else if (attr->name() == rulesAttr) { + // The presence of a valid rules attribute causes border collapsing to be enabled. + if (m_rulesAttr != UnsetRules) + addPropertyToAttributeStyle(style, CSSPropertyBorderCollapse, CSSValueCollapse); + } else if (attr->name() == frameAttr) { + bool borderTop; + bool borderRight; + bool borderBottom; + bool borderLeft; + if (getBordersFromFrameAttributeValue(attr->value(), borderTop, borderRight, borderBottom, borderLeft)) { + addPropertyToAttributeStyle(style, CSSPropertyBorderWidth, CSSValueThin); + addPropertyToAttributeStyle(style, CSSPropertyBorderTopStyle, borderTop ? CSSValueSolid : CSSValueHidden); + addPropertyToAttributeStyle(style, CSSPropertyBorderBottomStyle, borderBottom ? CSSValueSolid : CSSValueHidden); + addPropertyToAttributeStyle(style, CSSPropertyBorderLeftStyle, borderLeft ? CSSValueSolid : CSSValueHidden); + addPropertyToAttributeStyle(style, CSSPropertyBorderRightStyle, borderRight ? CSSValueSolid : CSSValueHidden); + } + } else + HTMLElement::collectStyleForAttribute(attr, style); +} + +bool HTMLTableElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == widthAttr || attr->name() == heightAttr || attr->name() == bgcolorAttr || attr->name() == backgroundAttr || attr->name() == valignAttr || attr->name() == vspaceAttr || attr->name() == hspaceAttr || attr->name() == alignAttr || attr->name() == cellspacingAttr || attr->name() == borderAttr || attr->name() == bordercolorAttr || attr->name() == frameAttr || attr->name() == rulesAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + void HTMLTableElement::parseAttribute(Attribute* attr) { CellBorders bordersBefore = cellBorders(); unsigned short oldPadding = m_padding; - if (attr->name() == widthAttr) - if (attr->isNull()) - removeCSSProperty(CSSPropertyWidth); - else - addCSSLength(CSSPropertyWidth, attr->value()); - else if (attr->name() == heightAttr) - if (attr->isNull()) - removeCSSProperty(CSSPropertyHeight); - else - addCSSLength(CSSPropertyHeight, attr->value()); - else if (attr->name() == borderAttr) { + if (attr->name() == borderAttr) { + // FIXME: This attribute is a mess. m_borderAttr = true; - - if (attr->isNull()) - removeCSSProperty(CSSPropertyBorderWidth); - else { - int border = 0; - if (attr->isEmpty()) - border = 1; - else - border = attr->value().toInt(); + if (!attr->isNull()) { + int border = attr->isEmpty() ? 1 : attr->value().toInt(); m_borderAttr = border; - addCSSLength(CSSPropertyBorderWidth, String::number(border)); } - } else if (attr->name() == bgcolorAttr) - if (attr->isNull()) - removeCSSProperty(CSSPropertyBackgroundColor); - else - addCSSColor(CSSPropertyBackgroundColor, attr->value()); - else if (attr->name() == bordercolorAttr) { + } else if (attr->name() == bordercolorAttr) { m_borderColorAttr = !attr->isEmpty(); - if (!attr->isEmpty()) - addCSSColor(CSSPropertyBorderColor, attr->value()); - else - removeCSSProperty(CSSPropertyBorderColor); - } else if (attr->name() == backgroundAttr) { - String url = stripLeadingAndTrailingHTMLSpaces(attr->value()); - if (!url.isEmpty()) - addCSSImageProperty(CSSPropertyBackgroundImage, document()->completeURL(url).string()); - else - removeCSSProperty(CSSPropertyBackgroundImage); } else if (attr->name() == frameAttr) { - // Cache the value of "frame" so that the table can examine it later. - m_frameAttr = false; - - // Whether or not to hide the top/right/bottom/left borders. - const int cTop = 0; - const int cRight = 1; - const int cBottom = 2; - const int cLeft = 3; - bool borders[4] = { false, false, false, false }; - - // void, above, below, hsides, vsides, lhs, rhs, box, border - if (equalIgnoringCase(attr->value(), "void")) - m_frameAttr = true; - else if (equalIgnoringCase(attr->value(), "above")) { - m_frameAttr = true; - borders[cTop] = true; - } else if (equalIgnoringCase(attr->value(), "below")) { - m_frameAttr = true; - borders[cBottom] = true; - } else if (equalIgnoringCase(attr->value(), "hsides")) { - m_frameAttr = true; - borders[cTop] = borders[cBottom] = true; - } else if (equalIgnoringCase(attr->value(), "vsides")) { - m_frameAttr = true; - borders[cLeft] = borders[cRight] = true; - } else if (equalIgnoringCase(attr->value(), "lhs")) { - m_frameAttr = true; - borders[cLeft] = true; - } else if (equalIgnoringCase(attr->value(), "rhs")) { - m_frameAttr = true; - borders[cRight] = true; - } else if (equalIgnoringCase(attr->value(), "box") || - equalIgnoringCase(attr->value(), "border")) { - m_frameAttr = true; - borders[cTop] = borders[cBottom] = borders[cLeft] = borders[cRight] = true; - } - - // Now map in the border styles of solid and hidden respectively. - if (m_frameAttr) { - addCSSProperty(CSSPropertyBorderTopWidth, CSSValueThin); - addCSSProperty(CSSPropertyBorderBottomWidth, CSSValueThin); - addCSSProperty(CSSPropertyBorderLeftWidth, CSSValueThin); - addCSSProperty(CSSPropertyBorderRightWidth, CSSValueThin); - addCSSProperty(CSSPropertyBorderTopStyle, borders[cTop] ? CSSValueSolid : CSSValueHidden); - addCSSProperty(CSSPropertyBorderBottomStyle, borders[cBottom] ? CSSValueSolid : CSSValueHidden); - addCSSProperty(CSSPropertyBorderLeftStyle, borders[cLeft] ? CSSValueSolid : CSSValueHidden); - addCSSProperty(CSSPropertyBorderRightStyle, borders[cRight] ? CSSValueSolid : CSSValueHidden); - } else - removeCSSProperties(CSSPropertyBorderTopWidth, CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth, CSSPropertyBorderRightWidth, CSSPropertyBorderTopStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle, CSSPropertyBorderRightStyle); + // FIXME: This attribute is a mess. + bool borderTop; + bool borderRight; + bool borderBottom; + bool borderLeft; + m_frameAttr = getBordersFromFrameAttributeValue(attr->value(), borderTop, borderRight, borderBottom, borderLeft); } else if (attr->name() == rulesAttr) { m_rulesAttr = UnsetRules; if (equalIgnoringCase(attr->value(), "none")) @@ -374,17 +391,6 @@ void HTMLTableElement::parseAttribute(Attribute* attr) m_rulesAttr = ColsRules; if (equalIgnoringCase(attr->value(), "all")) m_rulesAttr = AllRules; - - // The presence of a valid rules attribute causes border collapsing to be enabled. - if (m_rulesAttr != UnsetRules) - addCSSProperty(CSSPropertyBorderCollapse, CSSValueCollapse); - else - removeCSSProperty(CSSPropertyBorderCollapse); - } else if (attr->name() == cellspacingAttr) { - if (!attr->value().isEmpty()) - addCSSLength(CSSPropertyBorderSpacing, attr->value()); - else - removeCSSProperty(CSSPropertyBorderSpacing); } else if (attr->name() == cellpaddingAttr) { if (!attr->value().isEmpty()) m_padding = max(0, attr->value().toInt()); @@ -392,34 +398,6 @@ void HTMLTableElement::parseAttribute(Attribute* attr) m_padding = 1; } else if (attr->name() == colsAttr) { // ### - } else if (attr->name() == vspaceAttr) { - if (attr->isNull()) - removeCSSProperties(CSSPropertyMarginTop, CSSPropertyMarginBottom); - else { - addCSSLength(CSSPropertyMarginTop, attr->value()); - addCSSLength(CSSPropertyMarginBottom, attr->value()); - } - } else if (attr->name() == hspaceAttr) { - if (attr->isNull()) - removeCSSProperties(CSSPropertyMarginLeft, CSSPropertyMarginRight); - else { - addCSSLength(CSSPropertyMarginLeft, attr->value()); - addCSSLength(CSSPropertyMarginRight, attr->value()); - } - } else if (attr->name() == alignAttr) { - if (!attr->value().isEmpty()) { - if (equalIgnoringCase(attr->value(), "center")) { - addCSSProperty(CSSPropertyWebkitMarginStart, CSSValueAuto); - addCSSProperty(CSSPropertyWebkitMarginEnd, CSSValueAuto); - } else - addCSSProperty(CSSPropertyFloat, attr->value()); - } else - removeCSSProperties(CSSPropertyWebkitMarginStart, CSSPropertyWebkitMarginEnd, CSSPropertyFloat); - } else if (attr->name() == valignAttr) { - if (!attr->value().isEmpty()) - addCSSProperty(CSSPropertyVerticalAlign, attr->value()); - else - removeCSSProperty(CSSPropertyVerticalAlign); } else HTMLElement::parseAttribute(attr); diff --git a/Source/WebCore/html/HTMLTableElement.h b/Source/WebCore/html/HTMLTableElement.h index ef8ccde6e..d9b86a8fc 100644 --- a/Source/WebCore/html/HTMLTableElement.h +++ b/Source/WebCore/html/HTMLTableElement.h @@ -73,6 +73,8 @@ private: HTMLTableElement(const QualifiedName&, Document*); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual bool isURLAttribute(Attribute*) const; // Used to obtain either a solid or outset border decl and to deal with the frame and rules attributes. diff --git a/Source/WebCore/html/HTMLTableElement.idl b/Source/WebCore/html/HTMLTableElement.idl index 7c046eb6e..5e3bb0cf7 100644 --- a/Source/WebCore/html/HTMLTableElement.idl +++ b/Source/WebCore/html/HTMLTableElement.idl @@ -46,8 +46,8 @@ module html { HTMLElement createCaption(); void deleteCaption(); - HTMLElement insertRow(in [Optional=CallWithDefaultValue] long index) raises(DOMException); - void deleteRow(in [Optional=CallWithDefaultValue] long index) raises(DOMException); + HTMLElement insertRow(in [Optional=DefaultIsUndefined] long index) raises(DOMException); + void deleteRow(in [Optional=DefaultIsUndefined] long index) raises(DOMException); }; } diff --git a/Source/WebCore/html/HTMLTablePartElement.cpp b/Source/WebCore/html/HTMLTablePartElement.cpp index 8fd747bd8..8a39260af 100644 --- a/Source/WebCore/html/HTMLTablePartElement.cpp +++ b/Source/WebCore/html/HTMLTablePartElement.cpp @@ -26,64 +26,73 @@ #include "HTMLTablePartElement.h" #include "Attribute.h" +#include "CSSImageValue.h" #include "CSSPropertyNames.h" #include "CSSValueKeywords.h" #include "Document.h" #include "HTMLNames.h" #include "HTMLParserIdioms.h" +#include "HTMLTableElement.h" namespace WebCore { using namespace HTMLNames; -void HTMLTablePartElement::parseAttribute(Attribute* attr) +bool HTMLTablePartElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == bgcolorAttr || attr->name() == backgroundAttr || attr->name() == bordercolorAttr || attr->name() == valignAttr || attr->name() == alignAttr || attr->name() == heightAttr) + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLTablePartElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) { if (attr->name() == bgcolorAttr) - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyBackgroundColor); - else - addCSSColor(CSSPropertyBackgroundColor, attr->value()); + addHTMLColorToStyle(style, CSSPropertyBackgroundColor, attr->value()); else if (attr->name() == backgroundAttr) { String url = stripLeadingAndTrailingHTMLSpaces(attr->value()); if (!url.isEmpty()) - addCSSImageProperty(CSSPropertyBackgroundImage, document()->completeURL(url).string()); - else - removeCSSProperty(CSSPropertyBackgroundImage); + style->setProperty(CSSProperty(CSSPropertyBackgroundImage, CSSImageValue::create(document()->completeURL(url).string()))); } else if (attr->name() == bordercolorAttr) { if (!attr->value().isEmpty()) { - addCSSColor(CSSPropertyBorderColor, attr->value()); - addCSSProperty(CSSPropertyBorderTopStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderBottomStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderLeftStyle, CSSValueSolid); - addCSSProperty(CSSPropertyBorderRightStyle, CSSValueSolid); - } else - removeCSSProperties(CSSPropertyBorderColor, CSSPropertyBorderTopStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle, CSSPropertyBorderRightStyle); + addHTMLColorToStyle(style, CSSPropertyBorderColor, attr->value()); + addPropertyToAttributeStyle(style, CSSPropertyBorderStyle, CSSValueSolid); + } } else if (attr->name() == valignAttr) { - if (!attr->value().isEmpty()) - addCSSProperty(CSSPropertyVerticalAlign, attr->value()); + if (equalIgnoringCase(attr->value(), "top")) + addPropertyToAttributeStyle(style, CSSPropertyVerticalAlign, CSSValueTop); + else if (equalIgnoringCase(attr->value(), "middle")) + addPropertyToAttributeStyle(style, CSSPropertyVerticalAlign, CSSValueMiddle); + else if (equalIgnoringCase(attr->value(), "bottom")) + addPropertyToAttributeStyle(style, CSSPropertyVerticalAlign, CSSValueBottom); + else if (equalIgnoringCase(attr->value(), "baseline")) + addPropertyToAttributeStyle(style, CSSPropertyVerticalAlign, CSSValueBaseline); else - removeCSSProperty(CSSPropertyVerticalAlign); + addPropertyToAttributeStyle(style, CSSPropertyVerticalAlign, attr->value()); } else if (attr->name() == alignAttr) { - const AtomicString& v = attr->value(); - if (v.isNull()) - removeCSSProperty(CSSPropertyTextAlign); - else if (equalIgnoringCase(v, "middle") || equalIgnoringCase(v, "center")) - addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitCenter); - else if (equalIgnoringCase(v, "absmiddle")) - addCSSProperty(CSSPropertyTextAlign, CSSValueCenter); - else if (equalIgnoringCase(v, "left")) - addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitLeft); - else if (equalIgnoringCase(v, "right")) - addCSSProperty(CSSPropertyTextAlign, CSSValueWebkitRight); + if (equalIgnoringCase(attr->value(), "middle") || equalIgnoringCase(attr->value(), "center")) + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, CSSValueWebkitCenter); + else if (equalIgnoringCase(attr->value(), "absmiddle")) + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, CSSValueCenter); + else if (equalIgnoringCase(attr->value(), "left")) + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, CSSValueWebkitLeft); + else if (equalIgnoringCase(attr->value(), "right")) + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, CSSValueWebkitRight); else - addCSSProperty(CSSPropertyTextAlign, v); + addPropertyToAttributeStyle(style, CSSPropertyTextAlign, attr->value()); } else if (attr->name() == heightAttr) { if (!attr->value().isEmpty()) - addCSSLength(CSSPropertyHeight, attr->value()); - else - removeCSSProperty(CSSPropertyHeight); + addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value()); } else - HTMLElement::parseAttribute(attr); + HTMLElement::collectStyleForAttribute(attr, style); +} + +HTMLTableElement* HTMLTablePartElement::findParentTable() const +{ + ContainerNode* parent = parentNode(); + while (parent && !parent->hasTagName(tableTag)) + parent = parent->parentNode(); + return static_cast<HTMLTableElement*>(parent); } } diff --git a/Source/WebCore/html/HTMLTablePartElement.h b/Source/WebCore/html/HTMLTablePartElement.h index c139bbe3c..49f75b3d5 100644 --- a/Source/WebCore/html/HTMLTablePartElement.h +++ b/Source/WebCore/html/HTMLTablePartElement.h @@ -30,6 +30,8 @@ namespace WebCore { +class HTMLTableElement; + class HTMLTablePartElement : public HTMLElement { protected: HTMLTablePartElement(const QualifiedName& tagName, Document* document) @@ -37,7 +39,10 @@ protected: { } - virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; + + HTMLTableElement* findParentTable() const; }; } //namespace diff --git a/Source/WebCore/html/HTMLTableRowElement.idl b/Source/WebCore/html/HTMLTableRowElement.idl index 482c61f7d..b16d754af 100644 --- a/Source/WebCore/html/HTMLTableRowElement.idl +++ b/Source/WebCore/html/HTMLTableRowElement.idl @@ -29,8 +29,8 @@ module html { attribute [Reflect=char] DOMString ch; attribute [Reflect=charoff] DOMString chOff; attribute [Reflect] DOMString vAlign; - HTMLElement insertCell(in [Optional=CallWithDefaultValue] long index) raises(DOMException); - void deleteCell(in [Optional=CallWithDefaultValue] long index) raises(DOMException); + HTMLElement insertCell(in [Optional=DefaultIsUndefined] long index) raises(DOMException); + void deleteCell(in [Optional=DefaultIsUndefined] long index) raises(DOMException); }; } diff --git a/Source/WebCore/html/HTMLTableSectionElement.cpp b/Source/WebCore/html/HTMLTableSectionElement.cpp index 0e7872d12..f450fea25 100644 --- a/Source/WebCore/html/HTMLTableSectionElement.cpp +++ b/Source/WebCore/html/HTMLTableSectionElement.cpp @@ -49,12 +49,9 @@ PassRefPtr<HTMLTableSectionElement> HTMLTableSectionElement::create(const Qualif StylePropertySet* HTMLTableSectionElement::additionalAttributeStyle() { - ContainerNode* p = parentNode(); - while (p && !p->hasTagName(tableTag)) - p = p->parentNode(); - if (!p) - return 0; - return static_cast<HTMLTableElement*>(p)->additionalGroupStyle(true); + if (HTMLTableElement* table = findParentTable()) + return table->additionalGroupStyle(true); + return 0; } // these functions are rather slow, since we need to get the row at diff --git a/Source/WebCore/html/HTMLTableSectionElement.idl b/Source/WebCore/html/HTMLTableSectionElement.idl index 1553b5ea1..88f53369b 100644 --- a/Source/WebCore/html/HTMLTableSectionElement.idl +++ b/Source/WebCore/html/HTMLTableSectionElement.idl @@ -28,8 +28,8 @@ module html { attribute [Reflect=charoff] DOMString chOff; attribute [Reflect] DOMString vAlign; readonly attribute HTMLCollection rows; - HTMLElement insertRow(in [Optional=CallWithDefaultValue] long index) raises(DOMException); - void deleteRow(in [Optional=CallWithDefaultValue] long index) raises(DOMException); + HTMLElement insertRow(in [Optional=DefaultIsUndefined] long index) raises(DOMException); + void deleteRow(in [Optional=DefaultIsUndefined] long index) raises(DOMException); }; } diff --git a/Source/WebCore/html/HTMLTextAreaElement.cpp b/Source/WebCore/html/HTMLTextAreaElement.cpp index bff7574be..f110ef695 100644 --- a/Source/WebCore/html/HTMLTextAreaElement.cpp +++ b/Source/WebCore/html/HTMLTextAreaElement.cpp @@ -38,6 +38,7 @@ #include "HTMLNames.h" #include "RenderTextControlMultiLine.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include "Text.h" #include "TextControlInnerElements.h" #include "TextIterator.h" @@ -84,7 +85,7 @@ PassRefPtr<HTMLTextAreaElement> HTMLTextAreaElement::create(const QualifiedName& void HTMLTextAreaElement::createShadowSubtree() { - ASSERT(!shadowRoot()); + ASSERT(!hasShadowRoot()); RefPtr<ShadowRoot> root = ShadowRoot::create(this, ShadowRoot::CreatingUserAgentShadowRoot); root->appendChild(TextControlInnerTextElement::create(document()), ASSERT_NO_EXCEPTION); } @@ -117,7 +118,34 @@ void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChan setInnerTextValue(value()); HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); } - + +bool HTMLTextAreaElement::isPresentationAttribute(Attribute* attr) const +{ + 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 + return false; + } + + if (attr->name() == wrapAttr) + return true; + return HTMLTextFormControlElement::isPresentationAttribute(attr); +} + +void HTMLTextAreaElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == wrapAttr) { + if (shouldWrapText()) { + addPropertyToAttributeStyle(style, CSSPropertyWhiteSpace, CSSValuePreWrap); + addPropertyToAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord); + } else { + addPropertyToAttributeStyle(style, CSSPropertyWhiteSpace, CSSValuePre); + addPropertyToAttributeStyle(style, CSSPropertyWordWrap, CSSValueNormal); + } + } else + HTMLTextFormControlElement::collectStyleForAttribute(attr, style); +} + void HTMLTextAreaElement::parseAttribute(Attribute* attr) { if (attr->name() == rowsAttr) { @@ -150,23 +178,11 @@ void HTMLTextAreaElement::parseAttribute(Attribute* attr) wrap = SoftWrap; if (wrap != m_wrap) { m_wrap = wrap; - - if (shouldWrapText()) { - addCSSProperty(CSSPropertyWhiteSpace, CSSValuePreWrap); - addCSSProperty(CSSPropertyWordWrap, CSSValueBreakWord); - } else { - addCSSProperty(CSSPropertyWhiteSpace, CSSValuePre); - addCSSProperty(CSSPropertyWordWrap, CSSValueNormal); - } - 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() == maxlengthAttr) setNeedsValidityCheck(); else @@ -278,7 +294,7 @@ String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue, HTMLElement* HTMLTextAreaElement::innerTextElement() const { - Node* node = shadowRoot()->firstChild(); + Node* node = shadowRootList()->oldestShadowRoot()->firstChild(); ASSERT(!node || node->hasTagName(divTag)); return toHTMLElement(node); } @@ -360,7 +376,7 @@ String HTMLTextAreaElement::defaultValue() const // Since there may be comments, ignore nodes other than text nodes. for (Node* n = firstChild(); n; n = n->nextSibling()) { if (n->isTextNode()) - value += static_cast<Text*>(n)->data(); + value += toText(n)->data(); } return value; @@ -455,7 +471,7 @@ void HTMLTextAreaElement::updatePlaceholderText() String placeholderText = strippedPlaceholder(); if (placeholderText.isEmpty()) { if (m_placeholder) { - shadowRoot()->removeChild(m_placeholder.get(), ec); + shadowRootList()->oldestShadowRoot()->removeChild(m_placeholder.get(), ec); ASSERT(!ec); m_placeholder.clear(); } @@ -464,7 +480,7 @@ void HTMLTextAreaElement::updatePlaceholderText() if (!m_placeholder) { m_placeholder = HTMLDivElement::create(document()); m_placeholder->setShadowPseudoId("-webkit-input-placeholder"); - shadowRoot()->insertBefore(m_placeholder, shadowRoot()->firstChild()->nextSibling(), ec); + shadowRootList()->oldestShadowRoot()->insertBefore(m_placeholder, shadowRootList()->oldestShadowRoot()->firstChild()->nextSibling(), ec); ASSERT(!ec); } m_placeholder->setInnerText(placeholderText, ec); diff --git a/Source/WebCore/html/HTMLTextAreaElement.h b/Source/WebCore/html/HTMLTextAreaElement.h index c2bbc718c..615af2585 100644 --- a/Source/WebCore/html/HTMLTextAreaElement.h +++ b/Source/WebCore/html/HTMLTextAreaElement.h @@ -94,6 +94,8 @@ private: virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); virtual bool appendFormData(FormDataList&, bool); virtual void reset(); diff --git a/Source/WebCore/html/HTMLTextAreaElement.idl b/Source/WebCore/html/HTMLTextAreaElement.idl index 3b76115e5..f6ed37503 100644 --- a/Source/WebCore/html/HTMLTextAreaElement.idl +++ b/Source/WebCore/html/HTMLTextAreaElement.idl @@ -40,6 +40,9 @@ module html { attribute [TreatNullAs=NullString] DOMString value; readonly attribute unsigned long textLength; +#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C + attribute [Reflect] DOMString accessKey; +#endif void select(); readonly attribute boolean willValidate; @@ -54,8 +57,8 @@ module html { #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C void setSelectionRange(in long start, in long end); #else - void setSelectionRange(in [Optional=CallWithDefaultValue] long start, - in [Optional=CallWithDefaultValue] long end, + void setSelectionRange(in [Optional=DefaultIsUndefined] long start, + in [Optional=DefaultIsUndefined] long end, in [Optional] DOMString direction); #endif readonly attribute NodeList labels; diff --git a/Source/WebCore/html/HTMLTextFormControlElement.cpp b/Source/WebCore/html/HTMLTextFormControlElement.cpp index c7f64903f..f47e1f209 100644 --- a/Source/WebCore/html/HTMLTextFormControlElement.cpp +++ b/Source/WebCore/html/HTMLTextFormControlElement.cpp @@ -37,6 +37,7 @@ #include "HTMLFormElement.h" #include "HTMLInputElement.h" #include "HTMLNames.h" +#include "NodeRenderingContext.h" #include "Page.h" #include "RenderBox.h" #include "RenderTextControl.h" @@ -64,6 +65,11 @@ HTMLTextFormControlElement::~HTMLTextFormControlElement() { } +bool HTMLTextFormControlElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const +{ + return childContext.isOnEncapsulationBoundary() && HTMLFormControlElementWithState::childShouldCreateRenderer(childContext); +} + void HTMLTextFormControlElement::insertedIntoDocument() { HTMLFormControlElement::insertedIntoDocument(); @@ -153,7 +159,7 @@ void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderVal if (!placeholder) return; ExceptionCode ec = 0; - placeholder->ensureInlineStyleDecl()->setProperty(CSSPropertyVisibility, placeholderShouldBeVisible() ? "visible" : "hidden", ec); + placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShouldBeVisible() ? "visible" : "hidden", ec); ASSERT(!ec); } @@ -493,7 +499,7 @@ String HTMLTextFormControlElement::innerTextValue() const if (node->hasTagName(brTag)) result.append(newlineCharacter); else if (node->isTextNode()) - result.append(static_cast<Text*>(node)->data()); + result.append(toText(node)->data()); } return finishText(result); } @@ -540,7 +546,7 @@ String HTMLTextFormControlElement::valueWithHardLineBreaks() const if (node->hasTagName(brTag)) result.append(newlineCharacter); else if (node->isTextNode()) { - String data = static_cast<Text*>(node)->data(); + String data = toText(node)->data(); unsigned length = data.length(); unsigned position = 0; while (breakNode == node && breakOffset <= length) { diff --git a/Source/WebCore/html/HTMLTextFormControlElement.h b/Source/WebCore/html/HTMLTextFormControlElement.h index 8aff29093..59cd741dd 100644 --- a/Source/WebCore/html/HTMLTextFormControlElement.h +++ b/Source/WebCore/html/HTMLTextFormControlElement.h @@ -34,6 +34,7 @@ class RenderTextControl; class VisiblePosition; enum TextFieldSelectionDirection { SelectionHasNoDirection, SelectionHasForwardDirection, SelectionHasBackwardDirection }; +enum TextFieldEventBehavior { DispatchNoEvent, DispatchChangeEvent, DispatchInputAndChangeEvent }; class HTMLTextFormControlElement : public HTMLFormControlElementWithState { public: @@ -81,14 +82,14 @@ public: String directionForFormData() const; + void setTextAsOfLastFormControlChangeEvent(const String& text) { m_textAsOfLastFormControlChangeEvent = text; } + protected: HTMLTextFormControlElement(const QualifiedName&, Document*, HTMLFormElement*); virtual void updatePlaceholderText() = 0; virtual void parseAttribute(Attribute*) OVERRIDE; - void setTextAsOfLastFormControlChangeEvent(const String& text) { m_textAsOfLastFormControlChangeEvent = text; } - void cacheSelection(int start, int end, TextFieldSelectionDirection direction) { m_cachedSelectionStart = start; @@ -113,6 +114,7 @@ private: virtual void dispatchFocusEvent(PassRefPtr<Node> oldFocusedNode); virtual void dispatchBlurEvent(PassRefPtr<Node> newFocusedNode); + virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE; bool isPlaceholderEmpty() const; diff --git a/Source/WebCore/html/HTMLTitleElement.cpp b/Source/WebCore/html/HTMLTitleElement.cpp index 69f1f84bc..6e7884b8b 100644 --- a/Source/WebCore/html/HTMLTitleElement.cpp +++ b/Source/WebCore/html/HTMLTitleElement.cpp @@ -70,7 +70,7 @@ String HTMLTitleElement::text() const for (Node *n = firstChild(); n; n = n->nextSibling()) { if (n->isTextNode()) - val += static_cast<Text*>(n)->data(); + val += toText(n)->data(); } return val; @@ -92,7 +92,7 @@ void HTMLTitleElement::setText(const String &value) int numChildren = childNodeCount(); if (numChildren == 1 && firstChild()->isTextNode()) - static_cast<Text*>(firstChild())->setData(value, ec); + toText(firstChild())->setData(value, ec); else { // We make a copy here because entity of "value" argument can be Document::m_title, // which goes empty during removeChildren() invocation below, diff --git a/Source/WebCore/html/HTMLTrackElement.cpp b/Source/WebCore/html/HTMLTrackElement.cpp index ea2ad05c7..f3578dacf 100644 --- a/Source/WebCore/html/HTMLTrackElement.cpp +++ b/Source/WebCore/html/HTMLTrackElement.cpp @@ -92,6 +92,20 @@ void HTMLTrackElement::parseAttribute(Attribute* attribute) { const QualifiedName& attrName = attribute->name(); + if (RuntimeEnabledFeatures::webkitVideoTrackEnabled()) { + if (attrName == srcAttr) { + if (!attribute->isEmpty() && mediaElement()) + scheduleLoad(); + // 4.8.10.12.3 Sourcing out-of-band text tracks + // As the kind, label, and srclang attributes are set, changed, or removed, the text track must update accordingly... + } else if (attrName == kindAttr) + track()->setKind(attribute->value()); + else if (attrName == labelAttr) + track()->setLabel(attribute->value()); + else if (attrName == srclangAttr) + track()->setLanguage(attribute->value()); + } + if (attrName == onloadAttr) setAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(this, attribute)); else if (attrName == onerrorAttr) @@ -100,28 +114,6 @@ void HTMLTrackElement::parseAttribute(Attribute* attribute) HTMLElement::parseAttribute(attribute); } -void HTMLTrackElement::attributeChanged(Attribute* attr) -{ - HTMLElement::attributeChanged(attr); - - if (!RuntimeEnabledFeatures::webkitVideoTrackEnabled()) - return; - - const QualifiedName& attrName = attr->name(); - if (attrName == srcAttr) { - if (!getAttribute(srcAttr).isEmpty() && mediaElement()) - scheduleLoad(); - - // 4.8.10.12.3 Sourcing out-of-band text tracks - // As the kind, label, and srclang attributes are set, changed, or removed, the text track must update accordingly... - } else if (attrName == kindAttr) - track()->setKind(attr->value()); - else if (attrName == labelAttr) - track()->setLabel(attr->value()); - else if (attrName == srclangAttr) - track()->setLanguage(attr->value()); -} - KURL HTMLTrackElement::src() const { return document()->completeURL(getAttribute(srcAttr)); diff --git a/Source/WebCore/html/HTMLTrackElement.h b/Source/WebCore/html/HTMLTrackElement.h index d3a05544a..ce1247c69 100644 --- a/Source/WebCore/html/HTMLTrackElement.h +++ b/Source/WebCore/html/HTMLTrackElement.h @@ -76,7 +76,6 @@ private: virtual ~HTMLTrackElement(); virtual void parseAttribute(Attribute*) OVERRIDE; - virtual void attributeChanged(Attribute*) OVERRIDE; virtual void insertedIntoDocument() OVERRIDE; virtual void removedFromDocument() OVERRIDE; diff --git a/Source/WebCore/html/HTMLUListElement.cpp b/Source/WebCore/html/HTMLUListElement.cpp index cc3c06999..e18d2a71c 100644 --- a/Source/WebCore/html/HTMLUListElement.cpp +++ b/Source/WebCore/html/HTMLUListElement.cpp @@ -47,15 +47,19 @@ PassRefPtr<HTMLUListElement> HTMLUListElement::create(const QualifiedName& tagNa return adoptRef(new HTMLUListElement(tagName, document)); } -void HTMLUListElement::parseAttribute(Attribute* attr) +bool HTMLUListElement::isPresentationAttribute(Attribute* attr) const { if (attr->name() == typeAttr) - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyListStyleType); - else - addCSSProperty(CSSPropertyListStyleType, attr->value()); + return true; + return HTMLElement::isPresentationAttribute(attr); +} + +void HTMLUListElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == typeAttr) + addPropertyToAttributeStyle(style, CSSPropertyListStyleType, attr->value()); else - HTMLElement::parseAttribute(attr); + HTMLElement::collectStyleForAttribute(attr, style); } } diff --git a/Source/WebCore/html/HTMLUListElement.h b/Source/WebCore/html/HTMLUListElement.h index c7867469f..ea6510da0 100644 --- a/Source/WebCore/html/HTMLUListElement.h +++ b/Source/WebCore/html/HTMLUListElement.h @@ -35,7 +35,8 @@ public: private: HTMLUListElement(const QualifiedName&, Document*); - virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; }; } //namespace diff --git a/Source/WebCore/html/HTMLVideoElement.cpp b/Source/WebCore/html/HTMLVideoElement.cpp index c59f995e4..64428d815 100644 --- a/Source/WebCore/html/HTMLVideoElement.cpp +++ b/Source/WebCore/html/HTMLVideoElement.cpp @@ -54,7 +54,9 @@ inline HTMLVideoElement::HTMLVideoElement(const QualifiedName& tagName, Document PassRefPtr<HTMLVideoElement> HTMLVideoElement::create(const QualifiedName& tagName, Document* document, bool createdByParser) { - return adoptRef(new HTMLVideoElement(tagName, document, createdByParser)); + RefPtr<HTMLVideoElement> videoElement(adoptRef(new HTMLVideoElement(tagName, document, createdByParser))); + videoElement->suspendIfNeeded(); + return videoElement.release(); } bool HTMLVideoElement::rendererIsNeeded(const NodeRenderingContext& context) @@ -93,6 +95,23 @@ void HTMLVideoElement::detach() m_imageLoader.clear(); } +void HTMLVideoElement::collectStyleForAttribute(Attribute* attr, StylePropertySet* style) +{ + if (attr->name() == widthAttr) + addHTMLLengthToStyle(style, CSSPropertyWidth, attr->value()); + else if (attr->name() == heightAttr) + addHTMLLengthToStyle(style, CSSPropertyHeight, attr->value()); + else + HTMLMediaElement::collectStyleForAttribute(attr, style); +} + +bool HTMLVideoElement::isPresentationAttribute(Attribute* attr) const +{ + if (attr->name() == widthAttr || attr->name() == heightAttr) + return true; + return HTMLMediaElement::isPresentationAttribute(attr); +} + void HTMLVideoElement::parseAttribute(Attribute* attr) { const QualifiedName& attrName = attr->name(); @@ -113,17 +132,7 @@ void HTMLVideoElement::parseAttribute(Attribute* attr) toRenderImage(renderer())->imageResource()->setCachedImage(0); } #endif - } else if (attrName == widthAttr) - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyWidth); - else - addCSSLength(CSSPropertyWidth, attr->value()); - else if (attrName == heightAttr) - if (attr->value().isNull()) - removeCSSProperty(CSSPropertyHeight); - else - addCSSLength(CSSPropertyHeight, attr->value()); - else + } else HTMLMediaElement::parseAttribute(attr); } diff --git a/Source/WebCore/html/HTMLVideoElement.h b/Source/WebCore/html/HTMLVideoElement.h index e8f6331ef..59efd882b 100644 --- a/Source/WebCore/html/HTMLVideoElement.h +++ b/Source/WebCore/html/HTMLVideoElement.h @@ -76,6 +76,8 @@ private: virtual void attach(); virtual void detach(); virtual void parseAttribute(Attribute*) OVERRIDE; + virtual bool isPresentationAttribute(Attribute*) const OVERRIDE; + virtual void collectStyleForAttribute(Attribute*, StylePropertySet*) OVERRIDE; virtual bool isVideo() const { return true; } virtual bool hasVideo() const { return player() && player()->hasVideo(); } virtual bool supportsFullscreen() const; diff --git a/Source/WebCore/html/HiddenInputType.cpp b/Source/WebCore/html/HiddenInputType.cpp index fc103975b..951b6d826 100644 --- a/Source/WebCore/html/HiddenInputType.cpp +++ b/Source/WebCore/html/HiddenInputType.cpp @@ -87,7 +87,7 @@ bool HiddenInputType::storesValueSeparateFromAttribute() return false; } -void HiddenInputType::setValue(const String& sanitizedValue, bool, bool) +void HiddenInputType::setValue(const String& sanitizedValue, bool, TextFieldEventBehavior) { element()->setAttribute(valueAttr, sanitizedValue); } diff --git a/Source/WebCore/html/HiddenInputType.h b/Source/WebCore/html/HiddenInputType.h index fd86fbc1f..9e8982c54 100644 --- a/Source/WebCore/html/HiddenInputType.h +++ b/Source/WebCore/html/HiddenInputType.h @@ -51,7 +51,7 @@ private: virtual bool storesValueSeparateFromAttribute() OVERRIDE; virtual bool isHiddenType() const OVERRIDE; virtual bool shouldRespectHeightAndWidthAttributes() OVERRIDE; - virtual void setValue(const String&, bool, bool) OVERRIDE; + virtual void setValue(const String&, bool, TextFieldEventBehavior) OVERRIDE; virtual bool appendFormData(FormDataList&, bool) const OVERRIDE; }; diff --git a/Source/WebCore/html/ImageData.idl b/Source/WebCore/html/ImageData.idl index bbfa460a3..c85945417 100644 --- a/Source/WebCore/html/ImageData.idl +++ b/Source/WebCore/html/ImageData.idl @@ -29,7 +29,7 @@ module html { interface [ - JSCustomToJS + CustomToJSObject ] ImageData { readonly attribute long width; readonly attribute long height; diff --git a/Source/WebCore/html/ImageDocument.cpp b/Source/WebCore/html/ImageDocument.cpp index dc95a0d71..eb8e82198 100644 --- a/Source/WebCore/html/ImageDocument.cpp +++ b/Source/WebCore/html/ImageDocument.cpp @@ -253,7 +253,7 @@ void ImageDocument::resizeImageToFit() m_imageElement->setWidth(static_cast<int>(imageSize.width() * scale)); m_imageElement->setHeight(static_cast<int>(imageSize.height() * scale)); - m_imageElement->ensureInlineStyleDecl()->setProperty(CSSPropertyCursor, "-webkit-zoom-in", false); + m_imageElement->setInlineStyleProperty(CSSPropertyCursor, "-webkit-zoom-in", false); } void ImageDocument::imageClicked(int x, int y) @@ -307,9 +307,9 @@ void ImageDocument::restoreImageSize() m_imageElement->setHeight(imageSize.height()); if (imageFitsInWindow()) - m_imageElement->ensureInlineStyleDecl()->removeProperty(CSSPropertyCursor); + m_imageElement->removeInlineStyleProperty(CSSPropertyCursor); else - m_imageElement->ensureInlineStyleDecl()->setProperty(CSSPropertyCursor, "-webkit-zoom-out", false); + m_imageElement->setInlineStyleProperty(CSSPropertyCursor, "-webkit-zoom-out", false); m_didShrinkImage = false; } @@ -340,9 +340,9 @@ void ImageDocument::windowSizeChanged() // and set it to a zoom out cursor if the image doesn't fit if (!m_shouldShrinkImage) { if (fitsInWindow) - m_imageElement->ensureInlineStyleDecl()->removeProperty(CSSPropertyCursor); + m_imageElement->removeInlineStyleProperty(CSSPropertyCursor); else - m_imageElement->ensureInlineStyleDecl()->setProperty(CSSPropertyCursor, "-webkit-zoom-out", false); + m_imageElement->setInlineStyleProperty(CSSPropertyCursor, "-webkit-zoom-out", false); return; } diff --git a/Source/WebCore/html/InputType.cpp b/Source/WebCore/html/InputType.cpp index f34e6eb32..f34b93b5f 100644 --- a/Source/WebCore/html/InputType.cpp +++ b/Source/WebCore/html/InputType.cpp @@ -56,6 +56,7 @@ #include "ResetInputType.h" #include "SearchInputType.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include "SubmitInputType.h" #include "TelephoneInputType.h" #include "TextInputType.h" @@ -192,7 +193,7 @@ double InputType::valueAsNumber() const return numeric_limits<double>::quiet_NaN(); } -void InputType::setValueAsNumber(double, bool, ExceptionCode& ec) const +void InputType::setValueAsNumber(double, TextFieldEventBehavior, ExceptionCode& ec) const { ec = INVALID_STATE_ERR; } @@ -378,7 +379,11 @@ void InputType::createShadowSubtree() void InputType::destroyShadowSubtree() { - element()->removeShadowRoot(); + if (!element()->hasShadowRoot()) + return; + + if (ShadowRoot* root = element()->shadowRootList()->oldestShadowRoot()) + root->removeAllChildren(); } double InputType::parseToDouble(const String&, double defaultValue) const @@ -535,15 +540,12 @@ bool InputType::storesValueSeparateFromAttribute() return true; } -void InputType::setValue(const String& sanitizedValue, bool, bool sendChangeEvent) +void InputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior) { - element()->setValueInternal(sanitizedValue, sendChangeEvent); + element()->setValueInternal(sanitizedValue, eventBehavior); element()->setNeedsStyleRecalc(); -} - -void InputType::dispatchChangeEventInResponseToSetValue() -{ - element()->dispatchFormControlChangeEvent(); + if (valueChanged && eventBehavior != DispatchNoEvent) + element()->dispatchFormControlChangeEvent(); } bool InputType::canSetValue(const String&) diff --git a/Source/WebCore/html/InputType.h b/Source/WebCore/html/InputType.h index c76aacc8f..6b0f9c15a 100644 --- a/Source/WebCore/html/InputType.h +++ b/Source/WebCore/html/InputType.h @@ -32,6 +32,7 @@ #ifndef InputType_h #define InputType_h +#include "HTMLTextFormControlElement.h" #include <wtf/Forward.h> #include <wtf/FastAllocBase.h> #include <wtf/Noncopyable.h> @@ -126,7 +127,7 @@ public: virtual double valueAsDate() const; virtual void setValueAsDate(double, ExceptionCode&) const; virtual double valueAsNumber() const; - virtual void setValueAsNumber(double, bool sendChangeEvent, ExceptionCode&) const; + virtual void setValueAsNumber(double, TextFieldEventBehavior, ExceptionCode&) const; // Validation functions @@ -225,8 +226,7 @@ public: virtual bool shouldSendChangeEventAfterCheckedChanged(); virtual bool canSetValue(const String&); virtual bool storesValueSeparateFromAttribute(); - virtual void setValue(const String&, bool valueChanged, bool sendChangeEvent); - virtual void dispatchChangeEventInResponseToSetValue(); + virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior); virtual bool shouldResetOnDocumentActivation(); virtual bool shouldRespectListAttribute(); virtual bool shouldRespectSpeechAttribute(); diff --git a/Source/WebCore/html/MediaController.idl b/Source/WebCore/html/MediaController.idl index 1899dc3d8..d3f33485b 100644 --- a/Source/WebCore/html/MediaController.idl +++ b/Source/WebCore/html/MediaController.idl @@ -28,7 +28,7 @@ module html { Conditional=VIDEO, Constructor, CallWith=ScriptExecutionContext, - JSGenerateToJS, + JSGenerateToJSObject, EventTarget ] MediaController { readonly attribute TimeRanges buffered; diff --git a/Source/WebCore/html/NumberInputType.cpp b/Source/WebCore/html/NumberInputType.cpp index 3a4d420cd..560a4515b 100644 --- a/Source/WebCore/html/NumberInputType.cpp +++ b/Source/WebCore/html/NumberInputType.cpp @@ -83,7 +83,7 @@ double NumberInputType::valueAsNumber() const return parseToDouble(element()->value(), numeric_limits<double>::quiet_NaN()); } -void NumberInputType::setValueAsNumber(double newValue, bool sendChangeEvent, ExceptionCode& ec) const +void NumberInputType::setValueAsNumber(double newValue, TextFieldEventBehavior eventBehavior, ExceptionCode& ec) const { if (newValue < -numeric_limits<float>::max()) { ec = INVALID_STATE_ERR; @@ -93,7 +93,7 @@ void NumberInputType::setValueAsNumber(double newValue, bool sendChangeEvent, Ex ec = INVALID_STATE_ERR; return; } - element()->setValue(serialize(newValue), sendChangeEvent); + element()->setValue(serialize(newValue), eventBehavior); } bool NumberInputType::typeMismatchFor(const String& value) const diff --git a/Source/WebCore/html/NumberInputType.h b/Source/WebCore/html/NumberInputType.h index 26e7986c3..1afef8a69 100644 --- a/Source/WebCore/html/NumberInputType.h +++ b/Source/WebCore/html/NumberInputType.h @@ -43,7 +43,7 @@ private: NumberInputType(HTMLInputElement* element) : TextFieldInputType(element) { } virtual const AtomicString& formControlType() const OVERRIDE; virtual double valueAsNumber() const OVERRIDE; - virtual void setValueAsNumber(double, bool sendChangeEvent, ExceptionCode&) const OVERRIDE; + virtual void setValueAsNumber(double, TextFieldEventBehavior, ExceptionCode&) const OVERRIDE; virtual bool typeMismatchFor(const String&) const OVERRIDE; virtual bool typeMismatch() const OVERRIDE; virtual bool rangeUnderflow(const String&) const OVERRIDE; diff --git a/Source/WebCore/html/RadioInputType.cpp b/Source/WebCore/html/RadioInputType.cpp index d31cc2daf..cea0132e8 100644 --- a/Source/WebCore/html/RadioInputType.cpp +++ b/Source/WebCore/html/RadioInputType.cpp @@ -161,7 +161,7 @@ PassOwnPtr<ClickHandlingState> RadioInputType::willDispatchClick() element()->setIndeterminate(false); #endif - element()->setChecked(true, true); + element()->setChecked(true, DispatchChangeEvent); return state.release(); } diff --git a/Source/WebCore/html/RangeInputType.cpp b/Source/WebCore/html/RangeInputType.cpp index acfe1cca5..a174ce7af 100644 --- a/Source/WebCore/html/RangeInputType.cpp +++ b/Source/WebCore/html/RangeInputType.cpp @@ -42,6 +42,7 @@ #include "PlatformMouseEvent.h" #include "RenderSlider.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include "SliderThumbElement.h" #include "StepRange.h" #include <limits> @@ -78,9 +79,9 @@ double RangeInputType::valueAsNumber() const return parseToDouble(element()->value(), numeric_limits<double>::quiet_NaN()); } -void RangeInputType::setValueAsNumber(double newValue, bool sendChangeEvent, ExceptionCode&) const +void RangeInputType::setValueAsNumber(double newValue, TextFieldEventBehavior eventBehavior, ExceptionCode&) const { - element()->setValue(serialize(newValue), sendChangeEvent); + element()->setValue(serialize(newValue), eventBehavior); } bool RangeInputType::supportsRequired() const @@ -157,7 +158,10 @@ void RangeInputType::handleMouseDownEvent(MouseEvent* event) return; Node* targetNode = event->target()->toNode(); - if (event->button() != LeftButton || !targetNode || (targetNode != element() && !targetNode->isDescendantOf(element()->shadowRoot()))) + if (event->button() != LeftButton || !targetNode) + return; + ASSERT(element()->hasShadowRoot()); + if (targetNode != element() && !targetNode->isDescendantOf(element()->shadowRootList()->oldestShadowRoot())) return; SliderThumbElement* thumb = sliderThumbElementOf(element()); if (targetNode == thumb) @@ -220,8 +224,8 @@ void RangeInputType::handleKeydownEvent(KeyboardEvent* event) if (newValue != current) { ExceptionCode ec; - bool sendChangeEvent = true; - setValueAsNumber(newValue, sendChangeEvent, ec); + TextFieldEventBehavior eventBehavior = DispatchChangeEvent; + setValueAsNumber(newValue, eventBehavior, ec); if (AXObjectCache::accessibilityEnabled()) element()->document()->axObjectCache()->postNotification(element()->renderer(), AXObjectCache::AXValueChanged, true); @@ -233,6 +237,8 @@ void RangeInputType::handleKeydownEvent(KeyboardEvent* event) void RangeInputType::createShadowSubtree() { + ASSERT(element()->hasShadowRoot()); + Document* document = element()->document(); RefPtr<HTMLDivElement> track = HTMLDivElement::create(document); track->setShadowPseudoId("-webkit-slider-runnable-track"); @@ -241,7 +247,7 @@ void RangeInputType::createShadowSubtree() RefPtr<HTMLElement> container = SliderContainerElement::create(document); container->appendChild(track.release(), ec); container->appendChild(TrackLimiterElement::create(document), ec); - element()->ensureShadowRoot()->appendChild(container.release(), ec); + element()->shadowRootList()->oldestShadowRoot()->appendChild(container.release(), ec); } RenderObject* RangeInputType::createRenderer(RenderArena* arena, RenderStyle*) const @@ -285,9 +291,9 @@ void RangeInputType::minOrMaxAttributeChanged() element()->setNeedsStyleRecalc(); } -void RangeInputType::setValue(const String& value, bool valueChanged, bool sendChangeEvent) +void RangeInputType::setValue(const String& value, bool valueChanged, TextFieldEventBehavior eventBehavior) { - InputType::setValue(value, valueChanged, sendChangeEvent); + InputType::setValue(value, valueChanged, eventBehavior); if (!valueChanged) return; diff --git a/Source/WebCore/html/RangeInputType.h b/Source/WebCore/html/RangeInputType.h index e75193098..abf2ea674 100644 --- a/Source/WebCore/html/RangeInputType.h +++ b/Source/WebCore/html/RangeInputType.h @@ -46,7 +46,7 @@ private: virtual bool isRangeControl() const OVERRIDE; virtual const AtomicString& formControlType() const OVERRIDE; virtual double valueAsNumber() const OVERRIDE; - virtual void setValueAsNumber(double, bool sendChangeEvent, ExceptionCode&) const OVERRIDE; + virtual void setValueAsNumber(double, TextFieldEventBehavior, ExceptionCode&) const OVERRIDE; virtual bool supportsRequired() const OVERRIDE; virtual bool rangeUnderflow(const String&) const OVERRIDE; virtual bool rangeOverflow(const String&) const OVERRIDE; @@ -66,7 +66,7 @@ private: virtual String serialize(double) const OVERRIDE; virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE; virtual void minOrMaxAttributeChanged() OVERRIDE; - virtual void setValue(const String&, bool valueChanged, bool sendChangeEvent) OVERRIDE; + virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior) OVERRIDE; virtual String fallbackValue() const OVERRIDE; virtual String sanitizeValue(const String& proposedValue) const OVERRIDE; virtual bool shouldRespectListAttribute() OVERRIDE; diff --git a/Source/WebCore/html/TextFieldInputType.cpp b/Source/WebCore/html/TextFieldInputType.cpp index 3ec15bcde..d56f47d4e 100644 --- a/Source/WebCore/html/TextFieldInputType.cpp +++ b/Source/WebCore/html/TextFieldInputType.cpp @@ -43,6 +43,7 @@ #include "RenderTextControlSingleLine.h" #include "RenderTheme.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include "TextControlInnerElements.h" #include "TextEvent.h" #include "TextIterator.h" @@ -77,29 +78,51 @@ bool TextFieldInputType::canSetSuggestedValue() return true; } -void TextFieldInputType::setValue(const String& sanitizedValue, bool valueChanged, bool sendChangeEvent) +void TextFieldInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior) { - InputType::setValue(sanitizedValue, valueChanged, sendChangeEvent); + // Grab this input element to keep reference even if JS event handler + // changes input type. + RefPtr<HTMLInputElement> input(element()); + + // We don't ask InputType::setValue to dispatch events because + // TextFieldInputType dispatches events different way from InputType. + InputType::setValue(sanitizedValue, valueChanged, DispatchNoEvent); if (valueChanged) - element()->updateInnerTextValue(); + input->updateInnerTextValue(); unsigned max = visibleValue().length(); - if (element()->focused()) - element()->setSelectionRange(max, max); + if (input->focused()) + input->setSelectionRange(max, max); else - element()->cacheSelectionInResponseToSetValue(max); -} + input->cacheSelectionInResponseToSetValue(max); -void TextFieldInputType::dispatchChangeEventInResponseToSetValue() -{ - // If the user is still editing this field, dispatch an input event rather than a change event. - // The change event will be dispatched when editing finishes. - if (element()->focused()) { - element()->dispatchFormControlInputEvent(); + if (!valueChanged) return; + + switch (eventBehavior) { + case DispatchChangeEvent: + // If the user is still editing this field, dispatch an input event rather than a change event. + // The change event will be dispatched when editing finishes. + if (input->focused()) + input->dispatchFormControlInputEvent(); + else + input->dispatchFormControlChangeEvent(); + break; + + case DispatchInputAndChangeEvent: { + input->dispatchFormControlInputEvent(); + input->dispatchFormControlChangeEvent(); + break; } - InputType::dispatchChangeEventInResponseToSetValue(); + + case DispatchNoEvent: + break; + } + + // FIXME: Why do we do this when eventBehavior == DispatchNoEvent + if (!input->focused() || eventBehavior == DispatchNoEvent) + input->setTextAsOfLastFormControlChangeEvent(sanitizedValue); } void TextFieldInputType::handleKeydownEvent(KeyboardEvent* event) @@ -189,6 +212,8 @@ bool TextFieldInputType::needsContainer() const void TextFieldInputType::createShadowSubtree() { + ASSERT(element()->hasShadowRoot()); + ASSERT(!m_innerText); ASSERT(!m_innerBlock); ASSERT(!m_innerSpinButton); @@ -201,11 +226,11 @@ void TextFieldInputType::createShadowSubtree() ExceptionCode ec = 0; m_innerText = TextControlInnerTextElement::create(document); if (!createsContainer) { - element()->ensureShadowRoot()->appendChild(m_innerText, ec); + element()->shadowRootList()->oldestShadowRoot()->appendChild(m_innerText, ec); return; } - ShadowRoot* shadowRoot = element()->ensureShadowRoot(); + ShadowRoot* shadowRoot = element()->shadowRootList()->oldestShadowRoot(); m_container = HTMLDivElement::create(document); m_container->setShadowPseudoId("-webkit-textfield-decoration-container"); shadowRoot->appendChild(m_container, ec); @@ -367,7 +392,7 @@ void TextFieldInputType::updatePlaceholderText() if (!m_placeholder) { m_placeholder = HTMLDivElement::create(element()->document()); m_placeholder->setShadowPseudoId("-webkit-input-placeholder"); - element()->shadowRoot()->insertBefore(m_placeholder, m_container ? m_container->nextSibling() : innerTextElement()->nextSibling(), ec); + element()->shadowRootList()->oldestShadowRoot()->insertBefore(m_placeholder, m_container ? m_container->nextSibling() : innerTextElement()->nextSibling(), ec); ASSERT(!ec); } m_placeholder->setInnerText(placeholderText, ec); diff --git a/Source/WebCore/html/TextFieldInputType.h b/Source/WebCore/html/TextFieldInputType.h index f94018bb0..d26e28a9b 100644 --- a/Source/WebCore/html/TextFieldInputType.h +++ b/Source/WebCore/html/TextFieldInputType.h @@ -73,8 +73,7 @@ private: virtual bool shouldSubmitImplicitly(Event*) OVERRIDE; virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) const OVERRIDE; virtual bool shouldUseInputMethod() const OVERRIDE; - virtual void setValue(const String&, bool valueChanged, bool sendChangeEvent) OVERRIDE; - virtual void dispatchChangeEventInResponseToSetValue() OVERRIDE; + virtual void setValue(const String&, bool valueChanged, TextFieldEventBehavior) OVERRIDE; virtual String sanitizeValue(const String&) const OVERRIDE; virtual bool shouldRespectListAttribute() OVERRIDE; virtual HTMLElement* placeholderElement() const OVERRIDE; diff --git a/Source/WebCore/html/ValidationMessage.cpp b/Source/WebCore/html/ValidationMessage.cpp index bc3c45489..7653951b0 100644 --- a/Source/WebCore/html/ValidationMessage.cpp +++ b/Source/WebCore/html/ValidationMessage.cpp @@ -44,6 +44,7 @@ #include "RenderObject.h" #include "Settings.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include "Text.h" #include <wtf/PassOwnPtr.h> @@ -119,14 +120,13 @@ static void adjustBubblePosition(const LayoutRect& hostRect, HTMLElement* bubble hostY -= containerLocation.y() + container->borderTop(); } - StylePropertySet* style = bubble->ensureInlineStyleDecl(); - style->setProperty(CSSPropertyTop, hostY + hostRect.height(), CSSPrimitiveValue::CSS_PX); + bubble->setInlineStyleProperty(CSSPropertyTop, hostY + hostRect.height(), CSSPrimitiveValue::CSS_PX); // The 'left' value of ::-webkit-validation-bubble-arrow. const int bubbleArrowTopOffset = 32; double bubbleX = hostX; if (hostRect.width() / 2 < bubbleArrowTopOffset) bubbleX = max(hostX + hostRect.width() / 2 - bubbleArrowTopOffset, 0.0); - style->setProperty(CSSPropertyLeft, bubbleX, CSSPrimitiveValue::CSS_PX); + bubble->setInlineStyleProperty(CSSPropertyLeft, bubbleX, CSSPrimitiveValue::CSS_PX); } void ValidationMessage::buildBubbleTree(Timer<ValidationMessage>*) @@ -137,7 +137,7 @@ void ValidationMessage::buildBubbleTree(Timer<ValidationMessage>*) m_bubble->setShadowPseudoId("-webkit-validation-bubble"); // Need to force position:absolute because RenderMenuList doesn't assume it // contains non-absolute or non-fixed renderers as children. - m_bubble->ensureInlineStyleDecl()->setProperty(CSSPropertyPosition, CSSValueAbsolute); + m_bubble->setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute); ExceptionCode ec = 0; host->ensureShadowRoot()->appendChild(m_bubble.get(), ec); ASSERT(!ec); @@ -187,7 +187,7 @@ void ValidationMessage::deleteBubbleTree(Timer<ValidationMessage>*) m_messageBody = 0; HTMLElement* host = toHTMLElement(m_element); ExceptionCode ec; - host->shadowRoot()->removeChild(m_bubble.get(), ec); + host->shadowRootList()->oldestShadowRoot()->removeChild(m_bubble.get(), ec); m_bubble = 0; } m_message = String(); diff --git a/Source/WebCore/html/canvas/ArrayBufferView.idl b/Source/WebCore/html/canvas/ArrayBufferView.idl index ed158bfae..0e934e6cb 100644 --- a/Source/WebCore/html/canvas/ArrayBufferView.idl +++ b/Source/WebCore/html/canvas/ArrayBufferView.idl @@ -25,7 +25,7 @@ module html { interface [ - JSCustomToJS, + CustomToJSObject, JSNoStaticTables, OmitConstructor ] ArrayBufferView { diff --git a/Source/WebCore/html/canvas/CanvasGradient.idl b/Source/WebCore/html/canvas/CanvasGradient.idl index 75b19279b..496d4c1b1 100644 --- a/Source/WebCore/html/canvas/CanvasGradient.idl +++ b/Source/WebCore/html/canvas/CanvasGradient.idl @@ -27,8 +27,8 @@ module html { interface CanvasGradient { - void addColorStop(in [Optional=CallWithDefaultValue] float offset, - in [Optional=CallWithDefaultValue] DOMString color) + void addColorStop(in [Optional=DefaultIsUndefined] float offset, + in [Optional=DefaultIsUndefined] DOMString color) raises (DOMException); }; diff --git a/Source/WebCore/html/canvas/CanvasPixelArray.idl b/Source/WebCore/html/canvas/CanvasPixelArray.idl index a12c8ce9b..8c0836b09 100644 --- a/Source/WebCore/html/canvas/CanvasPixelArray.idl +++ b/Source/WebCore/html/canvas/CanvasPixelArray.idl @@ -31,7 +31,8 @@ module html { interface [ OmitConstructor, NumericIndexedGetter, - CustomIndexedSetter + CustomIndexedSetter, + V8CustomToJSObject ] CanvasPixelArray { #if !defined(V8_BINDING) || !V8_BINDING readonly attribute long length; diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext.h b/Source/WebCore/html/canvas/CanvasRenderingContext.h index 53278788d..124729cbe 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext.h +++ b/Source/WebCore/html/canvas/CanvasRenderingContext.h @@ -55,7 +55,6 @@ public: virtual bool isAccelerated() const { return false; } virtual void paintRenderingResultsToCanvas() {} - virtual bool paintsIntoCanvasBuffer() const { return true; } #if USE(ACCELERATED_COMPOSITING) virtual PlatformLayer* platformLayer() const { return 0; } diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext.idl b/Source/WebCore/html/canvas/CanvasRenderingContext.idl index acdd0b75c..b9373931f 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext.idl +++ b/Source/WebCore/html/canvas/CanvasRenderingContext.idl @@ -28,7 +28,7 @@ module html { interface [ JSCustomMarkFunction, JSGenerateIsReachable, - JSCustomToJS + JSCustomToJSObject ] CanvasRenderingContext { readonly attribute HTMLCanvasElement canvas; diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp index b0e053ff3..0d195ac50 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp +++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp @@ -155,20 +155,6 @@ bool CanvasRenderingContext2D::isAccelerated() const #endif } -bool CanvasRenderingContext2D::paintsIntoCanvasBuffer() const -{ -#if ENABLE(ACCELERATED_2D_CANVAS) && USE(ACCELERATED_COMPOSITING) - if (!isAccelerated()) - return true; - - RenderBox* renderBox = canvas()->renderBox(); - if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing()) - return false; -#endif - return true; -} - - void CanvasRenderingContext2D::reset() { unwindStateStack(); @@ -669,9 +655,8 @@ void CanvasRenderingContext2D::setTransform(float m11, float m12, float m21, flo AffineTransform ctm = state().m_transform; if (!ctm.isInvertible()) return; - c->concatCTM(c->getCTM().inverse()); - c->concatCTM(canvas()->baseTransform()); - state().m_transform = ctm.inverse() * state().m_transform; + c->setCTM(canvas()->baseTransform()); + state().m_transform = AffineTransform(); m_path.transform(ctm); state().m_invertibleCTM = true; @@ -1920,7 +1905,7 @@ void CanvasRenderingContext2D::setFont(const String& newFont) String declarationText("font: "); declarationText += newFont; - parser.parseDeclaration(tempDecl.get(), declarationText); + parser.parseDeclaration(tempDecl.get(), declarationText, 0, 0); if (tempDecl->isEmpty()) return; diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.h b/Source/WebCore/html/canvas/CanvasRenderingContext2D.h index 1f481b755..5581ee9d5 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.h +++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.h @@ -67,7 +67,6 @@ public: virtual bool is2d() const { return true; } virtual bool isAccelerated() const; - virtual bool paintsIntoCanvasBuffer() const; CanvasStyle* strokeStyle() const; void setStrokeStyle(PassRefPtr<CanvasStyle>); diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl b/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl index d4560f7a0..cec5ce7bb 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl +++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl @@ -30,38 +30,38 @@ module html { void save(); void restore(); - void scale(in [Optional=CallWithDefaultValue] float sx, - in [Optional=CallWithDefaultValue] float sy); - void rotate(in [Optional=CallWithDefaultValue] float angle); - void translate(in [Optional=CallWithDefaultValue] float tx, - in [Optional=CallWithDefaultValue] float ty); - void transform(in [Optional=CallWithDefaultValue] float m11, - in [Optional=CallWithDefaultValue] float m12, - in [Optional=CallWithDefaultValue] float m21, - in [Optional=CallWithDefaultValue] float m22, - in [Optional=CallWithDefaultValue] float dx, - in [Optional=CallWithDefaultValue] float dy); - void setTransform(in [Optional=CallWithDefaultValue] float m11, - in [Optional=CallWithDefaultValue] float m12, - in [Optional=CallWithDefaultValue] float m21, - in [Optional=CallWithDefaultValue] float m22, - in [Optional=CallWithDefaultValue] float dx, - in [Optional=CallWithDefaultValue] float dy); + void scale(in [Optional=DefaultIsUndefined] float sx, + in [Optional=DefaultIsUndefined] float sy); + void rotate(in [Optional=DefaultIsUndefined] float angle); + void translate(in [Optional=DefaultIsUndefined] float tx, + in [Optional=DefaultIsUndefined] float ty); + void transform(in [Optional=DefaultIsUndefined] float m11, + in [Optional=DefaultIsUndefined] float m12, + in [Optional=DefaultIsUndefined] float m21, + in [Optional=DefaultIsUndefined] float m22, + in [Optional=DefaultIsUndefined] float dx, + in [Optional=DefaultIsUndefined] float dy); + void setTransform(in [Optional=DefaultIsUndefined] float m11, + in [Optional=DefaultIsUndefined] float m12, + in [Optional=DefaultIsUndefined] float m21, + in [Optional=DefaultIsUndefined] float m22, + in [Optional=DefaultIsUndefined] float dx, + in [Optional=DefaultIsUndefined] float dy); attribute float globalAlpha; attribute [TreatNullAs=NullString] DOMString globalCompositeOperation; - CanvasGradient createLinearGradient(in [Optional=CallWithDefaultValue] float x0, - in [Optional=CallWithDefaultValue] float y0, - in [Optional=CallWithDefaultValue] float x1, - in [Optional=CallWithDefaultValue] float y1) + CanvasGradient createLinearGradient(in [Optional=DefaultIsUndefined] float x0, + in [Optional=DefaultIsUndefined] float y0, + in [Optional=DefaultIsUndefined] float x1, + in [Optional=DefaultIsUndefined] float y1) raises (DOMException); - CanvasGradient createRadialGradient(in [Optional=CallWithDefaultValue] float x0, - in [Optional=CallWithDefaultValue] float y0, - in [Optional=CallWithDefaultValue] float r0, - in [Optional=CallWithDefaultValue] float x1, - in [Optional=CallWithDefaultValue] float y1, - in [Optional=CallWithDefaultValue] float r1) + CanvasGradient createRadialGradient(in [Optional=DefaultIsUndefined] float x0, + in [Optional=DefaultIsUndefined] float y0, + in [Optional=DefaultIsUndefined] float r0, + in [Optional=DefaultIsUndefined] float x1, + in [Optional=DefaultIsUndefined] float y1, + in [Optional=DefaultIsUndefined] float r1) raises (DOMException); attribute float lineWidth; @@ -80,71 +80,71 @@ module html { attribute float webkitLineDashOffset; #endif - void clearRect(in [Optional=CallWithDefaultValue] float x, - in [Optional=CallWithDefaultValue] float y, - in [Optional=CallWithDefaultValue] float width, - in [Optional=CallWithDefaultValue] float height); - void fillRect(in [Optional=CallWithDefaultValue] float x, - in [Optional=CallWithDefaultValue] float y, - in [Optional=CallWithDefaultValue] float width, - in [Optional=CallWithDefaultValue] float height); + void clearRect(in [Optional=DefaultIsUndefined] float x, + in [Optional=DefaultIsUndefined] float y, + in [Optional=DefaultIsUndefined] float width, + in [Optional=DefaultIsUndefined] float height); + void fillRect(in [Optional=DefaultIsUndefined] float x, + in [Optional=DefaultIsUndefined] float y, + in [Optional=DefaultIsUndefined] float width, + in [Optional=DefaultIsUndefined] float height); void beginPath(); void closePath(); - void moveTo(in [Optional=CallWithDefaultValue] float x, - in [Optional=CallWithDefaultValue] float y); - void lineTo(in [Optional=CallWithDefaultValue] float x, - in [Optional=CallWithDefaultValue] float y); - void quadraticCurveTo(in [Optional=CallWithDefaultValue] float cpx, - in [Optional=CallWithDefaultValue] float cpy, - in [Optional=CallWithDefaultValue] float x, - in [Optional=CallWithDefaultValue] float y); - void bezierCurveTo(in [Optional=CallWithDefaultValue] float cp1x, - in [Optional=CallWithDefaultValue] float cp1y, - in [Optional=CallWithDefaultValue] float cp2x, - in [Optional=CallWithDefaultValue] float cp2y, - in [Optional=CallWithDefaultValue] float x, - in [Optional=CallWithDefaultValue] float y); - void arcTo(in [Optional=CallWithDefaultValue] float x1, - in [Optional=CallWithDefaultValue] float y1, - in [Optional=CallWithDefaultValue] float x2, - in [Optional=CallWithDefaultValue] float y2, - in [Optional=CallWithDefaultValue] float radius) - raises (DOMException); - void rect(in [Optional=CallWithDefaultValue] float x, - in [Optional=CallWithDefaultValue] float y, - in [Optional=CallWithDefaultValue] float width, - in [Optional=CallWithDefaultValue] float height); - void arc(in [Optional=CallWithDefaultValue] float x, - in [Optional=CallWithDefaultValue] float y, - in [Optional=CallWithDefaultValue] float radius, - in [Optional=CallWithDefaultValue] float startAngle, - in [Optional=CallWithDefaultValue] float endAngle, - in [Optional=CallWithDefaultValue] boolean anticlockwise) + void moveTo(in [Optional=DefaultIsUndefined] float x, + in [Optional=DefaultIsUndefined] float y); + void lineTo(in [Optional=DefaultIsUndefined] float x, + in [Optional=DefaultIsUndefined] float y); + void quadraticCurveTo(in [Optional=DefaultIsUndefined] float cpx, + in [Optional=DefaultIsUndefined] float cpy, + in [Optional=DefaultIsUndefined] float x, + in [Optional=DefaultIsUndefined] float y); + void bezierCurveTo(in [Optional=DefaultIsUndefined] float cp1x, + in [Optional=DefaultIsUndefined] float cp1y, + in [Optional=DefaultIsUndefined] float cp2x, + in [Optional=DefaultIsUndefined] float cp2y, + in [Optional=DefaultIsUndefined] float x, + in [Optional=DefaultIsUndefined] float y); + void arcTo(in [Optional=DefaultIsUndefined] float x1, + in [Optional=DefaultIsUndefined] float y1, + in [Optional=DefaultIsUndefined] float x2, + in [Optional=DefaultIsUndefined] float y2, + in [Optional=DefaultIsUndefined] float radius) + raises (DOMException); + void rect(in [Optional=DefaultIsUndefined] float x, + in [Optional=DefaultIsUndefined] float y, + in [Optional=DefaultIsUndefined] float width, + in [Optional=DefaultIsUndefined] float height); + void arc(in [Optional=DefaultIsUndefined] float x, + in [Optional=DefaultIsUndefined] float y, + in [Optional=DefaultIsUndefined] float radius, + in [Optional=DefaultIsUndefined] float startAngle, + in [Optional=DefaultIsUndefined] float endAngle, + in [Optional=DefaultIsUndefined] boolean anticlockwise) raises (DOMException); void fill(); void stroke(); void clip(); - boolean isPointInPath(in [Optional=CallWithDefaultValue] float x, - in [Optional=CallWithDefaultValue] float y); + boolean isPointInPath(in [Optional=DefaultIsUndefined] float x, + in [Optional=DefaultIsUndefined] float y); // text attribute DOMString font; attribute DOMString textAlign; attribute DOMString textBaseline; - TextMetrics measureText(in [Optional=CallWithDefaultValue] DOMString text); + TextMetrics measureText(in [Optional=DefaultIsUndefined] DOMString text); // other - void setAlpha(in [Optional=CallWithDefaultValue] float alpha); - void setCompositeOperation(in [Optional=CallWithDefaultValue] DOMString compositeOperation); + void setAlpha(in [Optional=DefaultIsUndefined] float alpha); + void setCompositeOperation(in [Optional=DefaultIsUndefined] DOMString compositeOperation); #if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP - void setLineWidth(in [Optional=CallWithDefaultValue] float width); - void setLineCap(in [Optional=CallWithDefaultValue] DOMString cap); - void setLineJoin(in [Optional=CallWithDefaultValue] DOMString join); - void setMiterLimit(in [Optional=CallWithDefaultValue] float limit); + void setLineWidth(in [Optional=DefaultIsUndefined] float width); + void setLineCap(in [Optional=DefaultIsUndefined] DOMString cap); + void setLineJoin(in [Optional=DefaultIsUndefined] DOMString join); + void setMiterLimit(in [Optional=DefaultIsUndefined] float limit); #endif void clearShadow(); @@ -162,10 +162,10 @@ module html { void setFillColor(in float r, in float g, in float b, in float a); void setFillColor(in float c, in float m, in float y, in float k, in float a); - void strokeRect(in [Optional=CallWithDefaultValue] float x, - in [Optional=CallWithDefaultValue] float y, - in [Optional=CallWithDefaultValue] float width, - in [Optional=CallWithDefaultValue] float height, + void strokeRect(in [Optional=DefaultIsUndefined] float x, + in [Optional=DefaultIsUndefined] float y, + in [Optional=DefaultIsUndefined] float width, + in [Optional=DefaultIsUndefined] float height, in [Optional] float lineWidth); void drawImage(in HTMLImageElement image, in float x, in float y) @@ -217,8 +217,8 @@ module html { attribute [Custom] custom fillStyle; // pixel manipulation - ImageData getImageData(in [Optional=CallWithDefaultValue] float sx, in [Optional=CallWithDefaultValue] float sy, - in [Optional=CallWithDefaultValue] float sw, in [Optional=CallWithDefaultValue] float sh) + ImageData getImageData(in [Optional=DefaultIsUndefined] float sx, in [Optional=DefaultIsUndefined] float sy, + in [Optional=DefaultIsUndefined] float sw, in [Optional=DefaultIsUndefined] float sh) raises(DOMException); }; diff --git a/Source/WebCore/html/canvas/DOMWindowWebGL.idl b/Source/WebCore/html/canvas/DOMWindowWebGL.idl new file mode 100644 index 000000000..92056d3da --- /dev/null +++ b/Source/WebCore/html/canvas/DOMWindowWebGL.idl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 Google 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. + */ + +module window { + + interface [ + Conditional=WEBGL, + Supplemental=DOMWindow + ] DOMWindowWebGL { + attribute WebGLActiveInfoConstructor WebGLActiveInfo; + attribute WebGLBufferConstructor WebGLBuffer; + attribute WebGLFramebufferConstructor WebGLFramebuffer; + attribute WebGLProgramConstructor WebGLProgram; + attribute WebGLRenderbufferConstructor WebGLRenderbuffer; + attribute WebGLRenderingContextConstructor WebGLRenderingContext; + attribute WebGLShaderConstructor WebGLShader; + attribute WebGLTextureConstructor WebGLTexture; + attribute WebGLUniformLocationConstructor WebGLUniformLocation; + }; + +} diff --git a/Source/WebCore/html/canvas/DataView.idl b/Source/WebCore/html/canvas/DataView.idl index 9530220dc..27bad0e47 100755 --- a/Source/WebCore/html/canvas/DataView.idl +++ b/Source/WebCore/html/canvas/DataView.idl @@ -27,7 +27,7 @@ module html { interface [ CustomConstructor, - JSCustomToJS, + CustomToJSObject, JSNoStaticTables ] DataView : ArrayBufferView { // All these methods raise an exception if they would read or write beyond the end of the view. diff --git a/Source/WebCore/html/canvas/Float32Array.idl b/Source/WebCore/html/canvas/Float32Array.idl index 785ed819c..5e619a7ea 100644 --- a/Source/WebCore/html/canvas/Float32Array.idl +++ b/Source/WebCore/html/canvas/Float32Array.idl @@ -31,13 +31,13 @@ module html { CustomIndexedSetter, JSGenerateToNativeObject, JSNoStaticTables, - JSCustomToJS, + CustomToJSObject, DoNotCheckConstants ] Float32Array : ArrayBufferView { const unsigned int BYTES_PER_ELEMENT = 4; readonly attribute unsigned long length; - Float32Array subarray(in [Optional=CallWithDefaultValue] long start, + Float32Array subarray(in [Optional=DefaultIsUndefined] long start, in [Optional] long end); // void set(in Float32Array array, [Optional] in unsigned long offset); diff --git a/Source/WebCore/html/canvas/Float64Array.idl b/Source/WebCore/html/canvas/Float64Array.idl index 7180811fa..f4c448a45 100644 --- a/Source/WebCore/html/canvas/Float64Array.idl +++ b/Source/WebCore/html/canvas/Float64Array.idl @@ -31,13 +31,13 @@ module html { CustomIndexedSetter, JSGenerateToNativeObject, JSNoStaticTables, - JSCustomToJS, + CustomToJSObject, DoNotCheckConstants ] Float64Array : ArrayBufferView { const unsigned int BYTES_PER_ELEMENT = 8; readonly attribute unsigned long length; - Float64Array subarray(in [Optional=CallWithDefaultValue] long start, + Float64Array subarray(in [Optional=DefaultIsUndefined] long start, in [Optional] long end); // void set(in Float64Array array, [Optional] in unsigned long offset); diff --git a/Source/WebCore/html/canvas/Int16Array.idl b/Source/WebCore/html/canvas/Int16Array.idl index 40e18d530..b7ddc1e7c 100644 --- a/Source/WebCore/html/canvas/Int16Array.idl +++ b/Source/WebCore/html/canvas/Int16Array.idl @@ -30,13 +30,13 @@ module html { CustomIndexedSetter, JSGenerateToNativeObject, JSNoStaticTables, - JSCustomToJS, + CustomToJSObject, DoNotCheckConstants ] Int16Array : ArrayBufferView { const unsigned int BYTES_PER_ELEMENT = 2; readonly attribute unsigned long length; - Int16Array subarray(in [Optional=CallWithDefaultValue] long start, + Int16Array subarray(in [Optional=DefaultIsUndefined] long start, in [Optional] long end); // void set(in Int16Array array, [Optional] in unsigned long offset); diff --git a/Source/WebCore/html/canvas/Int32Array.idl b/Source/WebCore/html/canvas/Int32Array.idl index 0f5320ac4..950437aec 100644 --- a/Source/WebCore/html/canvas/Int32Array.idl +++ b/Source/WebCore/html/canvas/Int32Array.idl @@ -31,13 +31,13 @@ module html { CustomIndexedSetter, JSGenerateToNativeObject, JSNoStaticTables, - JSCustomToJS, + CustomToJSObject, DoNotCheckConstants ] Int32Array : ArrayBufferView { const unsigned int BYTES_PER_ELEMENT = 4; readonly attribute unsigned long length; - Int32Array subarray(in [Optional=CallWithDefaultValue] long start, + Int32Array subarray(in [Optional=DefaultIsUndefined] long start, in [Optional] long end); // void set(in Int32Array array, [Optional] in unsigned long offset); diff --git a/Source/WebCore/html/canvas/Int8Array.idl b/Source/WebCore/html/canvas/Int8Array.idl index 9984ada66..da0c8f166 100644 --- a/Source/WebCore/html/canvas/Int8Array.idl +++ b/Source/WebCore/html/canvas/Int8Array.idl @@ -31,13 +31,13 @@ module html { CustomIndexedSetter, JSGenerateToNativeObject, JSNoStaticTables, - JSCustomToJS, + CustomToJSObject, DoNotCheckConstants ] Int8Array : ArrayBufferView { const unsigned int BYTES_PER_ELEMENT = 1; readonly attribute unsigned long length; - Int8Array subarray(in [Optional=CallWithDefaultValue] long start, + Int8Array subarray(in [Optional=DefaultIsUndefined] long start, in [Optional] long end); // void set(in Int8Array array, [Optional] in unsigned long offset); diff --git a/Source/WebCore/html/canvas/OESVertexArrayObject.idl b/Source/WebCore/html/canvas/OESVertexArrayObject.idl index c4adf99d8..c3d366676 100644 --- a/Source/WebCore/html/canvas/OESVertexArrayObject.idl +++ b/Source/WebCore/html/canvas/OESVertexArrayObject.idl @@ -33,8 +33,8 @@ module html { const unsigned int VERTEX_ARRAY_BINDING_OES = 0x85B5; [StrictTypeChecking] WebGLVertexArrayObjectOES createVertexArrayOES(); - [StrictTypeChecking] void deleteVertexArrayOES(in [Optional=CallWithDefaultValue] WebGLVertexArrayObjectOES arrayObject); - [StrictTypeChecking] boolean isVertexArrayOES(in [Optional=CallWithDefaultValue] WebGLVertexArrayObjectOES arrayObject); - [StrictTypeChecking] void bindVertexArrayOES(in [Optional=CallWithDefaultValue] WebGLVertexArrayObjectOES arrayObject) raises(DOMException); + [StrictTypeChecking] void deleteVertexArrayOES(in [Optional=DefaultIsUndefined] WebGLVertexArrayObjectOES arrayObject); + [StrictTypeChecking] boolean isVertexArrayOES(in [Optional=DefaultIsUndefined] WebGLVertexArrayObjectOES arrayObject); + [StrictTypeChecking] void bindVertexArrayOES(in [Optional=DefaultIsUndefined] WebGLVertexArrayObjectOES arrayObject) raises(DOMException); }; } diff --git a/Source/WebCore/html/canvas/Uint16Array.idl b/Source/WebCore/html/canvas/Uint16Array.idl index 83877b582..33627bfce 100644 --- a/Source/WebCore/html/canvas/Uint16Array.idl +++ b/Source/WebCore/html/canvas/Uint16Array.idl @@ -31,13 +31,13 @@ module html { CustomIndexedSetter, JSGenerateToNativeObject, JSNoStaticTables, - JSCustomToJS, + CustomToJSObject, DoNotCheckConstants ] Uint16Array : ArrayBufferView { const unsigned int BYTES_PER_ELEMENT = 2; readonly attribute unsigned long length; - Uint16Array subarray(in [Optional=CallWithDefaultValue] long start, in [Optional] long end); + Uint16Array subarray(in [Optional=DefaultIsUndefined] long start, in [Optional] long end); // void set(in Uint16Array array, [Optional] in unsigned long offset); // void set(in sequence<long> array, [Optional] in unsigned long offset); diff --git a/Source/WebCore/html/canvas/Uint32Array.idl b/Source/WebCore/html/canvas/Uint32Array.idl index 2726473cb..7bb4ca39b 100644 --- a/Source/WebCore/html/canvas/Uint32Array.idl +++ b/Source/WebCore/html/canvas/Uint32Array.idl @@ -31,13 +31,13 @@ module html { CustomIndexedSetter, JSGenerateToNativeObject, JSNoStaticTables, - JSCustomToJS, + CustomToJSObject, DoNotCheckConstants ] Uint32Array : ArrayBufferView { const unsigned int BYTES_PER_ELEMENT = 4; readonly attribute unsigned long length; - Uint32Array subarray(in [Optional=CallWithDefaultValue] long start, in [Optional] long end); + Uint32Array subarray(in [Optional=DefaultIsUndefined] long start, in [Optional] long end); // void set(in Uint32Array array, [Optional] in unsigned long offset); // void set(in sequence<long> array, [Optional] in unsigned long offset); diff --git a/Source/WebCore/html/canvas/Uint8Array.idl b/Source/WebCore/html/canvas/Uint8Array.idl index 4892da8a8..fbbafc320 100644 --- a/Source/WebCore/html/canvas/Uint8Array.idl +++ b/Source/WebCore/html/canvas/Uint8Array.idl @@ -31,13 +31,13 @@ module html { CustomIndexedSetter, JSGenerateToNativeObject, JSNoStaticTables, - JSCustomToJS, + CustomToJSObject, DoNotCheckConstants ] Uint8Array : ArrayBufferView { const unsigned int BYTES_PER_ELEMENT = 1; readonly attribute unsigned long length; - Uint8Array subarray(in [Optional=CallWithDefaultValue] long start, in [Optional] long end); + Uint8Array subarray(in [Optional=DefaultIsUndefined] long start, in [Optional] long end); // void set(in Uint8Array array, [Optional] in unsigned long offset); // void set(in sequence<long> array, [Optional] in unsigned long offset); diff --git a/Source/WebCore/html/canvas/Uint8ClampedArray.idl b/Source/WebCore/html/canvas/Uint8ClampedArray.idl index a9a49f362..fd006e455 100644 --- a/Source/WebCore/html/canvas/Uint8ClampedArray.idl +++ b/Source/WebCore/html/canvas/Uint8ClampedArray.idl @@ -31,13 +31,13 @@ module html { CustomIndexedSetter, JSGenerateToNativeObject, JSNoStaticTables, - JSCustomToJS, + CustomToJSObject, DoNotCheckConstants ] Uint8ClampedArray : Uint8Array { const unsigned int BYTES_PER_ELEMENT = 1; readonly attribute unsigned long length; - Uint8ClampedArray subarray(in [Optional=CallWithDefaultValue] long start, in [Optional] long end); + Uint8ClampedArray subarray(in [Optional=DefaultIsUndefined] long start, in [Optional] long end); // FIXME: Missing other setters! // void set(in Uint8ClampedArray array, [Optional] in unsigned long offset); diff --git a/Source/WebCore/html/canvas/WebGLDebugShaders.idl b/Source/WebCore/html/canvas/WebGLDebugShaders.idl index 82d047550..ee330b6ae 100644 --- a/Source/WebCore/html/canvas/WebGLDebugShaders.idl +++ b/Source/WebCore/html/canvas/WebGLDebugShaders.idl @@ -29,6 +29,6 @@ module html { JSGenerateIsReachable=ImplContext, OmitConstructor ] WebGLDebugShaders { - [StrictTypeChecking, ConvertNullStringTo=Null] DOMString getTranslatedShaderSource(in WebGLShader shader) raises(DOMException); + [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getTranslatedShaderSource(in WebGLShader shader) raises(DOMException); }; } diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp index 9a5a295b5..cfb6505a9 100644 --- a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp +++ b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp @@ -719,11 +719,6 @@ PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData() return imageData; } -bool WebGLRenderingContext::paintsIntoCanvasBuffer() const -{ - return m_context->paintsIntoCanvasBuffer(); -} - void WebGLRenderingContext::reshape(int width, int height) { // This is an approximation because at WebGLRenderingContext level we don't @@ -4890,7 +4885,21 @@ bool WebGLRenderingContext::validateStencilFunc(const char* functionName, GC3Den void WebGLRenderingContext::printWarningToConsole(const String& message) { - canvas()->document()->frame()->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, canvas()->document()->url().string()); + if (!canvas()) + return; + Document* document = canvas()->document(); + if (!document) + return; + Frame* frame = document->frame(); + if (!frame) + return; + DOMWindow* window = frame->domWindow(); + if (!window) + return; + Console* console = window->console(); + if (!console) + return; + console->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, document->url().string()); } bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.h b/Source/WebCore/html/canvas/WebGLRenderingContext.h index 0449eade1..be9c8cf3c 100644 --- a/Source/WebCore/html/canvas/WebGLRenderingContext.h +++ b/Source/WebCore/html/canvas/WebGLRenderingContext.h @@ -77,7 +77,6 @@ public: virtual bool is3d() const { return true; } virtual bool isAccelerated() const { return true; } - virtual bool paintsIntoCanvasBuffer() const; int drawingBufferWidth() const; int drawingBufferHeight() const; diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.idl b/Source/WebCore/html/canvas/WebGLRenderingContext.idl index 6db811dd8..3aed43643 100644 --- a/Source/WebCore/html/canvas/WebGLRenderingContext.idl +++ b/Source/WebCore/html/canvas/WebGLRenderingContext.idl @@ -542,18 +542,18 @@ module html { [StrictTypeChecking, Custom] void getParameter(); // any getProgramParameter(in WebGLProgram program, in unsigned long pname) raises(DOMException); [StrictTypeChecking, Custom] void getProgramParameter(); - [StrictTypeChecking, ConvertNullStringTo=Null] DOMString getProgramInfoLog(in WebGLProgram program) raises(DOMException); + [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getProgramInfoLog(in WebGLProgram program) raises(DOMException); // any getRenderbufferParameter(in unsigned long target, in unsigned long pname) raises(DOMException); [StrictTypeChecking, Custom] void getRenderbufferParameter(); // any getShaderParameter(in WebGLShader shader, in unsigned long pname) raises(DOMException); [StrictTypeChecking, Custom] void getShaderParameter() raises(DOMException); - [StrictTypeChecking, ConvertNullStringTo=Null] DOMString getShaderInfoLog(in WebGLShader shader) raises(DOMException); + [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getShaderInfoLog(in WebGLShader shader) raises(DOMException); // TBD // void glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); - [StrictTypeChecking, ConvertNullStringTo=Null] DOMString getShaderSource(in WebGLShader shader) raises(DOMException); + [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getShaderSource(in WebGLShader shader) raises(DOMException); // DOMString[] getSupportedExtensions() [StrictTypeChecking, Custom] void getSupportedExtensions(); diff --git a/Source/WebCore/html/parser/HTMLElementStack.cpp b/Source/WebCore/html/parser/HTMLElementStack.cpp index 98885743e..9cc3a0316 100644 --- a/Source/WebCore/html/parser/HTMLElementStack.cpp +++ b/Source/WebCore/html/parser/HTMLElementStack.cpp @@ -53,7 +53,6 @@ inline bool isNumberedHeaderElement(ContainerNode* node) inline bool isRootNode(ContainerNode* node) { return node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE - || node->nodeType() == Node::SHADOW_ROOT_NODE || node->hasTagName(htmlTag); } @@ -310,7 +309,7 @@ void HTMLElementStack::popUntilForeignContentScopeMarker() void HTMLElementStack::pushRootNode(PassRefPtr<ContainerNode> rootNode) { - ASSERT(rootNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE || rootNode->nodeType() == Node::SHADOW_ROOT_NODE); + ASSERT(rootNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE); pushRootNodeCommon(rootNode); } diff --git a/Source/WebCore/html/parser/HTMLElementStack.h b/Source/WebCore/html/parser/HTMLElementStack.h index f604f82c7..5697e80c8 100644 --- a/Source/WebCore/html/parser/HTMLElementStack.h +++ b/Source/WebCore/html/parser/HTMLElementStack.h @@ -180,8 +180,7 @@ inline bool isInHTMLNamespace(Node* node) // A DocumentFragment takes the place of the document element when parsing // fragments and should be considered in the HTML namespace. return node->namespaceURI() == HTMLNames::xhtmlNamespaceURI - || node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE - || node->nodeType() == Node::SHADOW_ROOT_NODE; // FIXME: Does this also apply to ShadowRoot? + || node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE; // FIXME: Does this also apply to ShadowRoot? } diff --git a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp index 9d839120d..3b5414913 100644 --- a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp +++ b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp @@ -586,10 +586,8 @@ void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken& token) notImplemented(); // Acknowledge self-closing flag processFakeStartTag(formTag); RefPtr<Attribute> actionAttribute = token.getAttributeItem(actionAttr); - if (actionAttribute) { - ASSERT(m_tree.currentElement()->hasTagName(formTag)); - m_tree.currentElement()->setAttribute(actionAttr, actionAttribute->value()); - } + if (actionAttribute) + m_tree.form()->setAttribute(actionAttr, actionAttribute->value()); processFakeStartTag(hrTag); processFakeStartTag(labelTag); RefPtr<Attribute> promptAttribute = token.getAttributeItem(promptAttr); diff --git a/Source/WebCore/html/parser/XSSAuditor.cpp b/Source/WebCore/html/parser/XSSAuditor.cpp index 138a67118..8fde1a5d7 100644 --- a/Source/WebCore/html/parser/XSSAuditor.cpp +++ b/Source/WebCore/html/parser/XSSAuditor.cpp @@ -36,6 +36,7 @@ #include "FrameLoaderClient.h" #include "HTMLDocumentParser.h" #include "HTMLNames.h" +#include "HTMLTokenizer.h" #include "HTMLParamElement.h" #include "HTMLParserIdioms.h" #include "SecurityOrigin.h" @@ -54,7 +55,7 @@ static bool isNonCanonicalCharacter(UChar c) // We remove all non-ASCII characters, including non-printable ASCII characters. // // Note, we don't remove backslashes like PHP stripslashes(), which among other things converts "\\0" to the \0 character. - // Instead, we remove backslashes and zeros (since the string "\\0" =(remove backslashes)=> "0"). However, this has the + // Instead, we remove backslashes and zeros (since the string "\\0" =(remove backslashes)=> "0"). However, this has the // adverse effect that we remove any legitimate zeros from a string. // // For instance: new String("http://localhost:8000") => new String("http://localhost:8"). @@ -71,7 +72,7 @@ static bool isRequiredForInjection(UChar c) return (c == '\'' || c == '"' || c == '<' || c == '>'); } -static bool isTerminatingCharacter(UChar c) +static bool isTerminatingCharacter(UChar c) { return (c == '&' || c == '/' || c == '"' || c == '\'' || c == '<'); } @@ -81,26 +82,21 @@ static bool isHTMLQuote(UChar c) return (c == '"' || c == '\''); } -static bool isHTMLNewline(UChar c) +static bool isJSNewline(UChar c) { - return (c == '\n' || c == '\r'); + // Per ecma-262 section 7.3 Line Terminators. + return (c == '\n' || c == '\r' || c == 0x2028 || c == 0x2029); } -static bool startsHTMLEndTagAt(const String& string, size_t start) -{ - return (start + 1 < string.length() && string[start] == '<' && string[start+1] == '/'); -} - - static bool startsHTMLCommentAt(const String& string, size_t start) { return (start + 3 < string.length() && string[start] == '<' && string[start+1] == '!' && string[start+2] == '-' && string[start+3] == '-'); -} +} static bool startsSingleLineCommentAt(const String& string, size_t start) { return (start + 1 < string.length() && string[start] == '/' && string[start+1] == '/'); -} +} static bool startsMultiLineCommentAt(const String& string, size_t start) { @@ -137,23 +133,6 @@ static bool isDangerousHTTPEquiv(const String& value) return equalIgnoringCase(equiv, "refresh") || equalIgnoringCase(equiv, "set-cookie"); } -static bool containsJavaScriptURL(const Vector<UChar, 32>& value) -{ - static const char javaScriptScheme[] = "javascript:"; - static const size_t lengthOfJavaScriptScheme = sizeof(javaScriptScheme) - 1; - - size_t i; - for (i = 0; i < value.size(); ++i) { - if (!isHTMLSpace(value[i])) - break; - } - - if (value.size() - i < lengthOfJavaScriptScheme) - return false; - - return equalIgnoringCase(value.data() + i, javaScriptScheme, lengthOfJavaScriptScheme); -} - static inline String decode16BitUnicodeEscapeSequences(const String& string) { // Note, the encoding is ignored since each %u-escape sequence represents a UTF-16 code unit. @@ -176,7 +155,6 @@ static String fullyDecodeString(const String& string, const TextResourceDecoder* oldWorkingStringLength = workingString.length(); workingString = decode16BitUnicodeEscapeSequences(decodeStandardURLEscapeSequences(workingString, encoding)); } while (workingString.length() < oldWorkingStringLength); - ASSERT(!workingString.isEmpty()); workingString.replace('+', ' '); workingString = canonicalize(workingString); return workingString; @@ -187,6 +165,8 @@ XSSAuditor::XSSAuditor(HTMLDocumentParser* parser) , m_isEnabled(false) , m_xssProtection(XSSProtectionEnabled) , m_state(Uninitialized) + , m_shouldAllowCDATA(false) + , m_scriptTagNestingLevel(0) , m_notifiedClient(false) { ASSERT(m_parser); @@ -204,7 +184,7 @@ void XSSAuditor::init() const int suffixTreeDepth = 5; ASSERT(m_state == Uninitialized); - m_state = Initial; + m_state = Initialized; if (!m_isEnabled) return; @@ -257,28 +237,21 @@ void XSSAuditor::init() void XSSAuditor::filterToken(HTMLToken& token) { - if (m_state == Uninitialized) { + if (m_state == Uninitialized) init(); - ASSERT(m_state == Initial); - } - + + ASSERT(m_state == Initialized); if (!m_isEnabled || m_xssProtection == XSSProtectionDisabled) return; bool didBlockScript = false; - - switch (m_state) { - case Uninitialized: - ASSERT_NOT_REACHED(); - break; - case Initial: - didBlockScript = filterTokenInitial(token); - break; - case AfterScriptStartTag: - didBlockScript = filterTokenAfterScriptStartTag(token); - ASSERT(m_state == Initial); - m_cachedSnippet = String(); - break; + if (token.type() == HTMLTokenTypes::StartTag) + didBlockScript = filterStartToken(token); + else if (m_scriptTagNestingLevel) { + if (token.type() == HTMLTokenTypes::Character) + didBlockScript = filterCharacterToken(token); + else if (token.type() == HTMLTokenTypes::EndTag) + filterEndToken(token); } if (didBlockScript) { @@ -300,18 +273,15 @@ void XSSAuditor::filterToken(HTMLToken& token) } } -bool XSSAuditor::filterTokenInitial(HTMLToken& token) +bool XSSAuditor::filterStartToken(HTMLToken& token) { - ASSERT(m_state == Initial); - - if (token.type() != HTMLTokenTypes::StartTag) - return false; - bool didBlockScript = eraseDangerousAttributesIfInjected(token); - if (hasName(token, scriptTag)) + if (hasName(token, scriptTag)) { didBlockScript |= filterScriptToken(token); - else if (hasName(token, objectTag)) + ASSERT(m_shouldAllowCDATA || !m_scriptTagNestingLevel); + m_scriptTagNestingLevel++; + } else if (hasName(token, objectTag)) didBlockScript |= filterObjectToken(token); else if (hasName(token, paramTag)) didBlockScript |= filterParamToken(token); @@ -331,16 +301,18 @@ bool XSSAuditor::filterTokenInitial(HTMLToken& token) return didBlockScript; } -bool XSSAuditor::filterTokenAfterScriptStartTag(HTMLToken& token) +void XSSAuditor::filterEndToken(HTMLToken& token) { - ASSERT(m_state == AfterScriptStartTag); - m_state = Initial; - - if (token.type() != HTMLTokenTypes::Character) { - ASSERT(token.type() == HTMLTokenTypes::EndTag || token.type() == HTMLTokenTypes::EndOfFile); - return false; + ASSERT(m_scriptTagNestingLevel); + if (hasName(token, scriptTag)) { + m_scriptTagNestingLevel--; + ASSERT(m_shouldAllowCDATA || !m_scriptTagNestingLevel); } +} +bool XSSAuditor::filterCharacterToken(HTMLToken& token) +{ + ASSERT(m_scriptTagNestingLevel); TextResourceDecoder* decoder = m_parser->document()->decoder(); if (isContainedInRequest(fullyDecodeString(m_cachedSnippet, decoder))) { int start = 0; @@ -357,21 +329,19 @@ bool XSSAuditor::filterTokenAfterScriptStartTag(HTMLToken& token) bool XSSAuditor::filterScriptToken(HTMLToken& token) { - ASSERT(m_state == Initial); ASSERT(token.type() == HTMLTokenTypes::StartTag); ASSERT(hasName(token, scriptTag)); if (eraseAttributeIfInjected(token, srcAttr, blankURL().string(), SrcLikeAttribute)) return true; - m_state = AfterScriptStartTag; m_cachedSnippet = m_parser->sourceForToken(token); + m_shouldAllowCDATA = m_parser->tokenizer()->shouldAllowCDATA(); return false; } bool XSSAuditor::filterObjectToken(HTMLToken& token) { - ASSERT(m_state == Initial); ASSERT(token.type() == HTMLTokenTypes::StartTag); ASSERT(hasName(token, objectTag)); @@ -386,7 +356,6 @@ bool XSSAuditor::filterObjectToken(HTMLToken& token) bool XSSAuditor::filterParamToken(HTMLToken& token) { - ASSERT(m_state == Initial); ASSERT(token.type() == HTMLTokenTypes::StartTag); ASSERT(hasName(token, paramTag)); @@ -405,7 +374,6 @@ bool XSSAuditor::filterParamToken(HTMLToken& token) bool XSSAuditor::filterEmbedToken(HTMLToken& token) { - ASSERT(m_state == Initial); ASSERT(token.type() == HTMLTokenTypes::StartTag); ASSERT(hasName(token, embedTag)); @@ -420,7 +388,6 @@ bool XSSAuditor::filterEmbedToken(HTMLToken& token) bool XSSAuditor::filterAppletToken(HTMLToken& token) { - ASSERT(m_state == Initial); ASSERT(token.type() == HTMLTokenTypes::StartTag); ASSERT(hasName(token, appletTag)); @@ -434,7 +401,6 @@ bool XSSAuditor::filterAppletToken(HTMLToken& token) bool XSSAuditor::filterIframeToken(HTMLToken& token) { - ASSERT(m_state == Initial); ASSERT(token.type() == HTMLTokenTypes::StartTag); ASSERT(hasName(token, iframeTag)); @@ -443,7 +409,6 @@ bool XSSAuditor::filterIframeToken(HTMLToken& token) bool XSSAuditor::filterMetaToken(HTMLToken& token) { - ASSERT(m_state == Initial); ASSERT(token.type() == HTMLTokenTypes::StartTag); ASSERT(hasName(token, metaTag)); @@ -452,7 +417,6 @@ bool XSSAuditor::filterMetaToken(HTMLToken& token) bool XSSAuditor::filterBaseToken(HTMLToken& token) { - ASSERT(m_state == Initial); ASSERT(token.type() == HTMLTokenTypes::StartTag); ASSERT(hasName(token, baseTag)); @@ -461,7 +425,6 @@ bool XSSAuditor::filterBaseToken(HTMLToken& token) bool XSSAuditor::filterFormToken(HTMLToken& token) { - ASSERT(m_state == Initial); ASSERT(token.type() == HTMLTokenTypes::StartTag); ASSERT(hasName(token, formTag)); @@ -476,7 +439,7 @@ bool XSSAuditor::eraseDangerousAttributesIfInjected(HTMLToken& token) for (size_t i = 0; i < token.attributes().size(); ++i) { const HTMLToken::Attribute& attribute = token.attributes().at(i); bool isInlineEventHandler = isNameOfInlineEventHandler(attribute.m_name); - bool valueContainsJavaScriptURL = isInlineEventHandler ? false : containsJavaScriptURL(attribute.m_value); + bool valueContainsJavaScriptURL = !isInlineEventHandler && protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(String(attribute.m_value.data(), attribute.m_value.size()))); if (!isInlineEventHandler && !valueContainsJavaScriptURL) continue; // Beware of trailing characters which came from the page itself, not the @@ -540,8 +503,6 @@ String XSSAuditor::snippetForRange(const HTMLToken& token, int start, int end) String XSSAuditor::decodedSnippetForAttribute(const HTMLToken& token, const HTMLToken::Attribute& attribute, AttributeKind treatment) { - const size_t kMaximumSnippetLength = 100; - // The range doesn't inlcude the character which terminates the value. So, // for an input of |name="value"|, the snippet is |name="value|. For an // unquoted input of |name=value |, the snippet is |name=value|. @@ -549,7 +510,7 @@ String XSSAuditor::decodedSnippetForAttribute(const HTMLToken& token, const HTML int start = attribute.m_nameRange.m_start - token.startIndex(); int end = attribute.m_valueRange.m_end - token.startIndex(); String decodedSnippet = fullyDecodeString(snippetForRange(token, start, end), m_parser->document()->decoder()); - decodedSnippet.truncate(kMaximumSnippetLength); + decodedSnippet.truncate(kMaximumFragmentLengthTarget); if (treatment == SrcLikeAttribute) { int slashCount; size_t currentLength; @@ -592,8 +553,6 @@ bool XSSAuditor::isSameOriginResource(const String& url) String XSSAuditor::snippetForJavaScript(const String& string) { - const size_t kMaximumFragmentLengthTarget = 100; - size_t startPosition = 0; size_t endPosition = string.length(); size_t foundPosition = notFound; @@ -602,8 +561,17 @@ String XSSAuditor::snippetForJavaScript(const String& string) while (startPosition < endPosition) { while (startPosition < endPosition && isHTMLSpace(string[startPosition])) startPosition++; + + // Under SVG/XML rules, only HTML comment syntax matters and the parser returns + // these as a separate comment tokens. Having consumed whitespace, we need not look + // further for these. + if (m_shouldAllowCDATA) + break; + + // Under HTML rules, both the HTML and JS comment synatx matters, and the HTML + // comment ends at the end of the line, not with -->. if (startsHTMLCommentAt(string, startPosition) || startsSingleLineCommentAt(string, startPosition)) { - while (startPosition < endPosition && !isHTMLNewline(string[startPosition])) + while (startPosition < endPosition && !isJSNewline(string[startPosition])) startPosition++; } else if (startsMultiLineCommentAt(string, startPosition)) { if ((foundPosition = string.find("*/", startPosition)) != notFound) @@ -614,29 +582,29 @@ String XSSAuditor::snippetForJavaScript(const String& string) break; } - // Stop at next comment, or at a closing script tag (which may have been included with - // the code fragment because of buffering in the HTMLSourceTracker), or when we exceed - // the maximum length target. After hitting the length target, we can only stop at a - // point where we know we are not in the middle of a %-escape sequence. For the sake of - // simplicity, approximate stopping at a close script tag by stopping at any close tag, - // and approximate not stopping inside a (possibly multiply encoded) %-esacpe sequence - // by breaking on whitespace only. We should have enough text in these cases to avoid - // false positives. + // Stop at next comment (using the same rules as above for SVG/XML vs HTML), or when + // we exceed the maximum length target. After hitting the length target, we can only + // stop at a point where we know we are not in the middle of a %-escape sequence. For + // the sake of simplicity, approximate not stopping inside a (possibly multiply encoded) + // %-esacpe sequence by breaking on whitespace only. We should have enough text in + // these cases to avoid false positives. for (foundPosition = startPosition; foundPosition < endPosition; foundPosition++) { - if (startsSingleLineCommentAt(string, foundPosition) || startsMultiLineCommentAt(string, foundPosition) || startsHTMLEndTagAt(string, foundPosition)) { - endPosition = foundPosition + 2; - break; - } - if (startsHTMLCommentAt(string, foundPosition)) { - endPosition = foundPosition + 4; - break; + if (!m_shouldAllowCDATA) { + if (startsSingleLineCommentAt(string, foundPosition) || startsMultiLineCommentAt(string, foundPosition)) { + endPosition = foundPosition + 2; + break; + } + if (startsHTMLCommentAt(string, foundPosition)) { + endPosition = foundPosition + 4; + break; + } } if (foundPosition > startPosition + kMaximumFragmentLengthTarget && isHTMLSpace(string[foundPosition])) { endPosition = foundPosition; break; } } - + return string.substring(startPosition, endPosition - startPosition); } diff --git a/Source/WebCore/html/parser/XSSAuditor.h b/Source/WebCore/html/parser/XSSAuditor.h index 89b7b8c65..713cd0b6f 100644 --- a/Source/WebCore/html/parser/XSSAuditor.h +++ b/Source/WebCore/html/parser/XSSAuditor.h @@ -42,10 +42,11 @@ public: void filterToken(HTMLToken&); private: + static const size_t kMaximumFragmentLengthTarget = 100; + enum State { Uninitialized, - Initial, - AfterScriptStartTag, + Initialized }; enum AttributeKind { @@ -55,9 +56,9 @@ private: void init(); - bool filterTokenInitial(HTMLToken&); - bool filterTokenAfterScriptStartTag(HTMLToken&); - + bool filterStartToken(HTMLToken&); + void filterEndToken(HTMLToken&); + bool filterCharacterToken(HTMLToken&); bool filterScriptToken(HTMLToken&); bool filterObjectToken(HTMLToken&); bool filterParamToken(HTMLToken&); @@ -88,6 +89,8 @@ private: State m_state; String m_cachedSnippet; + bool m_shouldAllowCDATA; + unsigned m_scriptTagNestingLevel; bool m_notifiedClient; }; diff --git a/Source/WebCore/html/shadow/ContentInclusionSelector.h b/Source/WebCore/html/shadow/ContentInclusionSelector.h deleted file mode 100644 index 0f0b1978e..000000000 --- a/Source/WebCore/html/shadow/ContentInclusionSelector.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2011 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 ContentInclusionSelector_h -#define ContentInclusionSelector_h - -#include <wtf/Forward.h> -#include <wtf/HashSet.h> -#include <wtf/RefCounted.h> -#include <wtf/Vector.h> - -namespace WebCore { - -class Element; -class HTMLContentElement; -class Node; -class ShadowRoot; - -class ShadowInclusion : public RefCounted<ShadowInclusion> { -public: - static PassRefPtr<ShadowInclusion> create(HTMLContentElement*, Node*); - - HTMLContentElement* includer() const { return m_includer; } - Node* content() const { return m_content.get(); } - ShadowInclusion* next() const { return m_next.get(); } - ShadowInclusion* previous() const { return m_previous.get(); } - - void append(PassRefPtr<ShadowInclusion>); - void unlink(); - -private: - ShadowInclusion(HTMLContentElement*, Node*); - - HTMLContentElement* m_includer; - RefPtr<Node> m_content; - RefPtr<ShadowInclusion> m_next; - RefPtr<ShadowInclusion> m_previous; -}; - -inline ShadowInclusion::ShadowInclusion(HTMLContentElement* includer, Node* content) - : m_includer(includer), m_content(content) -{ } - -inline PassRefPtr<ShadowInclusion> ShadowInclusion::create(HTMLContentElement* includer, Node* content) -{ - return adoptRef(new ShadowInclusion(includer, content)); -} - -class ShadowInclusionList { -public: - ShadowInclusionList(); - ~ShadowInclusionList(); - - ShadowInclusion* first() const { return m_first.get(); } - ShadowInclusion* last() const { return m_last.get(); } - ShadowInclusion* find(Node*) const; - bool isEmpty() const { return !m_first; } - - void clear(); - void append(PassRefPtr<ShadowInclusion>); - -private: - RefPtr<ShadowInclusion> m_first; - RefPtr<ShadowInclusion> m_last; -}; - - -class ShadowInclusionSet { -public: - void add(ShadowInclusion* value) { m_set.add(value); } - void remove(ShadowInclusion* value) { m_set.remove(value); } - bool isEmpty() const { return m_set.isEmpty(); } - ShadowInclusion* find(Node* key) const; - -private: - struct Translator { - public: - static unsigned hash(const Node* key) { return PtrHash<const Node*>::hash(key); } - static bool equal(const ShadowInclusion* inclusion, const Node* content) { return inclusion->content() == content; } - }; - - struct Hash { - static unsigned hash(ShadowInclusion* key) { return PtrHash<const Node*>::hash(key->content()); } - static bool equal(ShadowInclusion* a, ShadowInclusion* b) { return a->content() == b->content(); } - static const bool safeToCompareToEmptyOrDeleted = false; - }; - - typedef HashSet<ShadowInclusion*, Hash> PointerSet; - - PointerSet m_set; -}; - -inline ShadowInclusion* ShadowInclusionSet::find(Node* key) const -{ - PointerSet::iterator found = m_set.find<Node*, ShadowInclusionSet::Translator>(key); - return found != m_set.end() ? *found : 0; -} - -class ContentInclusionSelector { - WTF_MAKE_NONCOPYABLE(ContentInclusionSelector); -public: - ContentInclusionSelector(); - ~ContentInclusionSelector(); - - void select(HTMLContentElement*, ShadowInclusionList*); - void unselect(ShadowInclusionList*); - ShadowInclusion* findFor(Node* key) const; - - void willSelectOver(ShadowRoot*); - void didSelect(); - bool hasCandidates() const { return !m_candidates.isEmpty(); } - -private: - void removeFromSet(ShadowInclusionList*); - void addToSet(ShadowInclusionList*); - - Vector<RefPtr<Node> > m_candidates; - ShadowInclusionSet m_inclusionSet; -}; - -} - -#endif diff --git a/Source/WebCore/html/shadow/HTMLContentElement.cpp b/Source/WebCore/html/shadow/HTMLContentElement.cpp index 961dd1d30..989acaee6 100644 --- a/Source/WebCore/html/shadow/HTMLContentElement.cpp +++ b/Source/WebCore/html/shadow/HTMLContentElement.cpp @@ -27,11 +27,12 @@ #include "config.h" #include "HTMLContentElement.h" -#include "ContentInclusionSelector.h" #include "ContentSelectorQuery.h" +#include "HTMLContentSelector.h" #include "HTMLNames.h" #include "QualifiedName.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include <wtf/StdLibExtras.h> namespace WebCore { @@ -59,8 +60,7 @@ PassRefPtr<HTMLContentElement> HTMLContentElement::create(const QualifiedName& t } HTMLContentElement::HTMLContentElement(const QualifiedName& name, Document* document) - : HTMLElement(name, document) - , m_inclusions(adoptPtr(new ShadowInclusionList())) + : InsertionPoint(name, document) { } @@ -74,32 +74,32 @@ void HTMLContentElement::attach() // Before calling StyledElement::attach, selector must be calculated. if (root) { - ContentInclusionSelector* selector = root->ensureInclusions(); - selector->unselect(m_inclusions.get()); - selector->select(this, m_inclusions.get()); + HTMLContentSelector* selector = root->list()->ensureSelector(); + selector->unselect(&m_selections); + selector->select(this, &m_selections); } - HTMLElement::attach(); + InsertionPoint::attach(); if (root) { - for (ShadowInclusion* inclusion = m_inclusions->first(); inclusion; inclusion = inclusion->next()) - inclusion->content()->attach(); + for (HTMLContentSelection* selection = m_selections.first(); selection; selection = selection->next()) + selection->node()->attach(); } } void HTMLContentElement::detach() { if (ShadowRoot* root = toShadowRoot(shadowTreeRootNode())) { - if (ContentInclusionSelector* selector = root->inclusions()) - selector->unselect(m_inclusions.get()); + if (HTMLContentSelector* selector = root->list()->selector()) + selector->unselect(&m_selections); - // When content element is detached, shadow tree should be recreated to re-calculate inclusions for + // When content element is detached, shadow tree should be recreated to re-calculate selector for // other content elements. - root->setNeedsReattachHostChildrenAndShadow(); + root->list()->setNeedsReattachHostChildrenAndShadow(); } - ASSERT(m_inclusions->isEmpty()); - HTMLElement::detach(); + ASSERT(m_selections.isEmpty()); + InsertionPoint::detach(); } const AtomicString& HTMLContentElement::select() const @@ -122,9 +122,9 @@ void HTMLContentElement::parseAttribute(Attribute* attr) { if (attr->name() == selectAttr) { if (ShadowRoot* root = toShadowRoot(shadowTreeRootNode())) - root->setNeedsReattachHostChildrenAndShadow(); + root->list()->setNeedsReattachHostChildrenAndShadow(); } else - HTMLElement::parseAttribute(attr); + InsertionPoint::parseAttribute(attr); } } diff --git a/Source/WebCore/html/shadow/HTMLContentElement.h b/Source/WebCore/html/shadow/HTMLContentElement.h index 6e1816c78..c2a1c1e36 100644 --- a/Source/WebCore/html/shadow/HTMLContentElement.h +++ b/Source/WebCore/html/shadow/HTMLContentElement.h @@ -31,18 +31,14 @@ #ifndef HTMLContentElement_h #define HTMLContentElement_h -#include "ContentInclusionSelector.h" -#include "HTMLElement.h" +#include "InsertionPoint.h" #include <wtf/Forward.h> namespace WebCore { -class ContentSelectorQuery; -class ShadowInclusionList; - // NOTE: Current implementation doesn't support dynamic insertion/deletion of HTMLContentElement. // You should create HTMLContentElement during the host construction. -class HTMLContentElement : public HTMLElement { +class HTMLContentElement : public InsertionPoint { public: static PassRefPtr<HTMLContentElement> create(const QualifiedName&, Document*); static PassRefPtr<HTMLContentElement> create(Document*); @@ -60,9 +56,6 @@ public: // See https://bugs.webkit.org/show_bug.cgi?id=76261 void setSelect(const AtomicString&); - const ShadowInclusionList* inclusions() const { return m_inclusions.get(); } - bool hasInclusion() const { return inclusions()->first(); } - virtual bool isSelectValid() const; protected: @@ -74,8 +67,6 @@ private: virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) { return 0; } virtual void parseAttribute(Attribute*) OVERRIDE; - - OwnPtr<ShadowInclusionList> m_inclusions; }; inline HTMLContentElement* toHTMLContentElement(Node* node) diff --git a/Source/WebCore/html/shadow/ContentInclusionSelector.cpp b/Source/WebCore/html/shadow/HTMLContentSelector.cpp index 6b541a5ae..5c30ff6e1 100644 --- a/Source/WebCore/html/shadow/ContentInclusionSelector.cpp +++ b/Source/WebCore/html/shadow/HTMLContentSelector.cpp @@ -25,7 +25,7 @@ */ #include "config.h" -#include "ContentInclusionSelector.h" +#include "HTMLContentSelector.h" #include "ContentSelectorQuery.h" #include "HTMLContentElement.h" @@ -34,7 +34,7 @@ namespace WebCore { -void ShadowInclusion::append(PassRefPtr<ShadowInclusion> next) +void HTMLContentSelection::append(PassRefPtr<HTMLContentSelection> next) { ASSERT(!m_next); ASSERT(!next->previous()); @@ -42,13 +42,13 @@ void ShadowInclusion::append(PassRefPtr<ShadowInclusion> next) m_next->m_previous = this; } -void ShadowInclusion::unlink() +void HTMLContentSelection::unlink() { ASSERT(!m_previous); // Can be called only for a head. - RefPtr<ShadowInclusion> item = this; + RefPtr<HTMLContentSelection> item = this; while (item) { ASSERT(!item->previous()); - RefPtr<ShadowInclusion> nextItem = item->m_next; + RefPtr<HTMLContentSelection> nextItem = item->m_next; item->m_next.clear(); if (nextItem) nextItem->m_previous.clear(); @@ -56,26 +56,26 @@ void ShadowInclusion::unlink() } } -ShadowInclusionList::ShadowInclusionList() +HTMLContentSelectionList::HTMLContentSelectionList() { } -ShadowInclusionList::~ShadowInclusionList() +HTMLContentSelectionList::~HTMLContentSelectionList() { ASSERT(isEmpty()); } -ShadowInclusion* ShadowInclusionList::find(Node* content) const +HTMLContentSelection* HTMLContentSelectionList::find(Node* node) const { - for (ShadowInclusion* item = first(); item; item = item->next()) { - if (content == item->content()) + for (HTMLContentSelection* item = first(); item; item = item->next()) { + if (node == item->node()) return item; } return 0; } -void ShadowInclusionList::clear() +void HTMLContentSelectionList::clear() { if (isEmpty()) { ASSERT(!m_last); @@ -87,7 +87,7 @@ void ShadowInclusionList::clear() m_last.clear(); } -void ShadowInclusionList::append(PassRefPtr<ShadowInclusion> child) +void HTMLContentSelectionList::append(PassRefPtr<HTMLContentSelection> child) { if (isEmpty()) { ASSERT(!m_last); @@ -99,18 +99,18 @@ void ShadowInclusionList::append(PassRefPtr<ShadowInclusion> child) m_last = m_last->next(); } -ContentInclusionSelector::ContentInclusionSelector() +HTMLContentSelector::HTMLContentSelector() { } -ContentInclusionSelector::~ContentInclusionSelector() +HTMLContentSelector::~HTMLContentSelector() { ASSERT(m_candidates.isEmpty()); } -void ContentInclusionSelector::select(HTMLContentElement* contentElement, ShadowInclusionList* inclusions) +void HTMLContentSelector::select(HTMLContentElement* contentElement, HTMLContentSelectionList* selections) { - ASSERT(inclusions->isEmpty()); + ASSERT(selections->isEmpty()); ContentSelectorQuery query(contentElement); for (size_t i = 0; i < m_candidates.size(); ++i) { @@ -120,35 +120,37 @@ void ContentInclusionSelector::select(HTMLContentElement* contentElement, Shadow if (!query.matches(child)) continue; - RefPtr<ShadowInclusion> inclusion = ShadowInclusion::create(contentElement, child); - inclusions->append(inclusion); - m_inclusionSet.add(inclusion.get()); + RefPtr<HTMLContentSelection> selection = HTMLContentSelection::create(contentElement, child); + + selections->append(selection); + m_selectionSet.add(selection.get()); m_candidates[i] = 0; } } -void ContentInclusionSelector::unselect(ShadowInclusionList* list) +void HTMLContentSelector::unselect(HTMLContentSelectionList* list) { - for (ShadowInclusion* inclusion = list->first(); inclusion; inclusion = inclusion->next()) - m_inclusionSet.remove(inclusion); + for (HTMLContentSelection* selection = list->first(); selection; selection = selection->next()) + m_selectionSet.remove(selection); list->clear(); } -ShadowInclusion* ContentInclusionSelector::findFor(Node* key) const +HTMLContentSelection* HTMLContentSelector::findFor(Node* key) const { - return m_inclusionSet.find(key); + return m_selectionSet.find(key); } -void ContentInclusionSelector::didSelect() +void HTMLContentSelector::didSelect() { m_candidates.clear(); } -void ContentInclusionSelector::willSelectOver(ShadowRoot* scope) +void HTMLContentSelector::willSelectOver(Element* shadowHost) { if (!m_candidates.isEmpty()) return; - for (Node* node = scope->shadowHost()->firstChild(); node; node = node->nextSibling()) + ASSERT(shadowHost); + for (Node* node = shadowHost->firstChild(); node; node = node->nextSibling()) m_candidates.append(node); } diff --git a/Source/WebCore/html/shadow/HTMLContentSelector.h b/Source/WebCore/html/shadow/HTMLContentSelector.h new file mode 100644 index 000000000..29bd6163f --- /dev/null +++ b/Source/WebCore/html/shadow/HTMLContentSelector.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2011 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 HTMLContentSelector_h +#define HTMLContentSelector_h + +#include <wtf/Forward.h> +#include <wtf/HashSet.h> +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class Element; +class HTMLContentElement; +class InsertionPoint; +class Node; +class ShadowRoot; + +class HTMLContentSelection : public RefCounted<HTMLContentSelection> { +public: + static PassRefPtr<HTMLContentSelection> create(InsertionPoint*, Node*); + + InsertionPoint* insertionPoint() const { return m_insertionPoint; } + Node* node() const { return m_node.get(); } + HTMLContentSelection* next() const { return m_next.get(); } + HTMLContentSelection* previous() const { return m_previous.get(); } + + void append(PassRefPtr<HTMLContentSelection>); + void unlink(); + +private: + HTMLContentSelection(InsertionPoint*, Node*); + + InsertionPoint* m_insertionPoint; + RefPtr<Node> m_node; + RefPtr<HTMLContentSelection> m_next; + RefPtr<HTMLContentSelection> m_previous; +}; + +inline HTMLContentSelection::HTMLContentSelection(InsertionPoint* insertionPoint, Node* node) + : m_insertionPoint(insertionPoint), m_node(node) +{ } + +inline PassRefPtr<HTMLContentSelection> HTMLContentSelection::create(InsertionPoint* insertionPoint, Node* node) +{ + return adoptRef(new HTMLContentSelection(insertionPoint, node)); +} + +class HTMLContentSelectionList { +public: + HTMLContentSelectionList(); + ~HTMLContentSelectionList(); + + HTMLContentSelection* first() const { return m_first.get(); } + HTMLContentSelection* last() const { return m_last.get(); } + HTMLContentSelection* find(Node*) const; + bool isEmpty() const { return !m_first; } + + void clear(); + void append(PassRefPtr<HTMLContentSelection>); + +private: + RefPtr<HTMLContentSelection> m_first; + RefPtr<HTMLContentSelection> m_last; +}; + + +class HTMLContentSelectionSet { +public: + void add(HTMLContentSelection* value) { m_set.add(value); } + void remove(HTMLContentSelection* value) { m_set.remove(value); } + bool isEmpty() const { return m_set.isEmpty(); } + HTMLContentSelection* find(Node* key) const; + +private: + struct Translator { + public: + static unsigned hash(const Node* key) { return PtrHash<const Node*>::hash(key); } + static bool equal(const HTMLContentSelection* selection, const Node* node) { return selection->node() == node; } + }; + + struct Hash { + static unsigned hash(HTMLContentSelection* key) { return PtrHash<const Node*>::hash(key->node()); } + static bool equal(HTMLContentSelection* a, HTMLContentSelection* b) { return a->node() == b->node(); } + static const bool safeToCompareToEmptyOrDeleted = false; + }; + + typedef HashSet<HTMLContentSelection*, Hash> PointerSet; + + PointerSet m_set; +}; + +inline HTMLContentSelection* HTMLContentSelectionSet::find(Node* key) const +{ + PointerSet::iterator found = m_set.find<Node*, HTMLContentSelectionSet::Translator>(key); + return found != m_set.end() ? *found : 0; +} + +class HTMLContentSelector { + WTF_MAKE_NONCOPYABLE(HTMLContentSelector); +public: + HTMLContentSelector(); + ~HTMLContentSelector(); + + void select(HTMLContentElement*, HTMLContentSelectionList*); + void unselect(HTMLContentSelectionList*); + HTMLContentSelection* findFor(Node* key) const; + + void willSelectOver(Element* shadowHost); + void didSelect(); + bool hasCandidates() const { return !m_candidates.isEmpty(); } + +private: + void removeFromSet(HTMLContentSelectionList*); + void addToSet(HTMLContentSelectionList*); + + Vector<RefPtr<Node> > m_candidates; + HTMLContentSelectionSet m_selectionSet; +}; + +} + +#endif diff --git a/Source/WebCore/html/shadow/HTMLShadowElement.h b/Source/WebCore/html/shadow/HTMLShadowElement.h index bfc85e2fb..151c7a2ab 100644 --- a/Source/WebCore/html/shadow/HTMLShadowElement.h +++ b/Source/WebCore/html/shadow/HTMLShadowElement.h @@ -45,6 +45,7 @@ public: private: HTMLShadowElement(const QualifiedName&, Document*); + virtual bool isShadowElement() const { return true; } }; } // namespace WebCore diff --git a/Source/WebCore/html/shadow/HTMLShadowElement.idl b/Source/WebCore/html/shadow/HTMLShadowElement.idl index 1310a1482..94facb7be 100644 --- a/Source/WebCore/html/shadow/HTMLShadowElement.idl +++ b/Source/WebCore/html/shadow/HTMLShadowElement.idl @@ -32,7 +32,7 @@ module html { interface [ Conditional=SHADOW_DOM, - EnabledAtRuntime=shadowDOM + V8EnabledAtRuntime=shadowDOM ] HTMLShadowElement : HTMLElement { }; diff --git a/Source/WebCore/html/shadow/InsertionPoint.cpp b/Source/WebCore/html/shadow/InsertionPoint.cpp new file mode 100644 index 000000000..e99dc26d2 --- /dev/null +++ b/Source/WebCore/html/shadow/InsertionPoint.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 "InsertionPoint.h" + +namespace WebCore { + +InsertionPoint::InsertionPoint(const QualifiedName& tagName, Document* document) + : HTMLElement(tagName, document) + , m_selections() +{ +} + +InsertionPoint::~InsertionPoint() +{ +} + +} // namespace WebCore diff --git a/Source/WebCore/html/shadow/InsertionPoint.h b/Source/WebCore/html/shadow/InsertionPoint.h new file mode 100644 index 000000000..292439032 --- /dev/null +++ b/Source/WebCore/html/shadow/InsertionPoint.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2012 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 InsertionPoint_h +#define InsertionPoint_h + +#include "HTMLContentSelector.h" +#include "HTMLElement.h" + +namespace WebCore { + +class InsertionPoint : public HTMLElement { +public: + virtual ~InsertionPoint(); + + const HTMLContentSelectionList* selections() const { return &m_selections; } + bool hasSelection() const { return m_selections.first(); } + +protected: + InsertionPoint(const QualifiedName&, Document*); + HTMLContentSelectionList m_selections; +}; + +inline bool isInsertionPoint(Node* node) +{ + // FIXME: <shadow> should also be InsertionPoint. + // https://bugs.webkit.org/show_bug.cgi?id=78596 + if (!node || node->isContentElement()) + return true; + + return false; +} + +inline InsertionPoint* toInsertionPoint(Node* node) +{ + ASSERT(isInsertionPoint(node)); + return static_cast<InsertionPoint*>(node); +} + +} // namespace WebCore + +#endif // InsertionPoint_h diff --git a/Source/WebCore/html/shadow/MediaControlElements.cpp b/Source/WebCore/html/shadow/MediaControlElements.cpp index e932e73d3..1f69e3cc6 100644 --- a/Source/WebCore/html/shadow/MediaControlElements.cpp +++ b/Source/WebCore/html/shadow/MediaControlElements.cpp @@ -92,12 +92,12 @@ MediaControlElement::MediaControlElement(Document* document) void MediaControlElement::show() { - ensureInlineStyleDecl()->removeProperty(CSSPropertyDisplay); + removeInlineStyleProperty(CSSPropertyDisplay); } void MediaControlElement::hide() { - ensureInlineStyleDecl()->setProperty(CSSPropertyDisplay, CSSValueNone); + setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); } // ---------------------------- @@ -175,17 +175,15 @@ void MediaControlPanelElement::endDrag() void MediaControlPanelElement::setPosition(const LayoutPoint& position) { - StylePropertySet* style = ensureInlineStyleDecl(); - double left = position.x(); double top = position.y(); // Set the left and top to control the panel's position; this depends on it being absolute positioned. // Set the margin to zero since the position passed in will already include the effect of the margin. - style->setProperty(CSSPropertyLeft, left, CSSPrimitiveValue::CSS_PX); - style->setProperty(CSSPropertyTop, top, CSSPrimitiveValue::CSS_PX); - style->setProperty(CSSPropertyMarginLeft, 0.0, CSSPrimitiveValue::CSS_PX); - style->setProperty(CSSPropertyMarginTop, 0.0, CSSPrimitiveValue::CSS_PX); + setInlineStyleProperty(CSSPropertyLeft, left, CSSPrimitiveValue::CSS_PX); + setInlineStyleProperty(CSSPropertyTop, top, CSSPrimitiveValue::CSS_PX); + setInlineStyleProperty(CSSPropertyMarginLeft, 0.0, CSSPrimitiveValue::CSS_PX); + setInlineStyleProperty(CSSPropertyMarginTop, 0.0, CSSPrimitiveValue::CSS_PX); ExceptionCode ignored; classList()->add("dragged", ignored); @@ -193,12 +191,10 @@ void MediaControlPanelElement::setPosition(const LayoutPoint& position) void MediaControlPanelElement::resetPosition() { - StylePropertySet* style = ensureInlineStyleDecl(); - - style->removeProperty(CSSPropertyLeft); - style->removeProperty(CSSPropertyTop); - style->removeProperty(CSSPropertyMarginLeft); - style->removeProperty(CSSPropertyMarginTop); + removeInlineStyleProperty(CSSPropertyLeft); + removeInlineStyleProperty(CSSPropertyTop); + removeInlineStyleProperty(CSSPropertyMarginLeft); + removeInlineStyleProperty(CSSPropertyMarginTop); ExceptionCode ignored; classList()->remove("dragged", ignored); @@ -211,10 +207,9 @@ void MediaControlPanelElement::makeOpaque() double duration = document()->page() ? document()->page()->theme()->mediaControlsFadeInDuration() : 0; - StylePropertySet* style = ensureInlineStyleDecl(); - style->setProperty(CSSPropertyWebkitTransitionProperty, CSSPropertyOpacity); - style->setProperty(CSSPropertyWebkitTransitionDuration, duration, CSSPrimitiveValue::CSS_S); - style->setProperty(CSSPropertyOpacity, 1.0, CSSPrimitiveValue::CSS_NUMBER); + setInlineStyleProperty(CSSPropertyWebkitTransitionProperty, CSSPropertyOpacity); + setInlineStyleProperty(CSSPropertyWebkitTransitionDuration, duration, CSSPrimitiveValue::CSS_S); + setInlineStyleProperty(CSSPropertyOpacity, 1.0, CSSPrimitiveValue::CSS_NUMBER); m_opaque = true; } @@ -224,10 +219,9 @@ void MediaControlPanelElement::makeTransparent() if (!m_opaque) return; - StylePropertySet* style = ensureInlineStyleDecl(); - style->setProperty(CSSPropertyWebkitTransitionProperty, CSSPropertyOpacity); - style->setProperty(CSSPropertyWebkitTransitionDuration, document()->page()->theme()->mediaControlsFadeOutDuration(), CSSPrimitiveValue::CSS_S); - style->setProperty(CSSPropertyOpacity, 0.0, CSSPrimitiveValue::CSS_NUMBER); + setInlineStyleProperty(CSSPropertyWebkitTransitionProperty, CSSPropertyOpacity); + setInlineStyleProperty(CSSPropertyWebkitTransitionDuration, document()->page()->theme()->mediaControlsFadeOutDuration(), CSSPrimitiveValue::CSS_S); + setInlineStyleProperty(CSSPropertyOpacity, 0.0, CSSPrimitiveValue::CSS_NUMBER); m_opaque = false; } @@ -434,12 +428,12 @@ MediaControlInputElement::MediaControlInputElement(Document* document, MediaCont void MediaControlInputElement::show() { - ensureInlineStyleDecl()->removeProperty(CSSPropertyDisplay); + removeInlineStyleProperty(CSSPropertyDisplay); } void MediaControlInputElement::hide() { - ensureInlineStyleDecl()->setProperty(CSSPropertyDisplay, CSSValueNone); + setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); } @@ -493,6 +487,7 @@ PassRefPtr<MediaControlPanelMuteButtonElement> MediaControlPanelMuteButtonElemen ASSERT(controls); RefPtr<MediaControlPanelMuteButtonElement> button = adoptRef(new MediaControlPanelMuteButtonElement(document, controls)); + button->createShadowSubtree(); button->setType("button"); return button.release(); } @@ -521,6 +516,7 @@ inline MediaControlVolumeSliderMuteButtonElement::MediaControlVolumeSliderMuteBu PassRefPtr<MediaControlVolumeSliderMuteButtonElement> MediaControlVolumeSliderMuteButtonElement::create(Document* document) { RefPtr<MediaControlVolumeSliderMuteButtonElement> button = adoptRef(new MediaControlVolumeSliderMuteButtonElement(document)); + button->createShadowSubtree(); button->setType("button"); return button.release(); } @@ -541,6 +537,7 @@ inline MediaControlPlayButtonElement::MediaControlPlayButtonElement(Document* do PassRefPtr<MediaControlPlayButtonElement> MediaControlPlayButtonElement::create(Document* document) { RefPtr<MediaControlPlayButtonElement> button = adoptRef(new MediaControlPlayButtonElement(document)); + button->createShadowSubtree(); button->setType("button"); return button.release(); } @@ -660,6 +657,7 @@ inline MediaControlSeekForwardButtonElement::MediaControlSeekForwardButtonElemen PassRefPtr<MediaControlSeekForwardButtonElement> MediaControlSeekForwardButtonElement::create(Document* document) { RefPtr<MediaControlSeekForwardButtonElement> button = adoptRef(new MediaControlSeekForwardButtonElement(document)); + button->createShadowSubtree(); button->setType("button"); return button.release(); } @@ -680,6 +678,7 @@ inline MediaControlSeekBackButtonElement::MediaControlSeekBackButtonElement(Docu PassRefPtr<MediaControlSeekBackButtonElement> MediaControlSeekBackButtonElement::create(Document* document) { RefPtr<MediaControlSeekBackButtonElement> button = adoptRef(new MediaControlSeekBackButtonElement(document)); + button->createShadowSubtree(); button->setType("button"); return button.release(); } @@ -700,6 +699,7 @@ inline MediaControlRewindButtonElement::MediaControlRewindButtonElement(Document PassRefPtr<MediaControlRewindButtonElement> MediaControlRewindButtonElement::create(Document* document) { RefPtr<MediaControlRewindButtonElement> button = adoptRef(new MediaControlRewindButtonElement(document)); + button->createShadowSubtree(); button->setType("button"); return button.release(); } @@ -730,6 +730,7 @@ inline MediaControlReturnToRealtimeButtonElement::MediaControlReturnToRealtimeBu PassRefPtr<MediaControlReturnToRealtimeButtonElement> MediaControlReturnToRealtimeButtonElement::create(Document* document) { RefPtr<MediaControlReturnToRealtimeButtonElement> button = adoptRef(new MediaControlReturnToRealtimeButtonElement(document)); + button->createShadowSubtree(); button->setType("button"); button->hide(); return button.release(); @@ -760,6 +761,7 @@ inline MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCa PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClosedCaptionsButtonElement::create(Document* document) { RefPtr<MediaControlToggleClosedCaptionsButtonElement> button = adoptRef(new MediaControlToggleClosedCaptionsButtonElement(document)); + button->createShadowSubtree(); button->setType("button"); button->hide(); return button.release(); @@ -801,6 +803,7 @@ PassRefPtr<MediaControlTimelineElement> MediaControlTimelineElement::create(Docu ASSERT(controls); RefPtr<MediaControlTimelineElement> timeline = adoptRef(new MediaControlTimelineElement(document, controls)); + timeline->createShadowSubtree(); timeline->setType("range"); timeline->setAttribute(precisionAttr, "float"); return timeline.release(); @@ -865,6 +868,7 @@ inline MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(Document PassRefPtr<MediaControlVolumeSliderElement> MediaControlVolumeSliderElement::create(Document* document) { RefPtr<MediaControlVolumeSliderElement> slider = adoptRef(new MediaControlVolumeSliderElement(document)); + slider->createShadowSubtree(); slider->setType("range"); slider->setAttribute(precisionAttr, "float"); slider->setAttribute(maxAttr, "1"); @@ -915,6 +919,7 @@ inline MediaControlFullscreenVolumeSliderElement::MediaControlFullscreenVolumeSl PassRefPtr<MediaControlFullscreenVolumeSliderElement> MediaControlFullscreenVolumeSliderElement::create(Document* document) { RefPtr<MediaControlFullscreenVolumeSliderElement> slider = adoptRef(new MediaControlFullscreenVolumeSliderElement(document)); + slider->createShadowSubtree(); slider->setType("range"); slider->setAttribute(precisionAttr, "float"); slider->setAttribute(maxAttr, "1"); @@ -940,6 +945,7 @@ PassRefPtr<MediaControlFullscreenButtonElement> MediaControlFullscreenButtonElem ASSERT(controls); RefPtr<MediaControlFullscreenButtonElement> button = adoptRef(new MediaControlFullscreenButtonElement(document, controls)); + button->createShadowSubtree(); button->setType("button"); button->hide(); return button.release(); @@ -983,6 +989,7 @@ inline MediaControlFullscreenVolumeMinButtonElement::MediaControlFullscreenVolum PassRefPtr<MediaControlFullscreenVolumeMinButtonElement> MediaControlFullscreenVolumeMinButtonElement::create(Document* document) { RefPtr<MediaControlFullscreenVolumeMinButtonElement> button = adoptRef(new MediaControlFullscreenVolumeMinButtonElement(document)); + button->createShadowSubtree(); button->setType("button"); return button.release(); } @@ -1013,6 +1020,7 @@ inline MediaControlFullscreenVolumeMaxButtonElement::MediaControlFullscreenVolum PassRefPtr<MediaControlFullscreenVolumeMaxButtonElement> MediaControlFullscreenVolumeMaxButtonElement::create(Document* document) { RefPtr<MediaControlFullscreenVolumeMaxButtonElement> button = adoptRef(new MediaControlFullscreenVolumeMaxButtonElement(document)); + button->createShadowSubtree(); button->setType("button"); return button.release(); } @@ -1197,13 +1205,13 @@ void MediaControlTextTrackContainerElement::updateSizes() float fontSize = m_videoDisplaySize.size().height() * videoHeightFontSizePercentage; if (fontSize != m_fontSize) { m_fontSize = fontSize; - ensureInlineStyleDecl()->setProperty(CSSPropertyFontSize, String::number(fontSize) + "px"); + setInlineStyleProperty(CSSPropertyFontSize, String::number(fontSize) + "px"); } LayoutUnit bottom = static_cast<LayoutUnit>(m_videoDisplaySize.y() + m_videoDisplaySize.height() - (m_videoDisplaySize.height() * trackBottomMultiplier)); if (bottom != m_bottom) { m_bottom = bottom; - ensureInlineStyleDecl()->setProperty(CSSPropertyBottom, String::number(bottom) + "px"); + setInlineStyleProperty(CSSPropertyBottom, String::number(bottom) + "px"); } } diff --git a/Source/WebCore/html/shadow/MeterShadowElement.cpp b/Source/WebCore/html/shadow/MeterShadowElement.cpp index 410535414..bc5ea6295 100644 --- a/Source/WebCore/html/shadow/MeterShadowElement.cpp +++ b/Source/WebCore/html/shadow/MeterShadowElement.cpp @@ -93,7 +93,7 @@ const AtomicString& MeterValueElement::shadowPseudoId() const void MeterValueElement::setWidthPercentage(double width) { - ensureInlineStyleDecl()->setProperty(CSSPropertyWidth, width, CSSPrimitiveValue::CSS_PERCENTAGE); + setInlineStyleProperty(CSSPropertyWidth, width, CSSPrimitiveValue::CSS_PERCENTAGE); } diff --git a/Source/WebCore/html/shadow/ProgressShadowElement.cpp b/Source/WebCore/html/shadow/ProgressShadowElement.cpp index ecd35544f..548571302 100644 --- a/Source/WebCore/html/shadow/ProgressShadowElement.cpp +++ b/Source/WebCore/html/shadow/ProgressShadowElement.cpp @@ -73,7 +73,7 @@ const AtomicString& ProgressValueElement::shadowPseudoId() const void ProgressValueElement::setWidthPercentage(double width) { - ensureInlineStyleDecl()->setProperty(CSSPropertyWidth, width, CSSPrimitiveValue::CSS_PERCENTAGE); + setInlineStyleProperty(CSSPropertyWidth, width, CSSPrimitiveValue::CSS_PERCENTAGE); } } diff --git a/Source/WebCore/html/shadow/SliderThumbElement.cpp b/Source/WebCore/html/shadow/SliderThumbElement.cpp index 319a11e80..7558924ce 100644 --- a/Source/WebCore/html/shadow/SliderThumbElement.cpp +++ b/Source/WebCore/html/shadow/SliderThumbElement.cpp @@ -43,6 +43,7 @@ #include "RenderSlider.h" #include "RenderTheme.h" #include "ShadowRoot.h" +#include "ShadowRootList.h" #include "StepRange.h" #include <wtf/MathExtras.h> @@ -66,7 +67,7 @@ inline static bool hasVerticalAppearance(HTMLInputElement* input) SliderThumbElement* sliderThumbElementOf(Node* node) { ASSERT(node); - ShadowRoot* shadow = node->toInputElement()->shadowRoot(); + ShadowRoot* shadow = node->toInputElement()->shadowRootList()->oldestShadowRoot(); ASSERT(shadow); Node* thumb = shadow->firstChild()->firstChild()->firstChild(); ASSERT(thumb); @@ -141,7 +142,7 @@ void RenderSliderContainer::layout() Length inputHeight = input->renderer()->style()->height(); RenderObject* trackRenderer = node()->firstChild()->renderer(); if (!isVertical && input->renderer()->isSlider() && !inputHeight.isFixed() && !inputHeight.isPercent()) { - RenderObject* thumbRenderer = input->shadowRoot()->firstChild()->firstChild()->firstChild()->renderer(); + RenderObject* thumbRenderer = input->shadowRootList()->oldestShadowRoot()->firstChild()->firstChild()->firstChild()->renderer(); if (thumbRenderer) { style()->setHeight(thumbRenderer->style()->height()); if (trackRenderer) @@ -334,9 +335,8 @@ PassRefPtr<TrackLimiterElement> TrackLimiterElement::create(Document* document) { RefPtr<TrackLimiterElement> element = adoptRef(new TrackLimiterElement(document)); - StylePropertySet* style = element->ensureInlineStyleDecl(); - style->setProperty(CSSPropertyVisibility, CSSValueHidden); - style->setProperty(CSSPropertyPosition, CSSValueStatic); + element->setInlineStyleProperty(CSSPropertyVisibility, CSSValueHidden); + element->setInlineStyleProperty(CSSPropertyPosition, CSSValueStatic); return element.release(); } @@ -355,7 +355,8 @@ const AtomicString& TrackLimiterElement::shadowPseudoId() const TrackLimiterElement* trackLimiterElementOf(Node* node) { ASSERT(node); - ShadowRoot* shadow = node->toInputElement()->shadowRoot(); + ASSERT(node->toInputElement()->hasShadowRoot()); + ShadowRoot* shadow = node->toInputElement()->shadowRootList()->oldestShadowRoot(); ASSERT(shadow); Node* limiter = shadow->firstChild()->lastChild(); ASSERT(limiter); diff --git a/Source/WebCore/html/shadow/TextControlInnerElements.cpp b/Source/WebCore/html/shadow/TextControlInnerElements.cpp index 808ffa31e..2fc35f20e 100644 --- a/Source/WebCore/html/shadow/TextControlInnerElements.cpp +++ b/Source/WebCore/html/shadow/TextControlInnerElements.cpp @@ -474,7 +474,7 @@ void InputFieldSpeechButtonElement::setState(SpeechInputState state) SpeechInput* InputFieldSpeechButtonElement::speechInput() { - return document()->page() ? document()->page()->speechInput() : 0; + return SpeechInput::from(document()->page()); } void InputFieldSpeechButtonElement::didCompleteRecording(int) @@ -520,7 +520,8 @@ void InputFieldSpeechButtonElement::setRecognitionResult(int, const SpeechInputR void InputFieldSpeechButtonElement::attach() { ASSERT(!m_listenerId); - m_listenerId = document()->page()->speechInput()->registerListener(this); + if (SpeechInput* input = SpeechInput::from(document()->page())) + m_listenerId = input->registerListener(this); HTMLDivElement::attach(); } @@ -550,7 +551,7 @@ void InputFieldSpeechButtonElement::startSpeechInput() AtomicString language = input->computeInheritedLanguage(); String grammar = input->getAttribute(webkitgrammarAttr); // FIXME: this should probably respect transforms - IntRect rect = renderer()->view()->frameView()->contentsToWindow(renderer()->absoluteBoundingBoxRectIgnoringTransforms()); + IntRect rect = pixelSnappedIntRect(renderer()->view()->frameView()->contentsToWindow(renderer()->absoluteBoundingBoxRectIgnoringTransforms())); if (speechInput()->startRecognition(m_listenerId, rect, language, grammar, document()->securityOrigin())) setState(Recording); } diff --git a/Source/WebCore/html/LoadableTextTrack.cpp b/Source/WebCore/html/track/LoadableTextTrack.cpp index b48d8c7cb..400b42c2c 100644 --- a/Source/WebCore/html/LoadableTextTrack.cpp +++ b/Source/WebCore/html/track/LoadableTextTrack.cpp @@ -125,9 +125,10 @@ void LoadableTextTrack::cueLoadingCompleted(TextTrackLoader* loader, bool loadin void LoadableTextTrack::fireCueChangeEvent() { - TextTrack::fireCueChangeEvent(); + RefPtr<Event> event = Event::create(eventNames().cuechangeEvent, false, false); ExceptionCode ec = 0; - m_trackElement->dispatchEvent(Event::create(eventNames().cuechangeEvent, false, false), ec); + + m_trackElement->dispatchEvent(event, ec); } size_t LoadableTextTrack::trackElementIndex() diff --git a/Source/WebCore/html/LoadableTextTrack.h b/Source/WebCore/html/track/LoadableTextTrack.h index b70122536..783cdfa7f 100644 --- a/Source/WebCore/html/LoadableTextTrack.h +++ b/Source/WebCore/html/track/LoadableTextTrack.h @@ -57,10 +57,12 @@ public: void scheduleLoad(const KURL&); virtual void clearClient(); - + size_t trackElementIndex(); HTMLTrackElement* trackElement() { return m_trackElement; } + virtual void fireCueChangeEvent(); + private: // TextTrackLoaderClient virtual bool shouldLoadCues(TextTrackLoader*) { return true; } @@ -71,8 +73,6 @@ private: LoadableTextTrack(HTMLTrackElement*, const String& kind, const String& label, const String& language, bool isDefault); void loadTimerFired(Timer<LoadableTextTrack>*); - - virtual void fireCueChangeEvent(); HTMLTrackElement* m_trackElement; Timer<LoadableTextTrack> m_loadTimer; diff --git a/Source/WebCore/html/TextTrack.cpp b/Source/WebCore/html/track/TextTrack.cpp index bdfbaa205..175171fd3 100644 --- a/Source/WebCore/html/TextTrack.cpp +++ b/Source/WebCore/html/track/TextTrack.cpp @@ -37,11 +37,15 @@ #include "Event.h" #include "ExceptionCode.h" +#include "HTMLMediaElement.h" #include "TextTrackCueList.h" +#include "TextTrackList.h" #include "TrackBase.h" namespace WebCore { +static const int invalidTrackIndex = -1; + const AtomicString& TextTrack::subtitlesKeyword() { DEFINE_STATIC_LOCAL(const AtomicString, subtitles, ("subtitles")); @@ -82,6 +86,7 @@ TextTrack::TextTrack(ScriptExecutionContext* context, TextTrackClient* client, c , m_trackType(type) , m_readinessState(NotLoaded) , m_showingByDefault(false) + , m_trackIndex(invalidTrackIndex) { setKind(kind); } @@ -155,16 +160,13 @@ TextTrack::Mode TextTrack::mode() const TextTrackCueList* TextTrack::cues() { - if (!m_cues) - m_cues = TextTrackCueList::create(); - // 4.8.10.12.5 If the text track mode ... is not the text track disabled mode, // then the cues attribute must return a live TextTrackCueList object ... // Otherwise, it must return null. When an object is returned, the // same object must be returned each time. // http://www.whatwg.org/specs/web-apps/current-work/#dom-texttrack-cues - if (m_cues && m_mode != TextTrack::DISABLED) - return m_cues.get(); + if (m_mode != TextTrack::DISABLED) + return ensureTextTrackCueList(); return 0; } @@ -208,7 +210,7 @@ void TextTrack::addCue(PassRefPtr<TextTrackCue> prpCue, ExceptionCode& ec) // 3. If the given cue is already listed in the method's TextTrack object's text // track's text track list of cues, then throw an InvalidStateError exception. // 4. Add cue to the method's TextTrack object's text track's text track list of cues. - if (!m_cues->add(cue)) { + if (!ensureTextTrackCueList()->add(cue)) { ec = INVALID_STATE_ERR; return; } @@ -236,7 +238,7 @@ void TextTrack::removeCue(TextTrackCue* cue, ExceptionCode& ec) // 2. If the given cue is not currently listed in the method's TextTrack // object's text track's text track list of cues, then throw a NotFoundError exception. // 3. Remove cue from the method's TextTrack object's text track's text track list of cues. - if (!m_cues->remove(cue)) { + if (!m_cues || !m_cues->remove(cue)) { ec = INVALID_STATE_ERR; return; } @@ -246,12 +248,6 @@ void TextTrack::removeCue(TextTrackCue* cue, ExceptionCode& ec) m_client->textTrackRemoveCue(this, cue); } -void TextTrack::fireCueChangeEvent() -{ - ExceptionCode ec = 0; - dispatchEvent(Event::create(eventNames().cuechangeEvent, false, false), ec); -} - void TextTrack::cueWillChange(TextTrackCue* cue) { if (!m_client) @@ -271,6 +267,29 @@ void TextTrack::cueDidChange(TextTrackCue* cue) m_client->textTrackAddCue(this, cue); } +int TextTrack::trackIndex() +{ + ASSERT(m_mediaElement); + + if (m_trackIndex == invalidTrackIndex) + m_trackIndex = m_mediaElement->textTracks()->getTrackIndex(this); + + return m_trackIndex; +} + +void TextTrack::invalidateTrackIndex() +{ + m_trackIndex = invalidTrackIndex; +} + +TextTrackCueList* TextTrack::ensureTextTrackCueList() +{ + if (!m_cues) + m_cues = TextTrackCueList::create(); + + return m_cues.get(); +} + } // namespace WebCore #endif diff --git a/Source/WebCore/html/TextTrack.h b/Source/WebCore/html/track/TextTrack.h index f6ecec848..9a8eb8bb4 100644 --- a/Source/WebCore/html/TextTrack.h +++ b/Source/WebCore/html/track/TextTrack.h @@ -59,7 +59,7 @@ public: return adoptRef(new TextTrack(context, client, kind, label, language, AddTrack)); } virtual ~TextTrack(); - + void setMediaElement(HTMLMediaElement* element) { m_mediaElement = element; } HTMLMediaElement* mediaElement() { return m_mediaElement; } @@ -99,21 +99,26 @@ public: void addCue(PassRefPtr<TextTrackCue>, ExceptionCode&); void removeCue(TextTrackCue*, ExceptionCode&); + virtual void fireCueChangeEvent() { }; + void cueWillChange(TextTrackCue*); void cueDidChange(TextTrackCue*); - - virtual void fireCueChangeEvent(); + DEFINE_ATTRIBUTE_EVENT_LISTENER(cuechange); enum TextTrackType { TrackElement, AddTrack, InBand }; TextTrackType trackType() const { return m_trackType; } + int trackIndex(); + void invalidateTrackIndex(); + protected: TextTrack(ScriptExecutionContext*, TextTrackClient*, const String& kind, const String& label, const String& language, TextTrackType); RefPtr<TextTrackCueList> m_cues; private: + TextTrackCueList* ensureTextTrackCueList(); HTMLMediaElement* m_mediaElement; String m_kind; String m_label; @@ -123,6 +128,7 @@ private: TextTrackType m_trackType; ReadinessState m_readinessState; bool m_showingByDefault; + int m_trackIndex; }; } // namespace WebCore diff --git a/Source/WebCore/html/TextTrack.idl b/Source/WebCore/html/track/TextTrack.idl index 845a80c01..845a80c01 100644 --- a/Source/WebCore/html/TextTrack.idl +++ b/Source/WebCore/html/track/TextTrack.idl diff --git a/Source/WebCore/html/TextTrackCue.cpp b/Source/WebCore/html/track/TextTrackCue.cpp index e1c01266e..59c3f3ea0 100644 --- a/Source/WebCore/html/TextTrackCue.cpp +++ b/Source/WebCore/html/track/TextTrackCue.cpp @@ -38,11 +38,14 @@ #include "Event.h" #include "DocumentFragment.h" #include "TextTrack.h" +#include "TextTrackCueList.h" #include "WebVTTParser.h" #include <wtf/text/StringBuilder.h> namespace WebCore { +static const int invalidCueIndex = -1; + static const AtomicString& startKeyword() { DEFINE_STATIC_LOCAL(const AtomicString, start, ("start")); @@ -87,6 +90,7 @@ TextTrackCue::TextTrackCue(ScriptExecutionContext* context, const String& id, do , m_linePosition(-1) , m_textPosition(50) , m_cueSize(100) + , m_cueIndex(invalidCueIndex) , m_cueAlignment(Middle) , m_scriptExecutionContext(context) , m_isActive(false) @@ -324,6 +328,19 @@ void TextTrackCue::setText(const String& text) cueDidChange(); } +int TextTrackCue::cueIndex() +{ + if (m_cueIndex == invalidCueIndex) + m_cueIndex = track()->cues()->getCueIndex(this); + + return m_cueIndex; +} + +void TextTrackCue::invalidateCueIndex() +{ + m_cueIndex = invalidCueIndex; +} + PassRefPtr<DocumentFragment> TextTrackCue::getCueAsHTML() { if (!m_documentFragment) @@ -337,6 +354,20 @@ void TextTrackCue::setCueHTML(PassRefPtr<DocumentFragment> fragment) m_documentFragment = fragment; } +bool TextTrackCue::dispatchEvent(PassRefPtr<Event> event) +{ + // When a TextTrack's mode is disabled: no cues are active, no events fired. + if (!track() || track()->mode() == TextTrack::DISABLED) + return false; + + return EventTarget::dispatchEvent(event); +} + +bool TextTrackCue::dispatchEvent(PassRefPtr<Event> event, ExceptionCode &ec) +{ + return EventTarget::dispatchEvent(event, ec); +} + bool TextTrackCue::isActive() { return m_isActive && track() && track()->mode() != TextTrack::DISABLED; @@ -345,19 +376,6 @@ bool TextTrackCue::isActive() void TextTrackCue::setIsActive(bool active) { m_isActive = active; - - // When a TextTrack's mode is disabled: No cues are active, no events are fired ... - if (!track() || track()->mode() == TextTrack::DISABLED) - return; - - ExceptionCode ec = 0; - if (active) - dispatchEvent(Event::create(eventNames().enterEvent, false, false), ec); - else - dispatchEvent(Event::create(eventNames().exitEvent, false, false), ec); - - if (m_track) - m_track->fireCueChangeEvent(); } void TextTrackCue::parseSettings(const String& input) diff --git a/Source/WebCore/html/TextTrackCue.h b/Source/WebCore/html/track/TextTrackCue.h index 16faf63ca..b3e0f32a5 100644 --- a/Source/WebCore/html/TextTrackCue.h +++ b/Source/WebCore/html/track/TextTrackCue.h @@ -50,7 +50,7 @@ public: { return adoptRef(new TextTrackCue(context, id, start, end, content, settings, pauseOnExit)); } - + enum Direction { Horizontal, VerticalGrowingLeft, VerticalGrowingRight }; enum Alignment { Start, Middle, End }; @@ -92,12 +92,18 @@ public: const String& text() const { return m_content; } void setText(const String&); + int cueIndex(); + void invalidateCueIndex(); + PassRefPtr<DocumentFragment> getCueAsHTML(); void setCueHTML(PassRefPtr<DocumentFragment>); + virtual bool dispatchEvent(PassRefPtr<Event>); + bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); + bool isActive(); void setIsActive(bool); - + virtual const AtomicString& interfaceName() const; virtual ScriptExecutionContext* scriptExecutionContext() const; @@ -118,10 +124,10 @@ private: void parseSettings(const String&); void cueWillChange(); void cueDidChange(); - + virtual void refEventTarget() { ref(); } virtual void derefEventTarget() { deref(); } - + String m_id; double m_startTime; double m_endTime; @@ -130,6 +136,8 @@ private: int m_linePosition; int m_textPosition; int m_cueSize; + int m_cueIndex; + Alignment m_cueAlignment; RefPtr<DocumentFragment> m_documentFragment; RefPtr<TextTrack> m_track; diff --git a/Source/WebCore/html/TextTrackCue.idl b/Source/WebCore/html/track/TextTrackCue.idl index 4f7a40bae..12a827959 100644 --- a/Source/WebCore/html/TextTrackCue.idl +++ b/Source/WebCore/html/track/TextTrackCue.idl @@ -29,7 +29,7 @@ module html { Conditional=VIDEO_TRACK, V8EnabledAtRuntime=webkitVideoTrack, JSGenerateToNativeObject, - Constructor(in DOMString id, in double startTime, in double endTime, in DOMString text, in [Optional=CallWithDefaultValue] DOMString settings, in [Optional=CallWithDefaultValue] boolean pauseOnExit), + Constructor(in DOMString id, in double startTime, in double endTime, in DOMString text, in [Optional=DefaultIsUndefined] DOMString settings, in [Optional=DefaultIsUndefined] boolean pauseOnExit), CallWith=ScriptExecutionContext, EventTarget, JSCustomMarkFunction, diff --git a/Source/WebCore/html/TextTrackCueList.cpp b/Source/WebCore/html/track/TextTrackCueList.cpp index 34b71ca1b..391b2f651 100644 --- a/Source/WebCore/html/TextTrackCueList.cpp +++ b/Source/WebCore/html/track/TextTrackCueList.cpp @@ -40,6 +40,11 @@ unsigned long TextTrackCueList::length() const return m_list.size(); } +unsigned long TextTrackCueList::getCueIndex(TextTrackCue* cue) const +{ + return m_list.find(cue); +} + TextTrackCue* TextTrackCueList::item(unsigned index) const { if (index < m_list.size()) @@ -88,6 +93,7 @@ bool TextTrackCueList::add(PassRefPtr<TextTrackCue> prpCue, size_t start, size_t return false; m_list.insert(start, cue); + invalidateCueIndexes(start); return true; } @@ -119,6 +125,12 @@ void TextTrackCueList::clear() m_list.clear(); } +void TextTrackCueList::invalidateCueIndexes(size_t start) +{ + for (size_t i = start; i < m_list.size(); ++i) + m_list[i]->invalidateCueIndex(); +} + } // namespace WebCore #endif diff --git a/Source/WebCore/html/TextTrackCueList.h b/Source/WebCore/html/track/TextTrackCueList.h index 7a7f90415..90b19a5be 100644 --- a/Source/WebCore/html/TextTrackCueList.h +++ b/Source/WebCore/html/track/TextTrackCueList.h @@ -45,6 +45,8 @@ public: ~TextTrackCueList() { } unsigned long length() const; + unsigned long getCueIndex(TextTrackCue*) const; + TextTrackCue* item(unsigned index) const; TextTrackCue* getCueById(const String&) const; TextTrackCueList* activeCues(); @@ -57,10 +59,11 @@ private: TextTrackCueList(); bool add(PassRefPtr<TextTrackCue>, size_t, size_t); void clear(); - + void invalidateCueIndexes(size_t); + Vector<RefPtr<TextTrackCue> > m_list; RefPtr<TextTrackCueList> m_activeCues; - + }; } // namespace WebCore diff --git a/Source/WebCore/html/TextTrackCueList.idl b/Source/WebCore/html/track/TextTrackCueList.idl index 551840fe9..551840fe9 100644 --- a/Source/WebCore/html/TextTrackCueList.idl +++ b/Source/WebCore/html/track/TextTrackCueList.idl diff --git a/Source/WebCore/html/track/TextTrackList.cpp b/Source/WebCore/html/track/TextTrackList.cpp index 77d9673d4..ead195071 100644 --- a/Source/WebCore/html/track/TextTrackList.cpp +++ b/Source/WebCore/html/track/TextTrackList.cpp @@ -55,6 +55,19 @@ unsigned TextTrackList::length() const return m_addTrackTracks.size() + m_elementTracks.size(); } +unsigned TextTrackList::getTrackIndex(TextTrack *textTrack) +{ + if (textTrack->trackType() == TextTrack::TrackElement) + return static_cast<LoadableTextTrack*>(textTrack)->trackElementIndex(); + + if (textTrack->trackType() == TextTrack::AddTrack) + return m_elementTracks.size() + m_addTrackTracks.find(textTrack); + + ASSERT_NOT_REACHED(); + + return -1; +} + TextTrack* TextTrackList::item(unsigned index) { // 4.8.10.12.1 Text track model @@ -77,13 +90,21 @@ TextTrack* TextTrackList::item(unsigned index) void TextTrackList::append(PassRefPtr<TextTrack> prpTrack) { RefPtr<TextTrack> track = prpTrack; - + if (track->trackType() == TextTrack::AddTrack) m_addTrackTracks.append(track); else if (track->trackType() == TextTrack::TrackElement) { // Insert tracks added for <track> element in tree order. size_t index = static_cast<LoadableTextTrack*>(track.get())->trackElementIndex(); m_elementTracks.insert(index, track); + + // Invalidate the cached index for all the following tracks. + for (size_t i = index; i < m_elementTracks.size(); ++i) + m_elementTracks[i]->invalidateTrackIndex(); + + for (size_t i = 0; i < m_addTrackTracks.size(); ++i) + m_addTrackTracks[i]->invalidateTrackIndex(); + } else ASSERT_NOT_REACHED(); diff --git a/Source/WebCore/html/track/TextTrackList.h b/Source/WebCore/html/track/TextTrackList.h index 88d9af62e..f8f04ffa9 100644 --- a/Source/WebCore/html/track/TextTrackList.h +++ b/Source/WebCore/html/track/TextTrackList.h @@ -51,6 +51,8 @@ public: ~TextTrackList(); unsigned length() const; + unsigned getTrackIndex(TextTrack*); + TextTrack* item(unsigned index); void append(PassRefPtr<TextTrack>); void remove(TextTrack*); |