Commit e60bb185 authored by darin's avatar darin

LayoutTests:

        Reviewed by Maciej.
        Landed by Darin.

        - test for http://bugs.webkit.org/show_bug.cgi?id=14569
          Repro crash due to saved state not being cleared when select and textarea elements are adopted by another document
          and for http://bugs.webkit.org/show_bug.cgi?id=13701
          REGRESSION (r21431): Reproducible crash resulting from calling adoptNode on a password field

        * fast/forms/saved-state-adoptNode-crash-expected.txt: Added.
        * fast/forms/saved-state-adoptNode-crash.html: Added.

WebCore:

        Reviewed by Mitz.

        - fix http://bugs.webkit.org/show_bug.cgi?id=14569
          Repro crash due to saved state not being cleared when select and textarea elements
          are adopted by another document

        Test: fast/forms/saved-state-adoptNode-crash.html

        * dom/Document.h:
        (WebCore::Document::registerFormElementWithState): Updated parameter type to be
        HTMLFormControlElementWithState.
        (WebCore::Document::unregisterFormElementWithState): Ditto.
        Also removed isFormElementRegistered function and changed the type of the
        m_formElementsWithState ListHashSet.
        * dom/Document.cpp: (WebCore::Document::formElementsState): Updated to use new type,
        for set contents and to use new saveState() function and only save state for elements
        that return true.

        * html/HTMLGenericFormElement.h: Added HTMLFormControlElementWithState class,
        derived from HTMLGenericFormElement, and moved down all the behavior related to
        saving form control element state. Also removed the unnecessary default parameter
        to the HTMLGenericFormElement constructor.
        * html/HTMLGenericFormElement.cpp:
        (WebCore::HTMLFormControlElementWithState::HTMLFormControlElementWithState): Added.
        Calls registerFormElementWithState.
        (WebCore::HTMLFormControlElementWithState::~HTMLFormControlElementWithState): Added.
        Calls unregisterFormElementWithState.
        (WebCore::HTMLFormControlElementWithState::willMoveToNewOwnerDocument): Added.
        Calls unregisterFormElementWithState.
        (WebCore::HTMLFormControlElementWithState::didMoveToNewOwnerDocument): Added.
        Calls registerFormElementWithState.
        (WebCore::HTMLFormControlElementWithState::closeRenderer): Moved to this class from
        the base class.

        * html/HTMLInputElement.h: Updated the base class name and overrode saveState instead
        of stateValue.
        * html/HTMLInputElement.cpp: Updated the base class name.
        (WebCore::HTMLInputElement::init): Removed the call to registerFormElementWithState.
        (WebCore::HTMLInputElement::~HTMLInputElement): Removed the call to
        unregisterFormElementWithState. Also changed the code to only call the
        unregisterForDidRestoreFromCacheCallback function for type PASSWORD (consistency
        and efficiency).
        (WebCore::HTMLInputElement::setInputType): Removed calls to registerFormElementWithState
        and unregisterFormElementWithState; we now let the element stay registered and simply
        don't save or restore state for password fields.
        (WebCore::HTMLInputElement::saveState): Updated function name and signature to replace
        the old stateValue function. Returns false for password fields.
        (WebCore::HTMLInputElement::willMoveToNewOwnerDocument): Removed the call to
        unregisterFormElementWithState.
        (WebCore::HTMLInputElement::didMoveToNewOwnerDocument): Removed the call to
        registerFormElementWithState.

        * html/HTMLSelectElement.h: Updated the base class name and overrode saveState instead
        of stateValue.
        * html/HTMLSelectElement.cpp: Updated the base class name.
        (WebCore::HTMLSelectElement::HTMLSelectElement): Removed the call to
        registerFormElementWithState.
        (WebCore::HTMLSelectElement::~HTMLSelectElement): Removed the call to
        unregisterFormElementWithState.
        (WebCore::HTMLSelectElement::saveState): Updated function name and signature to
        replace the old stateValue function.
        (WebCore::HTMLSelectElement::setLength): Updated to use document() instead of
        ownerDocument(); the latter is just a slower virtual-function way of doing the
        same thing in all cases except for Document and XPathNamespace.

        * html/HTMLTextAreaElement.h: Update the base class name, overrode saveState instead
        of stateValue, and removed the now-unnecessary explicit destructor.
        * html/HTMLTextAreaElement.cpp: Updated the base class name.
        (WebCore::HTMLTextAreaElement::HTMLTextAreaElement): Removed the call to
        registerFormElementWithState.
        (WebCore::HTMLTextAreaElement::saveState): Updated function name and signature to replace
        the old stateValue function.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@24363 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 6d162e78
2007-07-17 Mitz Pettel <mitz@webkit.org>
Reviewed by Maciej.
Landed by Darin.
- test for http://bugs.webkit.org/show_bug.cgi?id=14569
Repro crash due to saved state not being cleared when select and textarea elements are adopted by another document
and for http://bugs.webkit.org/show_bug.cgi?id=13701
REGRESSION (r21431): Reproducible crash resulting from calling adoptNode on a password field
* fast/forms/saved-state-adoptNode-crash-expected.txt: Added.
* fast/forms/saved-state-adoptNode-crash.html: Added.
2007-07-17 Darin Adler <darin@apple.com>
* http/tests/navigation/multiple-back-forward-entries-expected.txt: Updated results to
<select id="select">
<option>Truffles</option>
</select>
<textarea id="textarea">
Marshmallows
</textarea>
<iframe id="iframe" src="data:text/html,"></iframe>
<input type="password" id="password" value="seikooC">
<script>
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}
var newDoc = document.getElementById("iframe").contentDocument;
newDoc.adoptNode(document.getElementById("select"));
newDoc.adoptNode(document.getElementById("textarea"));
newDoc.adoptNode(document.getElementById("password"));
location.href="data:text/html,SUCCESS<script>if (window.layoutTestController) layoutTestController.notifyDone()</scr" + "ipt>";
</script>
2007-07-17 Darin Adler <darin@apple.com>
Reviewed by Mitz.
- fix http://bugs.webkit.org/show_bug.cgi?id=14569
Repro crash due to saved state not being cleared when select and textarea elements
are adopted by another document
Test: fast/forms/saved-state-adoptNode-crash.html
* dom/Document.h:
(WebCore::Document::registerFormElementWithState): Updated parameter type to be
HTMLFormControlElementWithState.
(WebCore::Document::unregisterFormElementWithState): Ditto.
Also removed isFormElementRegistered function and changed the type of the
m_formElementsWithState ListHashSet.
* dom/Document.cpp: (WebCore::Document::formElementsState): Updated to use new type,
for set contents and to use new saveState() function and only save state for elements
that return true.
* html/HTMLGenericFormElement.h: Added HTMLFormControlElementWithState class,
derived from HTMLGenericFormElement, and moved down all the behavior related to
saving form control element state. Also removed the unnecessary default parameter
to the HTMLGenericFormElement constructor.
* html/HTMLGenericFormElement.cpp:
(WebCore::HTMLFormControlElementWithState::HTMLFormControlElementWithState): Added.
Calls registerFormElementWithState.
(WebCore::HTMLFormControlElementWithState::~HTMLFormControlElementWithState): Added.
Calls unregisterFormElementWithState.
(WebCore::HTMLFormControlElementWithState::willMoveToNewOwnerDocument): Added.
Calls unregisterFormElementWithState.
(WebCore::HTMLFormControlElementWithState::didMoveToNewOwnerDocument): Added.
Calls registerFormElementWithState.
(WebCore::HTMLFormControlElementWithState::closeRenderer): Moved to this class from
the base class.
* html/HTMLInputElement.h: Updated the base class name and overrode saveState instead
of stateValue.
* html/HTMLInputElement.cpp: Updated the base class name.
(WebCore::HTMLInputElement::init): Removed the call to registerFormElementWithState.
(WebCore::HTMLInputElement::~HTMLInputElement): Removed the call to
unregisterFormElementWithState. Also changed the code to only call the
unregisterForDidRestoreFromCacheCallback function for type PASSWORD (consistency
and efficiency).
(WebCore::HTMLInputElement::setInputType): Removed calls to registerFormElementWithState
and unregisterFormElementWithState; we now let the element stay registered and simply
don't save or restore state for password fields.
(WebCore::HTMLInputElement::saveState): Updated function name and signature to replace
the old stateValue function. Returns false for password fields.
(WebCore::HTMLInputElement::willMoveToNewOwnerDocument): Removed the call to
unregisterFormElementWithState.
(WebCore::HTMLInputElement::didMoveToNewOwnerDocument): Removed the call to
registerFormElementWithState.
* html/HTMLSelectElement.h: Updated the base class name and overrode saveState instead
of stateValue.
* html/HTMLSelectElement.cpp: Updated the base class name.
(WebCore::HTMLSelectElement::HTMLSelectElement): Removed the call to
registerFormElementWithState.
(WebCore::HTMLSelectElement::~HTMLSelectElement): Removed the call to
unregisterFormElementWithState.
(WebCore::HTMLSelectElement::saveState): Updated function name and signature to
replace the old stateValue function.
(WebCore::HTMLSelectElement::setLength): Updated to use document() instead of
ownerDocument(); the latter is just a slower virtual-function way of doing the
same thing in all cases except for Document and XPathNamespace.
* html/HTMLTextAreaElement.h: Update the base class name, overrode saveState instead
of stateValue, and removed the now-unnecessary explicit destructor.
* html/HTMLTextAreaElement.cpp: Updated the base class name.
(WebCore::HTMLTextAreaElement::HTMLTextAreaElement): Removed the call to
registerFormElementWithState.
(WebCore::HTMLTextAreaElement::saveState): Updated function name and signature to replace
the old stateValue function.
2007-07-17 Sam Weinig <sam@webkit.org>
Reviewed by Darin.
......@@ -3431,13 +3431,16 @@ Vector<String> Document::formElementsState() const
{
Vector<String> stateVector;
stateVector.reserveCapacity(m_formElementsWithState.size() * 3);
typedef ListHashSet<HTMLGenericFormElement*>::const_iterator Iterator;
typedef ListHashSet<HTMLFormControlElementWithState*>::const_iterator Iterator;
Iterator end = m_formElementsWithState.end();
for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
HTMLGenericFormElement* e = *it;
stateVector.append(e->name().domString());
stateVector.append(e->type().domString());
stateVector.append(e->stateValue());
HTMLFormControlElementWithState* e = *it;
String value;
if (e->saveState(value)) {
stateVector.append(e->name().domString());
stateVector.append(e->type().domString());
stateVector.append(value);
}
}
return stateVector;
}
......
......@@ -3,7 +3,7 @@
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Dirk Mueller (mueller@kde.org)
* (C) 2006 Alexey Proskuryakov (ap@webkit.org)
* Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
* Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -61,8 +61,8 @@ namespace WebCore {
class FrameView;
class HTMLDocument;
class HTMLElement;
class HTMLFormControlElementWithState;
class HTMLFormElement;
class HTMLGenericFormElement;
class HTMLHeadElement;
class HTMLImageLoader;
class HTMLInputElement;
......@@ -293,9 +293,8 @@ public:
void setUsesFirstLetterRules(bool b) { m_usesFirstLetterRules = b; }
// Machinery for saving and restoring state when you leave and then go back to a page.
void registerFormElementWithState(HTMLGenericFormElement* e) { m_formElementsWithState.add(e); }
void unregisterFormElementWithState(HTMLGenericFormElement* e) { m_formElementsWithState.remove(e); }
bool isFormElementRegistered(HTMLGenericFormElement* e) { return m_formElementsWithState.contains(e); }
void registerFormElementWithState(HTMLFormControlElementWithState* e) { m_formElementsWithState.add(e); }
void unregisterFormElementWithState(HTMLFormControlElementWithState* e) { m_formElementsWithState.remove(e); }
Vector<String> formElementsState() const;
void setStateForNewFormElements(const Vector<String>&);
bool hasStateForNewFormElements() const;
......@@ -708,7 +707,7 @@ protected:
RegisteredEventListenerList m_windowEventListeners;
typedef HashMap<FormElementKey, Vector<String>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
ListHashSet<HTMLGenericFormElement*> m_formElementsWithState;
ListHashSet<HTMLFormControlElementWithState*> m_formElementsWithState;
FormElementStateMap m_stateForNewFormElements;
HashSet<Element*> m_didRestorePageCallbackSet;
......
......@@ -40,7 +40,11 @@ using namespace EventNames;
using namespace HTMLNames;
HTMLGenericFormElement::HTMLGenericFormElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
: HTMLElement(tagName, doc), m_form(f), m_disabled(false), m_readOnly(false), m_valueMatchesRenderer(false)
: HTMLElement(tagName, doc)
, m_form(f)
, m_disabled(false)
, m_readOnly(false)
, m_valueMatchesRenderer(false)
{
if (!m_form)
m_form = findFormAncestor();
......@@ -189,45 +193,52 @@ bool HTMLGenericFormElement::isMouseFocusable() const
return false;
}
String HTMLGenericFormElement::stateValue() const
void HTMLGenericFormElement::setTabIndex(int value)
{
setAttribute(tabindexAttr, String::number(value));
}
bool HTMLGenericFormElement::supportsFocus() const
{
// Should only reach here if object is inserted into the "form element with
// state" set. If so, the derived class is responsible for implementing this function.
ASSERT_NOT_REACHED();
return String();
return isFocusable() || (!disabled() && !document()->haveStylesheetsLoaded());
}
void HTMLGenericFormElement::restoreState(const String&)
HTMLFormElement* HTMLGenericFormElement::virtualForm() const
{
// Should only reach here if object of this type was once inserted into the
// "form element with state" set. If so, the derived class is responsible for
// implementing this function.
ASSERT_NOT_REACHED();
return m_form;
}
void HTMLGenericFormElement::closeRenderer()
HTMLFormControlElementWithState::HTMLFormControlElementWithState(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
: HTMLGenericFormElement(tagName, doc, f)
{
Document* doc = document();
if (doc->isFormElementRegistered(this) && doc->hasStateForNewFormElements()) {
String state;
if (doc->takeStateForFormElement(name().impl(), type().impl(), state))
restoreState(state);
}
doc->registerFormElementWithState(this);
}
void HTMLGenericFormElement::setTabIndex(int value)
HTMLFormControlElementWithState::~HTMLFormControlElementWithState()
{
setAttribute(tabindexAttr, String::number(value));
document()->unregisterFormElementWithState(this);
}
bool HTMLGenericFormElement::supportsFocus() const
void HTMLFormControlElementWithState::willMoveToNewOwnerDocument()
{
return isFocusable() || (!disabled() && !document()->haveStylesheetsLoaded());
document()->unregisterFormElementWithState(this);
HTMLGenericFormElement::willMoveToNewOwnerDocument();
}
HTMLFormElement* HTMLGenericFormElement::virtualForm() const
void HTMLFormControlElementWithState::didMoveToNewOwnerDocument()
{
return m_form;
document()->registerFormElementWithState(this);
HTMLGenericFormElement::didMoveToNewOwnerDocument();
}
void HTMLFormControlElementWithState::closeRenderer()
{
Document* doc = document();
if (doc->hasStateForNewFormElements()) {
String state;
if (doc->takeStateForFormElement(name().impl(), type().impl(), state))
restoreState(state);
}
}
} // namespace Webcore
......@@ -34,7 +34,7 @@ class HTMLFormElement;
// FIXME: Rename this class to HTMLFormControlElement.
class HTMLGenericFormElement : public HTMLElement {
public:
HTMLGenericFormElement(const QualifiedName& tagName, Document*, HTMLFormElement* = 0);
HTMLGenericFormElement(const QualifiedName& tagName, Document*, HTMLFormElement*);
virtual ~HTMLGenericFormElement();
virtual HTMLTagStatus endTagRequirement() const { return TagStatusRequired; }
......@@ -51,7 +51,6 @@ public:
virtual void attach();
virtual void insertedIntoTree(bool deep);
virtual void removedFromTree(bool deep);
virtual void closeRenderer();
virtual void reset() {}
......@@ -85,9 +84,6 @@ public:
*/
virtual bool appendFormData(FormDataList&, bool) { return false; }
virtual String stateValue() const;
virtual void restoreState(const String& value);
virtual bool isSuccessfulSubmitButton() const { return false; }
virtual bool isActivatedSubmit() const { return false; }
virtual void setActivatedSubmit(bool flag) { }
......@@ -105,6 +101,23 @@ private:
mutable bool m_valueMatchesRenderer;
};
class HTMLFormControlElementWithState : public HTMLGenericFormElement {
public:
HTMLFormControlElementWithState(const QualifiedName& tagName, Document*, HTMLFormElement*);
virtual ~HTMLFormControlElementWithState();
virtual void closeRenderer();
virtual bool saveState(String& value) const = 0;
protected:
virtual void willMoveToNewOwnerDocument();
virtual void didMoveToNewOwnerDocument();
private:
virtual void restoreState(const String& value) = 0;
};
} //namespace
#endif
......@@ -97,14 +97,14 @@ static int numCharactersInGraphemeClusters(const StringImpl* s, int numGraphemeC
return textBreakCurrent(it);
}
HTMLInputElement::HTMLInputElement(Document *doc, HTMLFormElement *f)
: HTMLGenericFormElement(inputTag, doc, f)
HTMLInputElement::HTMLInputElement(Document* doc, HTMLFormElement* f)
: HTMLFormControlElementWithState(inputTag, doc, f)
{
init();
}
HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document *doc, HTMLFormElement *f)
: HTMLGenericFormElement(tagName, doc, f)
HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
: HTMLFormControlElementWithState(tagName, doc, f)
{
init();
}
......@@ -136,14 +136,12 @@ void HTMLInputElement::init()
if (form())
m_autocomplete = form()->autoComplete();
document()->registerFormElementWithState(this);
}
HTMLInputElement::~HTMLInputElement()
{
ownerDocument()->unregisterFormElementWithState(this);
ownerDocument()->unregisterForDidRestoreFromCacheCallback(this);
if (inputType() == PASSWORD)
document()->unregisterForDidRestoreFromCacheCallback(this);
delete m_imageLoader;
}
......@@ -156,10 +154,10 @@ bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
{
// If text fields can be focused, then they should always be keyboard focusable
if (isTextField())
return HTMLGenericFormElement::isFocusable();
return HTMLFormControlElementWithState::isFocusable();
// If the base class says we can't be focused, then we can stop now.
if (!HTMLGenericFormElement::isKeyboardFocusable(event))
if (!HTMLFormControlElementWithState::isKeyboardFocusable(event))
return false;
if (inputType() == RADIO) {
......@@ -187,8 +185,8 @@ bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
bool HTMLInputElement::isMouseFocusable() const
{
if (isTextField())
return HTMLGenericFormElement::isFocusable();
return HTMLGenericFormElement::isMouseFocusable();
return HTMLFormControlElementWithState::isFocusable();
return HTMLFormControlElementWithState::isMouseFocusable();
}
void HTMLInputElement::focus(bool restorePreviousSelection)
......@@ -210,7 +208,7 @@ void HTMLInputElement::focus(bool restorePreviousSelection)
updateFocusAppearance(restorePreviousSelection);
return;
}
HTMLGenericFormElement::focus(restorePreviousSelection);
HTMLFormControlElementWithState::focus(restorePreviousSelection);
}
void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
......@@ -225,7 +223,7 @@ void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
if (document() && document()->frame())
document()->frame()->revealSelection();
} else
HTMLGenericFormElement::updateFocusAppearance();
HTMLFormControlElementWithState::updateFocusAppearance();
}
void HTMLInputElement::aboutToUnload()
......@@ -241,7 +239,7 @@ void HTMLInputElement::dispatchFocusEvent()
if (inputType() == PASSWORD && document()->frame())
document()->setUseSecureKeyboardEntryWhenActive(true);
}
HTMLGenericFormElement::dispatchFocusEvent();
HTMLFormControlElementWithState::dispatchFocusEvent();
}
void HTMLInputElement::dispatchBlurEvent()
......@@ -251,7 +249,7 @@ void HTMLInputElement::dispatchBlurEvent()
document()->setUseSecureKeyboardEntryWhenActive(false);
document()->frame()->textFieldDidEndEditing(this);
}
HTMLGenericFormElement::dispatchBlurEvent();
HTMLFormControlElementWithState::dispatchBlurEvent();
}
void HTMLInputElement::setType(const String& t)
......@@ -328,13 +326,10 @@ void HTMLInputElement::setInputType(const String& t)
else
recheckValue();
if (wasPasswordField && !isPasswordField) {
ownerDocument()->registerFormElementWithState(this);
ownerDocument()->unregisterForDidRestoreFromCacheCallback(this);
} else if (!wasPasswordField && isPasswordField) {
ownerDocument()->unregisterFormElementWithState(this);
ownerDocument()->registerForDidRestoreFromCacheCallback(this);
}
if (wasPasswordField && !isPasswordField)
document()->unregisterForDidRestoreFromCacheCallback(this);
else if (!wasPasswordField && isPasswordField)
document()->registerForDidRestoreFromCacheCallback(this);
if (didRespectHeightAndWidth != willRespectHeightAndWidth) {
NamedMappedAttrMap* map = mappedAttributes();
......@@ -421,9 +416,8 @@ const AtomicString& HTMLInputElement::type() const
return emptyAtom;
}
String HTMLInputElement::stateValue() const
bool HTMLInputElement::saveState(String& result) const
{
ASSERT(inputType() != PASSWORD); // should never save/restore password fields
switch (inputType()) {
case BUTTON:
case FILE:
......@@ -435,14 +429,17 @@ String HTMLInputElement::stateValue() const
case SEARCH:
case SUBMIT:
case TEXT:
return value();
result = value();
return true;
case CHECKBOX:
case RADIO:
return checked() ? "on" : "off";
result = checked() ? "on" : "off";
return true;
case PASSWORD:
break;
return false;
}
return String();
ASSERT_NOT_REACHED();
return false;
}
void HTMLInputElement::restoreState(const String& state)
......@@ -683,7 +680,7 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr)
attr->name() == precisionAttr) {
setChanged();
} else
HTMLGenericFormElement::parseMappedAttribute(attr);
HTMLFormControlElementWithState::parseMappedAttribute(attr);
}
bool HTMLInputElement::rendererIsNeeded(RenderStyle *style)
......@@ -701,7 +698,7 @@ bool HTMLInputElement::rendererIsNeeded(RenderStyle *style)
case SEARCH:
case SUBMIT:
case TEXT:
return HTMLGenericFormElement::rendererIsNeeded(style);
return HTMLFormControlElementWithState::rendererIsNeeded(style);
case HIDDEN:
return false;
}
......@@ -745,7 +742,7 @@ void HTMLInputElement::attach()
m_inited = true;
}
HTMLGenericFormElement::attach();
HTMLFormControlElementWithState::attach();
if (inputType() == IMAGE) {
if (!m_imageLoader)
......@@ -765,7 +762,7 @@ void HTMLInputElement::attach()
void HTMLInputElement::detach()
{
HTMLGenericFormElement::detach();
HTMLFormControlElementWithState::detach();
setValueMatchesRenderer(false);
}
......@@ -922,7 +919,7 @@ void HTMLInputElement::copyNonAttributeProperties(const Element *source)
m_checked = sourceElem->m_checked;
m_indeterminate = sourceElem->m_indeterminate;
HTMLGenericFormElement::copyNonAttributeProperties(source);
HTMLFormControlElementWithState::copyNonAttributeProperties(source);
}
String HTMLInputElement::value() const
......@@ -1144,7 +1141,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt)
// Let the key handling done in EventTargetNode take precedence over the event handling here for editable text fields
if (!clickDefaultFormButton) {
HTMLGenericFormElement::defaultEventHandler(evt);
HTMLFormControlElementWithState::defaultEventHandler(evt);
if (evt->defaultHandled())
return;
}
......@@ -1481,21 +1478,17 @@ void HTMLInputElement::didRestoreFromCache()
void HTMLInputElement::willMoveToNewOwnerDocument()
{
if (inputType() == PASSWORD)
ownerDocument()->unregisterForDidRestoreFromCacheCallback(this);
else
ownerDocument()->unregisterFormElementWithState(this);
document()->unregisterForDidRestoreFromCacheCallback(this);
HTMLGenericFormElement::willMoveToNewOwnerDocument();
HTMLFormControlElementWithState::willMoveToNewOwnerDocument();
}
void HTMLInputElement::didMoveToNewOwnerDocument()
{
if (inputType() == PASSWORD)
document()->registerForDidRestoreFromCacheCallback(this);
else
document()->registerFormElementWithState(this);
HTMLGenericFormElement::didMoveToNewOwnerDocument();
HTMLFormControlElementWithState::didMoveToNewOwnerDocument();
}
} // namespace
/*
* This file is part of the DOM implementation for KDE.
*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007 Apple Inc.
* Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -33,7 +31,7 @@ namespace WebCore {
class HTMLImageLoader;
class Selection;
class HTMLInputElement : public HTMLGenericFormElement {
class HTMLInputElement : public HTMLFormControlElementWithState {
public:
enum InputType {
TEXT,
......@@ -97,7 +95,7 @@ public:
void setValueFromRenderer(const String&);
virtual String stateValue() const;
virtual bool saveState(String& value) const;
virtual void restoreState(const String&);
bool canHaveSelection() const;
......
......@@ -63,7 +63,7 @@ using namespace HTMLNames;
static const DOMTimeStamp typeAheadTimeout = 1000;
HTMLSelectElement::HTMLSelectElement(Document* doc, HTMLFormElement* f)
: HTMLGenericFormElement(selectTag, doc, f)
: HTMLFormControlElementWithState(selectTag, doc, f)
, m_minwidth(0)
, m_size(0)
, m_multiple(false)
......@@ -75,11 +75,10 @@ HTMLSelectElement::HTMLSelectElement(Document* doc, HTMLFormElement* f)
, m_repeatingChar(0)
, m_lastCharTime(0)
{
document()->registerFormElementWithState(this);
}
HTMLSelectElement::HTMLSelectElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
: HTMLGenericFormElement(tagName, doc, f)
: HTMLFormControlElementWithState(tagName, doc, f)
, m_minwidth(0)
, m_size(0)
, m_multiple(false)
......@@ -91,12 +90,6 @@ HTMLSelectElement::HTMLSelectElement(const QualifiedName& tagName, Document* doc
, m_repeatingChar(0)
, m_lastCharTime(0)
{
document()->registerFormElementWithState(this);
}
HTMLSelectElement::~HTMLSelectElement()
{
document()->unregisterFormElementWithState(this);
}
bool HTMLSelectElement::checkDTD(const Node* newChild)
......@@ -115,7 +108,7 @@ void HTMLSelectElement::recalcStyle( StyleChange ch )
static_cast<RenderListBox*>(renderer())->setOptionsChanged(true);
}
HTMLGenericFormElement::recalcStyle( ch );
HTMLFormControlElementWithState::recalcStyle(ch);
}
const AtomicString& HTMLSelectElement::type() const
......@@ -277,7 +270,7 @@ void HTMLSelectElement::setValue(const String &value)
}
}
String HTMLSelectElement::stateValue() const
bool HTMLSelectElement::saveState(String& value) const
{
const Vector<HTMLElement*>& items = listItems();
int l = items.size();
......@@ -287,7 +280,8 @@ String HTMLSelectElement::stateValue() const
bool selected = e->hasLocalName(optionTag) && static_cast<HTMLOptionElement*>(e)->selected();
characters[i] = selected ? 'X' : '.';
}
return String(characters, l);
value = String(characters, l);
return true;
}
void HTMLSelectElement::restoreState(const String& state)
......@@ -305,7 +299,7 @@ void HTMLSelectElement::restoreState(const String& state)
bool HTMLSelectElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec)
{
bool result = HTMLGenericFormElement::insertBefore(newChild, refChild, ec);
bool result = HTMLFormControlElementWithState::insertBefore(newChild, refChild, ec);
if (result)
setRecalcListItems();
return result;
......@@ -313,7 +307,7 @@ bool HTMLSelectElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild,
bool HTMLSelectElement::replaceChild(PassRefPtr<Node> newChild, Node *oldChild, ExceptionCode& ec)
{
bool result = HTMLGenericFormElement::replaceChild(newChild, oldChild, ec);
bool result = HTMLFormControlElementWithState::replaceChild(newChild, oldChild, ec);
if (result)
setRecalcListItems();
return result;
......@@ -321,7 +315,7 @@ bool HTMLSelectElement::replaceChild(PassRefPtr<Node> newChild, Node *oldChild,
bool HTMLSelectElement::removeChild(Node* oldChild, ExceptionCode& ec)
{
bool result = HTMLGenericFormElement::removeChild(oldChild, ec);
bool result = HTMLFormControlElementWithState::removeChild(oldChild, ec);
if (result)
setRecalcListItems();
return result;
......@@ -329,7 +323,7 @@ bool HTMLSelectElement::removeChild(Node* oldChild, ExceptionCode& ec)
bool HTMLSelectElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec)
{
bool result = HTMLGenericFormElement::appendChild(newChild, ec);
bool result = HTMLFormControlElementWithState::appendChild(newChild, ec);
if (result)
setRecalcListItems();
return result;
......@@ -337,7 +331,7 @@ bool HTMLSelectElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec
ContainerNode* HTMLSelectElement::addChild(PassRefPtr<Node> newChild)
{
ContainerNode* result = HTMLGenericFormElement::addChild(newChild);
ContainerNode* result = HTMLFormControlElementWithState::addChild(newChild);
if (result)
setRecalcListItems();
return result;
......@@ -380,21 +374,21 @@ void HTMLSelectElement::parseMappedAttribute(MappedAttribute *attr)
} else if (attr->name() == onchangeAttr) {
setHTMLEventListener(changeEvent, attr);
} else
HTMLGenericFormElement::parseMappedAttribute(attr);
HTMLFormControlElementWithState::parseMappedAttribute(attr);
}