从KK开始,Google开始切换Web引擎了, androd webkit废弃,改为chromium了,但是前面运营商大爷要求的WML咋办?唉,硬着头皮开始把WML往chromium上搞呗.
如何搞?采用最笨的方法,HTML相关的类被调用的地方过一遍,加上WML相对应的类。
贴出来部分修改的地方,因为本来就是基于opensource的,所以不存在confidential的问题。
看到修改的文件,大概就能知道HTML相关的类在显示和交互的过程中会与那些类打交道。
Source/core/html/BaseTextInputType.h
class BaseTextInputType : public TextFieldInputType {
protected:
#if ENABLE(WML)
BaseTextInputType(WMLInputElement* element) : TextFieldInputType(element) { }
#endif
BaseTextInputType(HTMLInputElement* element) : TextFieldInputType(element) { }
Source/core/html/BaseTextInputType.cpp
bool BaseTextInputType::patternMismatch(const String& value) const
{
#if ENABLE(WML)
if (isWML()) {
/Fix me, Neo Check???/
return false;
} else {
#endif
const AtomicString& rawPattern = element()->fastGetAttribute(patternAttr);
// Empty values can’t be mismatched
if (rawPattern.isNull() || value.isEmpty() || !RegularExpression(rawPattern, TextCaseSensitive).isValid())
return false;
String pattern = “^(?:” + rawPattern + “)$”;
int matchLength = 0;
int valueLength = value.length();
int matchOffset = RegularExpression(pattern, TextCaseSensitive).match(value, 0, &matchLength);
return matchOffset || matchLength != valueLength;
#if ENABLE(WML)
}
#endif
}
Source/core/html/InputType.h
public:
#if ENABLE(WML)
static PassOwnPtr create(WMLInputElement*, const AtomicString&);
static PassOwnPtr createText(WMLInputElement*);
#endif
static PassOwnPtr create(HTMLInputElement*, const AtomicString&);
protected:
#if ENABLE(WML)
bool isWML() const { return m_wmlinput; }
InputType(WMLInputElement* element) : m_elementwml(element), m_wmlinput(true) { }
WMLInputElement* wmlelement() const { return m_elementwml; }
#endif
InputType(HTMLInputElement* element) : m_element(element),m_wmlinput(false) { }
HTMLInputElement* element() const { return m_element; }
Chrome* chrome() const;
Decimal parseToNumberOrNaN(const String&) const;
void observeFeatureIfVisible(UseCounter::Feature) const;
private:
// Helper for stepUp()/stepDown(). Adds step value * count to the current value.
void applyStep(int count, AnyStepHandling, TextFieldEventBehavior, ExceptionState&);
// Raw pointer because the HTMLInputElement object owns this InputType object.
HTMLInputElement* m_element;
#if ENABLE(WML)
WMLInputElement* m_elementwml;
bool m_wmlinput;
#endif
Source/core/html/InputType.cpp
PassOwnPtr InputType::create(WMLInputElement* element, const AtomicString& typeName)
{
return (typeName == InputTypeNames::password())?PasswordInputType::create(element): TextInputType::create(element);
}
PassOwnPtr InputType::createText(WMLInputElement* element)
{
return TextInputType::create(element);
}
FormControlState InputType::saveFormControlState() const
{
#if ENABLE(WML)
if (isWML())
return FormControlState();
#endif
String currentValue = element()->value();
if (currentValue == element()->defaultValue())
return FormControlState();
return FormControlState(currentValue);
}
void InputType::restoreFormControlState(const FormControlState& state)
{
#if ENABLE(WML)
if (isWML())
wmlelement()->setValue(state[0]);
else
#endif
element()->setValue(state[0]);
}
bool InputType::isFormDataAppendable() const
{
#if ENABLE(WML)
if (isWML())
return !wmlelement()->name().isEmpty();
else
#endif
// There is no form data unless there’s a name for non-image types.
return !element()->name().isEmpty();
}
bool InputType::appendFormData(FormDataList& encoding, bool) const
{
#if ENABLE(WML)
if (isWML())
encoding.appendData(wmlelement()->name(), wmlelement()->value());
else
#endif
bool InputType::sizeShouldIncludeDecoration(int, int& preferredSize) const
{
#if ENABLE(WML)
if (isWML())
preferredSize = wmlelement()->size();
else
#endif
preferredSize = element()->size();
return false;
}
String InputType::validationMessage() const
{
String value;
#if ENABLE(WML)
if (isWML())
value = wmlelement()->value();
else
#endif
value = element()->value();
// The order of the following checks is meaningful. e.g. We'd like to show the
// badInput message even if the control has other validation errors.
if (hasBadInput())
return badInputText();
if (valueMissing(value))
return valueMissingText();
if (typeMismatch())
return typeMismatchText();
if (patternMismatch(value))
return validationMessagePatternMismatchText();
#if ENABLE(WML)
if (isWML() && wmlelement()->tooLong())
return validationMessageTooLongText(numGraphemeClusters(value), wmlelement()->maxLength());
if (!isWML() && element()->tooLong())
return validationMessageTooLongText(numGraphemeClusters(value), element()->maxLength());
#endif
PassRefPtr InputType::formForSubmission() const
{
#if ENABLE(WML)
if (isWML())
return 0;
else
#endif
return element()->form();
}
RenderObject* InputType::createRenderer(RenderStyle* style) const
{
#if ENABLE(WML)
if (isWML())
return RenderObject::createObject(wmlelement(), style);
else
#endif
return RenderObject::createObject(element(), style);
}
PassRefPtr InputType::customStyleForRenderer(PassRefPtr originalStyle)
{
return originalStyle;
}
void InputType::blur()
{
#if ENABLE(WML)
if (isWML())
wmlelement()->defaultBlur();
else
#endif
element()->defaultBlur();
}
void InputType::createShadowSubtree()
{
}
void InputType::destroyShadowSubtree()
{
ShadowRoot* root;
#if ENABLE(WML)
if (isWML())
root = wmlelement()->userAgentShadowRoot();
else
#endif
root = element()->userAgentShadowRoot();
if (!root)
return;
void InputType::dispatchSimulatedClickIfActive(KeyboardEvent* event) const
{
#if ENABLE(WML)
if (isWML()) {
if (wmlelement()->active())
wmlelement()->dispatchSimulatedClick(event);
} else {
#endif
if (element()->active())
element()->dispatchSimulatedClick(event);
event->setDefaultHandled();
#if ENABLE(WML)
}
#endif
}
Chrome* InputType::chrome() const
{
#if ENABLE(WML)
if (isWML()) {
if (Page* page = wmlelement()->document()->page())
return &page->chrome();
}
else
#endif
if (Page* page = element()->document()->page())
return &page->chrome();
return 0;
}
bool InputType::canSetStringValue() const
{
return true;
}
bool InputType::hasCustomFocusLogic() const
{
return true;
}
bool InputType::isKeyboardFocusable() const
{
#if ENABLE(WML)
if (isWML())
return wmlelement()->isFocusable();
else
#endif
return element()->isFocusable();
}
void InputType::accessKeyAction(bool)
{
#if ENABLE(WML)
if (isWML())
wmlelement()->focus(false);
else
#endif
element()->focus(false);
}
void InputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
{
#if ENABLE(WML)
if (isWML()) {
wmlelement()->setValueInternal(sanitizedValue, eventBehavior);
wmlelement()->setNeedsStyleRecalc();
if (!valueChanged)
return;
switch (eventBehavior) {
case DispatchChangeEvent:
wmlelement()->dispatchFormControlChangeEvent();
break;
case DispatchInputAndChangeEvent:
wmlelement()->dispatchFormControlInputEvent();
wmlelement()->dispatchFormControlChangeEvent();
break;
case DispatchNoEvent:
break;
}
} else {
#endif
element()->setValueInternal(sanitizedValue, eventBehavior);
element()->setNeedsStyleRecalc();
if (!valueChanged)
return;
switch (eventBehavior) {
case DispatchChangeEvent:
element()->dispatchFormControlChangeEvent();
break;
case DispatchInputAndChangeEvent:
element()->dispatchFormControlInputEvent();
element()->dispatchFormControlChangeEvent();
break;
case DispatchNoEvent:
break;
}
#if ENABLE(WML)
}
#endif
}
String InputType::visibleValue() const
{
#if ENABLE(WML)
if (isWML())
return wmlelement()->value();
else
#endif
return element()->value();
}
void InputType::applyStep(int count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionState& es)
{
#if ENABLE(WML)
if (isWML())
return;
#endif
StepRange stepRange(createStepRange(anyStepHandling));
void InputType::stepUpFromRenderer(int n)
{
#if ENABLE(WML)
if (isWML())
return;
#endif
void InputType::observeFeatureIfVisible(UseCounter::Feature feature) const
{
#if ENABLE(WML)
if (isWML())
return;
#endif
if (RenderStyle* style = element()->renderStyle()) {
/Source/core/html/PasswordInputType.h
class PasswordInputType FINAL : public BaseTextInputType {
public:
#if ENABLE(WML)
static PassOwnPtr create(WMLInputElement*);
#endif
static PassOwnPtr create(HTMLInputElement*);
private:
#if ENABLE(WML)
PasswordInputType(WMLInputElement* element) : BaseTextInputType(element) { }
#endif
Source/core/html/PasswordInputType.cpp
#if ENABLE(WML)
PassOwnPtr PasswordInputType::create(WMLInputElement* element)
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, element=%x”,element);
return adoptPtr(new PasswordInputType(element));
}
#endif
PassOwnPtr PasswordInputType::create(HTMLInputElement* element)
{
return adoptPtr(new PasswordInputType(element));
}
HTMLElement* PasswordInputType::passwordGeneratorButtonElement() const
{
return m_generatorButton.get();
}
bool PasswordInputType::isPasswordGenerationEnabled() const
{
#if ENABLE(WML)
if (isWML())
return false;
#endif
void PasswordInputType::handleFocusEvent(Element* oldFocusedElement, FocusDirection direction)
{
BaseTextInputType::handleFocusEvent(oldFocusedElement, direction);
#if ENABLE(WML)
if (isWML() && wmlelement()->document()->frame())
wmlelement()->document()->setUseSecureKeyboardEntryWhenActive(true);
else
#endif
if (element()->document()->frame())
element()->document()->setUseSecureKeyboardEntryWhenActive(true);
}
void PasswordInputType::handleBlurEvent()
{
#if ENABLE(WML)
if (isWML() && wmlelement()->document()->frame())
wmlelement()->document()->setUseSecureKeyboardEntryWhenActive(false);
else
#endif
Source/core/html/TextFieldInputType.h
#if ENABLE(WML)
TextFieldInputType(WMLInputElement*);
#endif
Source/core/html/TextFieldInputType.cpp
#if ENABLE(WML)
static inline bool shouldIgnoreRequiredAttribute(const WMLInputElement& input)
{
return false;
}
#endif
static inline bool shouldIgnoreRequiredAttribute(const HTMLInputElement& input)
{
if (!input.document()->settings() || !input.document()->settings()->needsSiteSpecificQuirks())
return false;
if (!equalIgnoringCase(input.document()->url().host(), “egov.uscis.gov”))
return false;
return input.fastGetAttribute(requiredAttr) == “no”;
}
bool TextFieldInputType::valueMissing(const String& value) const
{
#if ENABLE(WML)
if (isWML())
return wmlelement()->isRequired() && value.isEmpty();
#endif
return !shouldIgnoreRequiredAttribute(*element()) && element()->isRequired() && value.isEmpty();
}
bool TextFieldInputType::canSetSuggestedValue()
{
return true;
}
void TextFieldInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
{
#if ENABLE(WML)
if (isWML()) {
RefPtr input(wmlelement());
// We don't ask InputType::setValue to dispatch events because
// TextFieldInputType dispatches events different way from InputType.
InputType::setValue(sanitizedValue, valueChanged, DispatchNoEvent);
if (valueChanged)
updateInnerTextValue();
unsigned max = visibleValue().length();
if (input->focused())
input->setSelectionRange(max, max);
else
input->cacheSelectionInResponseToSetValue(max);
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;
}
case DispatchNoEvent:
break;
}
// FIXME: Why do we do this when eventBehavior == DispatchNoEvent
if (!input->focused() || eventBehavior == DispatchNoEvent)
input->setTextAsOfLastFormControlChangeEvent(sanitizedValue);
} else {
#endif
// FIXME: Why do we do this when eventBehavior == DispatchNoEvent
if (!input->focused() || eventBehavior == DispatchNoEvent)
input->setTextAsOfLastFormControlChangeEvent(sanitizedValue);
#if ENABLE(WML)
}
#endif
}
void TextFieldInputType::handleKeydownEvent(KeyboardEvent* event)
{
#if ENABLE(WML)
if (isWML()) {
if (!wmlelement()->focused())
return;
Frame* frame = wmlelement()->document()->frame();
if (!frame || !frame->editor()->doTextFieldCommandFromEvent(wmlelement(), event))
return;
} else {
#endif
if (!element()->focused())
return;
Frame* frame = element()->document()->frame();
if (!frame || !frame->editor()->doTextFieldCommandFromEvent(element(), event))
return;
#if ENABLE(WML)
}
#endif
event->setDefaultHandled();
}
void TextFieldInputType::handleKeydownEventForSpinButton(KeyboardEvent* event)
{
#if ENABLE(WML)
if (isWML())
return;
#endif
void TextFieldInputType::forwardEvent(Event* event)
{
#if ENABLE(WML)
if (isWML()) {
if (wmlelement()->renderer() && (event->isMouseEvent() || event->isDragEvent() || event->hasInterface(eventNames().interfaceForWheelEvent) || event->type() == eventNames().blurEvent || event->type() == eventNames().focusEvent)) {
RenderTextControlSingleLine* renderTextControl = toRenderTextControlSingleLine(wmlelement()->renderer());
if (event->type() == eventNames().blurEvent) {
if (RenderBox* innerTextRenderer = innerTextElement()->renderBox()) {
if (RenderLayer* innerLayer = innerTextRenderer->layer()) {
IntSize scrollOffset(!renderTextControl->style()->isLeftToRightDirection() ? innerLayer->scrollWidth() : 0, 0);
innerLayer->scrollToOffset(scrollOffset, RenderLayer::ScrollOffsetClamped);
}
}
renderTextControl->capsLockStateMayHaveChanged();
} else if (event->type() == eventNames().focusEvent)
renderTextControl->capsLockStateMayHaveChanged();
// wmlelement()->forwardEvent(event);
}
} else {
#endif
void TextFieldInputType::handleFocusEvent(Element* oldFocusedNode, FocusDirection focusDirection)
{
InputType::handleFocusEvent(oldFocusedNode, focusDirection);
#if ENABLE(WML)
if (isWML())
wmlelement()->beginEditing();
else
#endif
element()->beginEditing();
}
void TextFieldInputType::handleBlurEvent()
{
InputType::handleBlurEvent();
#if ENABLE(WML)
if (isWML())
wmlelement()->endEditing();
else
#endif
element()->endEditing();
}
bool TextFieldInputType::shouldSubmitImplicitly(Event* event)
{
return (event->type() == eventNames().textInputEvent && event->hasInterface(eventNames().interfaceForTextEvent) && static_cast<TextEvent*>(event)->data() == “\n”) || InputType::shouldSubmitImplicitly(event);
}
RenderObject* TextFieldInputType::createRenderer(RenderStyle*) const
{
#if ENABLE(WML)
if (isWML())
return new RenderTextControlSingleLine(wmlelement());
else
#endif
return new RenderTextControlSingleLine(element());
}
bool TextFieldInputType::needsContainer() const
{
#if ENABLE(INPUT_SPEECH)
#if ENABLE(WML)
if (isWML())
return false;
#endif
return element()->isSpeechEnabled();
#else
return false;
#endif
}
bool TextFieldInputType::shouldHaveSpinButton() const
{
#if ENABLE(WML)
if (isWML())
return false;
#endif
Document* document = element()->document();
RefPtr theme = document->page() ? document->page()->theme() : RenderTheme::defaultTheme();
return theme->shouldHaveSpinButton(element());
}
void TextFieldInputType::createShadowSubtree()
{
#if ENABLE(WML)
if (isWML()) {
ASSERT(wmlelement()->shadow());
ASSERT(!m_innerText);
ASSERT(!m_innerBlock);
ASSERT(!m_innerSpinButton);
Document* document = wmlelement()->document();
bool shouldHaveSpinButton = this->shouldHaveSpinButton();
bool createsContainer = shouldHaveSpinButton || needsContainer();
m_innerText = TextControlInnerTextElement::create(document);
if (!createsContainer) {
wmlelement()->userAgentShadowRoot()->appendChild(m_innerText, IGNORE_EXCEPTION);
return;
}
ShadowRoot* shadowRoot = wmlelement()->userAgentShadowRoot();
m_container = TextControlInnerContainer::create(document);
m_container->setPart(AtomicString("-webkit-textfield-decoration-container", AtomicString::ConstructFromLiteral));
shadowRoot->appendChild(m_container, IGNORE_EXCEPTION);
m_innerBlock = TextControlInnerElement::create(document);
m_innerBlock->appendChild(m_innerText, IGNORE_EXCEPTION);
m_container->appendChild(m_innerBlock, IGNORE_EXCEPTION);
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, %x, wmlelement=%x,m_innerText=%x,m_container=%x,m_innerBlock=%x”,this,wmlelement(),m_innerText.get(),m_container.get(),m_innerBlock.get());
} else {
#endif
void TextFieldInputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* event)
{
// Make sure that the text to be inserted will not violate the maxLength.
// We use HTMLInputElement::innerTextValue() instead of
// HTMLInputElement::value() because they can be mismatched by
// sanitizeValue() in HTMLInputElement::subtreeHasChanged() in some cases.
#if ENABLE(WML)
unsigned oldLength;
if (isWML())
oldLength = wmlelement()->innerTextValue().length();
else
oldLength = element()->innerTextValue().length();
#else
unsigned oldLength = element()->innerTextValue().length();
#endif
// selectionLength represents the selection length of this text field to be
// removed by this insertion.
// If the text field has no focus, we don't need to take account of the
// selection length. The selection is the source of text drag-and-drop in
// that case, and nothing in the text field will be removed.
unsigned selectionLength;
#if ENABLE(WML)
if (isWML())
selectionLength = wmlelement()->focused() ? plainText(wmlelement()->document()->frame()->selection()->selection().toNormalizedRange().get()).length() : 0;
else
#endif
selectionLength = element()->focused() ? plainText(element()->document()->frame()->selection()->selection().toNormalizedRange().get()).length() : 0;
ASSERT(oldLength >= selectionLength);
// Selected characters will be removed by the next text event.
unsigned baseLength = oldLength - selectionLength;
unsigned maxLength;
#if ENABLE(WML)
if (isWML())
maxLength = static_cast(isTextType() ? wmlelement()->maxLength() : HTMLInputElement::maximumLength); // maxLength can never be negative.
else
#endif
maxLength = static_cast(isTextType() ? element()->maxLength() : HTMLInputElement::maximumLength); // maxLength can never be negative.
void TextFieldInputType::updatePlaceholderText()
{
if (!supportsPlaceholder())
return;
#if ENABLE(WML)
if (isWML()) {
if (m_placeholder) {
m_placeholder->parentNode()->removeChild(m_placeholder.get(), ASSERT_NO_EXCEPTION);
m_placeholder.clear();
}
return;
}
#endif
void TextFieldInputType::attach()
{
InputType::attach();
// If container exists, the container should not have any content data.
ASSERT(!m_container || !m_container->renderStyle() || !m_container->renderStyle()->hasContent());
#if ENABLE(WML)
if (isWML())
wmlelement()->fixPlaceholderRenderer(m_placeholder.get(), m_container ? m_container.get() : m_innerText.get());
else
#endif
element()->fixPlaceholderRenderer(m_placeholder.get(), m_container ? m_container.get() : m_innerText.get());
}
bool TextFieldInputType::appendFormData(FormDataList& list, bool multipart) const
{
InputType::appendFormData(list, multipart);
#if ENABLE(WML)
if (isWML())
return true;
#endif
void TextFieldInputType::subtreeHasChanged()
{
bool wasChanged;
#if ENABLE(WML)
if (isWML()) {
ASSERT(wmlelement()->renderer());
wasChanged = wmlelement()->wasChangedSinceLastFormControlChangeEvent();
wmlelement()->setChangedSinceLastFormControlChangeEvent(true);
// We don't need to call sanitizeUserInputValue() function here because
// HTMLInputElement::handleBeforeTextInsertedEvent() has already called
// sanitizeUserInputValue().
// sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent.
wmlelement()->setValueFromRenderer(sanitizeValue(convertFromVisibleValue(element()->innerTextValue())));
wmlelement()->updatePlaceholderVisibility(false);
// Recalc for :invalid change.
wmlelement()->setNeedsStyleRecalc();
} else {
#endif
void TextFieldInputType::didSetValueByUserEdit(ValueChangeState state)
{
#if ENABLE(WML)
if (isWML()) {
if (!wmlelement()->focused())
return;
if (Frame* frame = wmlelement()->document()->frame())
frame->editor()->textDidChangeInTextField(wmlelement());
} else {
#endif
void TextFieldInputType::updateInnerTextValue()
{
#if ENABLE(WML)
if (isWML()) {
if (!wmlelement()->suggestedValue().isNull()) {
wmlelement()->setInnerTextValue(wmlelement()->suggestedValue());
wmlelement()->updatePlaceholderVisibility(false);
} else if (!wmlelement()->formControlValueMatchesRenderer()) {
// Update the renderer value if the formControlValueMatchesRenderer() flag is false.
// It protects an unacceptable renderer value from being overwritten with the DOM value.
wmlelement()->setInnerTextValue(visibleValue());
wmlelement()->updatePlaceholderVisibility(false);
}
} else {
#endif
Source/core/html/TextInputType.h
public:
#if ENABLE(WML)
static PassOwnPtr create(WMLInputElement*);
#endif
static PassOwnPtr create(HTMLInputElement*);
private:
#if ENABLE(WML)
TextInputType(WMLInputElement* element) : BaseTextInputType(element) { }
#endif
Source/core/html/TextInputType.cpp
if ENABLE(WML)
PassOwnPtr TextInputType::create(WMLInputElement* element)
{
return adoptPtr(new TextInputType(element));
}
#endif
PassOwnPtr TextInputType::create(HTMLInputElement* element)
{
return adoptPtr(new TextInputType(element));
}
void TextInputType::attach()
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, %x, element=%x”,this, element());
TextFieldInputType::attach();
#if ENABLE(WML)
if (isWML())
return;
#endif
Source/core/rendering/RenderBox.h
virtual const char* renderName() const { return “renderbox”;}
Source/core/rendering/RenderBox.cpp
bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const
if (logicalWidth.type() == Auto && !isStretchingColumnFlexItem(this) && node() && (node()->hasTagName(inputTag)
#if ENABLE(WML)
|| node()->hasTagName(WMLNames::inputTag)
#endif
|| node()->hasTagName(selectTag) || node()->hasTagName(buttonTag) || isHTMLTextAreaElement(node()) || node()->hasTagName(legendTag)))
return true;
Source/core/rendering/RenderTextControl.h
class HTMLTextFormControlElement;
class WMLFormControlElement;
class RenderTextControl : public RenderBlock {
public:
virtual ~RenderTextControl();
HTMLTextFormControlElement* textFormControlElement() const;
WMLFormControlElement* wmlFormControlElement() const;
virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;
protected:
#if ENABLE(WML)
RenderTextControl(ContainerNode*);
#else
RenderTextControl(HTMLTextFormControlElement*);
#endif
ource/core/rendering/RenderTextControl.cpp
#if ENABLE(WML)
RenderTextControl::RenderTextControl(ContainerNode* element)
#else
RenderTextControl(HTMLTextFormControlElement*)
#endif
WMLFormControlElement* RenderTextControl::wmlFormControlElement() const
{
return toWMLFormControlElement(node());
}
HTMLElement* RenderTextControl::innerTextElement() const
{
#if ENABLE(WML)
if (node()->isWMLElement())
return wmlFormControlElement()->innerTextElement();
else
#endif
void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
#if ENABLE(WML)
if (node()->isWMLElement())
wmlFormControlElement()->updatePlaceholderVisibility(false);
else
#endif
void RenderTextControl::adjustInnerTextStyle(RenderStyle* textBlockStyle) const
{
// The inner block, if present, always has its direction set to LTR,
// so we need to inherit the direction and unicode-bidi style from the element.
textBlockStyle->setDirection(style()->direction());
textBlockStyle->setUnicodeBidi(style()->unicodeBidi());
#if ENABLE(WML)
if (node()->isWMLElement())
textBlockStyle->setUserModify(READ_WRITE_PLAINTEXT_ONLY);
else
#endif
void RenderTextControl::updateFromElement()
{
#if ENABLE(WML)
if (node()->isWMLElement()) {
Element* innerText = innerTextElement();
if (innerText && innerText->renderer())
innerText->renderer()->style()->setUserModify(READ_WRITE_PLAINTEXT_ONLY);
} else {
#endif
Element* innerText = innerTextElement();
if (innerText && innerText->renderer())
updateUserModifyProperty(textFormControlElement(), innerText->renderer()->style());
#if ENABLE(WML)
}
#endif
RenderObject* RenderTextControl::layoutSpecialExcludedChild(bool relayoutChildren)
{
HTMLElement* placeholder;
if (node()->isWMLElement())
placeholder = toWMLInputElement(node())->placeholderElement();
else
placeholder = toHTMLTextFormControlElement(node())->placeholderElement();
Source/core/rendering/RenderTextControlSingleLine.h
public:
#if ENABLE(WML)
RenderTextControlSingleLine(ContainerNode*);
#else
RenderTextControlSingleLine(HTMLInputElement*);
#endif
WMLInputElement* wmlinputElement() const;
inline HTMLElement* RenderTextControlSingleLine::containerElement() const
{
#if ENABLE(WML)
if (node()->isWMLElement())
return wmlinputElement()->containerElement();
else
#endif
return inputElement()->containerElement();
}
inline HTMLElement* RenderTextControlSingleLine::innerBlockElement() const
{
#if ENABLE(WML)
if (node()->isWMLElement())
return wmlinputElement()->innerBlockElement();
else
#endif
Source/core/rendering/RenderTextControlSingleLine.cpp
inline HTMLElement* RenderTextControlSingleLine::innerSpinButtonElement() const
{
#if ENABLE(WML)
if (node()->isWMLElement())
return wmlinputElement()->innerSpinButtonElement();
else
#endif
HTMLElement* placeholderElement;
#if ENABLE(WML)
if (node()->isWMLElement())
placeholderElement = wmlinputElement()->placeholderElement();
else
#endif
placeholderElement = inputElement()->placeholderElement();
void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
m_desiredInnerTextLogicalHeight = -1;
RenderTextControl::styleDidChange(diff, oldStyle);
// We may have set the width and the height in the old style in layout().
// Reset them now to avoid getting a spurious layout hint.
HTMLElement* innerBlock = innerBlockElement();
if (RenderObject* innerBlockRenderer = innerBlock ? innerBlock->renderer() : 0) {
innerBlockRenderer->style()->setHeight(Length());
innerBlockRenderer->style()->setWidth(Length());
}
HTMLElement* container = containerElement();
if (RenderObject* containerRenderer = container ? container->renderer() : 0) {
containerRenderer->style()->setHeight(Length());
containerRenderer->style()->setWidth(Length());
}
RenderObject* innerTextRenderer = innerTextElement()->renderer();
if (innerTextRenderer && diff == StyleDifferenceLayout)
innerTextRenderer->setNeedsLayout(MarkContainingBlockChain);
#if ENABLE(WML)
if (node()->isWMLElement()) {
if (HTMLElement* placeholder = wmlinputElement()->placeholderElement())
placeholder->setInlineStyleProperty(CSSPropertyTextOverflow, textShouldBeTruncated() ? CSSValueEllipsis : CSSValueClip);
} else {
#endif
void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
{
if (Frame* frame = document()->frame())
#if ENABLE(WML)
if (node()->isWMLElement())
shouldDrawCapsLockIndicator = wmlinputElement()->isPasswordField() && frame->selection()->isFocusedAndActive() && document()->focusedElement() == node() && PlatformKeyboardEvent::currentCapsLockState();
else
#endif
LayoutUnit RenderTextControlSingleLine::preferredContentLogicalWidth(float charWidth) const
{
int factor;
bool includesDecoration;
#if ENABLE(WML)
if (node()->isWMLElement())
includesDecoration = wmlinputElement()->sizeShouldIncludeDecoration(factor);
else
#endif
WMLInputElement* RenderTextControlSingleLine::wmlinputElement() const
{
return toWMLInputElement(node());
}
}
Source/core/wml/WMLElement.h
virtual bool rendererIsNeeded(const NodeRenderingContext& context);
virtual RenderObject* createRenderer(RenderStyle*);
virtual void insertedIntoDocument() {}
virtual void removedFromDocument() {}
void addCSSProperty(Attribute* attribute, int id, const String &value)
{/*
if (!attribute->decl())
createMappedDecl(attribute);
attribute->decl()->setProperty(id, value, false);*/
}
void addCSSLength(Attribute*, int id, const String& value) {}
void addCSSProperty(Attribute*, int id, int value) {}
virtual bool hasCustomFocusLogic() const;
virtual bool supportsFocus() const;
String contentEditable() const;
void setContentEditable(const String&, ExceptionState&);
virtual bool draggable() const;
void setDraggable(bool);
bool spellcheck() const;
void setSpellcheck(bool);
void click();
virtual void accessKeyAction(bool sendMouseEvents);
virtual short tabIndex() const;
void setTabIndex(int);
protected:
WMLElement(const QualifiedName& tagName, Document*);
virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
// Helper function for derived classes
String parseValueSubstitutingVariableReferences(const AtomicString&, WMLErrorCode defaultErrorCode = WMLErrorInvalidVariableReference) const;
String parseValueForbiddingVariableReferences(const AtomicString&) const;
void addWMLLengthToStyle(MutableStylePropertySet*, CSSPropertyID, const String& value);
void applyAlignmentAttributeToStyle(const AtomicString&, MutableStylePropertySet*);
virtual String nodeName() const OVERRIDE FINAL;
private:
AtomicString eventNameForAttributeName(const QualifiedName& attrName) const;
};
inline WMLElement* toWMLElement(Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isWMLElement());
return static_cast<WMLElement*>(node);
}
inline const WMLElement* toWMLElement(const Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isWMLElement());
return static_cast<const WMLElement*>(node);
}
Source/core/wml/WMLElement.cpp
String WMLElement::nodeName() const
{
// FIXME: Would be nice to have an atomicstring lookup based off uppercase
// chars that does not have to copy the string on a hit in the hash.
// FIXME: We should have a way to detect XHTML elements and replace the hasPrefix() check with it.
if (document()->isWMLDocument() && !tagQName().hasPrefix())
return tagQName().localNameUpper();
return Element::nodeName();
}
void WMLElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
{
if (isIdAttributeName(name)
|| name == HTMLNames::classAttr
|| name == HTMLNames::styleAttr)
Element::collectStyleForPresentationAttribute(name, value, style);
if (name == HTMLNames::alignAttr) {
if (equalIgnoringCase(value, "middle"))
addPropertyToPresentationAttributeStyle(style, CSSPropertyTextAlign, CSSValueCenter);
else
addPropertyToPresentationAttributeStyle(style, CSSPropertyTextAlign, value);
} else if (name == HTMLNames::tabindexAttr) {
String indexstring = value;
int tabindex = 0;
if (parseHTMLInteger(indexstring, tabindex)) {
// 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 (name == HTMLNames::contenteditableAttr) {
if (value.isEmpty() || equalIgnoringCase(value, “true”)) {
addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadWrite);
addPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord);
addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
} else if (equalIgnoringCase(value, “plaintext-only”)) {
addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly);
addPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord);
addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
} else if (equalIgnoringCase(value, “false”))
addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadOnly);
} else
Element::collectStyleForPresentationAttribute(name, value, style);
}
AtomicString WMLElement::eventNameForAttributeName(const QualifiedName& attrName) const
{
return AtomicString();
}
void WMLElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
if (isIdAttributeName(name)
|| name == HTMLNames::classAttr
|| name == HTMLNames::styleAttr)
return Element::parseAttribute(name, value);
if (name == HTMLNames::tabindexAttr) {
String indexstring = value;
int tabindex = 0;
if (parseHTMLInteger(indexstring, tabindex)) {
// 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()))));
}
}
}
void WMLElement::applyAlignmentAttributeToStyle(const AtomicString& alignment, MutableStylePropertySet* style)
{
// Vertical alignment with respect to the current baseline of the text
// right or left means floating images.
CSSValueID floatValue = CSSValueInvalid;
CSSValueID verticalAlignValue = CSSValueInvalid;
if (equalIgnoringCase(alignment, "absmiddle"))
verticalAlignValue = CSSValueMiddle;
else if (equalIgnoringCase(alignment, "absbottom"))
verticalAlignValue = CSSValueBottom;
else if (equalIgnoringCase(alignment, "left")) {
floatValue = CSSValueLeft;
verticalAlignValue = CSSValueTop;
} else if (equalIgnoringCase(alignment, "right")) {
floatValue = CSSValueRight;
verticalAlignValue = CSSValueTop;
} else if (equalIgnoringCase(alignment, "top"))
verticalAlignValue = CSSValueTop;
else if (equalIgnoringCase(alignment, "middle"))
verticalAlignValue = CSSValueWebkitBaselineMiddle;
else if (equalIgnoringCase(alignment, "center"))
verticalAlignValue = CSSValueMiddle;
else if (equalIgnoringCase(alignment, "bottom"))
verticalAlignValue = CSSValueBaseline;
else if (equalIgnoringCase(alignment, "texttop"))
verticalAlignValue = CSSValueTextTop;
if (floatValue != CSSValueInvalid)
addPropertyToPresentationAttributeStyle(style, CSSPropertyFloat, floatValue);
if (verticalAlignValue != CSSValueInvalid)
addPropertyToPresentationAttributeStyle(style, CSSPropertyVerticalAlign, verticalAlignValue);
}
bool WMLElement::hasCustomFocusLogic() const
{
return false;
}
bool WMLElement::supportsFocus() const
{
// FIXME: supportsFocus() can be called when layout is not up to date.
// Logic that deals with the renderer should be moved to rendererIsFocusable().
// But supportsFocus must return true when the element is editable, or else
// it won’t be focusable. Furthermore, supportsFocus cannot just return true
// always or else tabIndex() will change for all HTML elements.
return Element::supportsFocus() || (rendererIsEditable() && parentNode() && !parentNode()->rendererIsEditable());
}
String WMLElement::contentEditable() const
{
const AtomicString& value = fastGetAttribute(HTMLNames::contenteditableAttr);
if (value.isNull())
return "inherit";
if (value.isEmpty() || equalIgnoringCase(value, "true"))
return "true";
if (equalIgnoringCase(value, "false"))
return "false";
if (equalIgnoringCase(value, "plaintext-only"))
return "plaintext-only";
return "inherit";
}
void WMLElement::setContentEditable(const String& enabled, ExceptionState& es)
{
if (equalIgnoringCase(enabled, “true”))
setAttribute(HTMLNames::contenteditableAttr, “true”);
else if (equalIgnoringCase(enabled, “false”))
setAttribute(HTMLNames::contenteditableAttr, “false”);
else if (equalIgnoringCase(enabled, “plaintext-only”))
setAttribute(HTMLNames::contenteditableAttr, “plaintext-only”);
else if (equalIgnoringCase(enabled, “inherit”))
removeAttribute(HTMLNames::contenteditableAttr);
else
es.throwDOMException(SyntaxError);
}
bool WMLElement::draggable() const
{
return equalIgnoringCase(getAttribute(HTMLNames::draggableAttr), “true”);
}
void WMLElement::setDraggable(bool value)
{
setAttribute(HTMLNames::draggableAttr, value ? “true” : “false”);
}
bool WMLElement::spellcheck() const
{
return isSpellCheckingEnabled();
}
void WMLElement::setSpellcheck(bool enable)
{
setAttribute(HTMLNames::spellcheckAttr, enable ? “true” : “false”);
}
void WMLElement::click()
{
dispatchSimulatedClick(0, SendNoEvents, DoNotShowPressedLook);
}
void WMLElement::accessKeyAction(bool sendMouseEvents)
{
dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
}
short WMLElement::tabIndex() const
{
if (supportsFocus())
return Element::tabIndex();
return -1;
}
void WMLElement::setTabIndex(int value)
{
setAttribute(HTMLNames::tabindexAttr, String::number(value));
}
bool WMLElement::rendererIsNeeded(const NodeRenderingContext& context)
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , " ");
/android::CallStack stack;
stack.update();
stack.dump(“Neo callstack”);/
return document()->documentElement() == this || Element::rendererIsNeeded(context);
}
RenderObject* WMLElement::createRenderer(RenderStyle* style)
{
return RenderObject::createObject(this, style);
}
void WMLElement::addWMLLengthToStyle(MutableStylePropertySet* style, CSSPropertyID 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()) {
addPropertyToPresentationAttributeStyle(style, propertyID, v->substring(0, l));
return;
}
}
addPropertyToPresentationAttributeStyle(style, propertyID, value);
}
Source/core/wml/WMLFormControlElement.h
class ExceptionState;
class Position;
class RenderTextControl;
class VisiblePosition;
class WMLFormControlElement : public WMLElement {
public:
static PassRefPtr create(const QualifiedName&, Document*);
enum NeedsToCheckDirtyFlag {CheckDirtyFlag, IgnoreDirtyFlag};
virtual ~WMLFormControlElement();
virtual bool isFormControlElement() const { return true; }
virtual bool isReadOnlyFormControl() const { return false; }
virtual bool isTextFormControl() const { return true; }
virtual bool formControlValueMatchesRenderer() const { return m_valueMatchesRenderer; }
virtual void setFormControlValueMatchesRenderer(bool b = true) { m_valueMatchesRenderer = b; }
void attach(const AttachContext& context);
virtual bool supportsFocus() const;
virtual bool isFocusable() const;
// virtual void attach();
virtual void recalcStyle(StyleChange);
void setTextAsOfLastFormControlChangeEvent(const String& text) { m_textAsOfLastFormControlChangeEvent = text; }
void forwardEvent(Event*);
virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
// The derived class should return true if placeholder processing is needed.
virtual bool supportsPlaceholder() const {}
String strippedPlaceholder() const;
bool placeholderShouldBeVisible() const;
virtual HTMLElement* placeholderElement() const {}
void updatePlaceholderVisibility(bool);
static void fixPlaceholderRenderer(HTMLElement* placeholder, HTMLElement* siblingElement);
VisiblePosition visiblePositionForIndex(int) const;
int indexForVisiblePosition(const VisiblePosition&) const;
int selectionStart() const;
int selectionEnd() const;
const AtomicString& selectionDirection() const;
void setSelectionStart(int);
void setSelectionEnd(int);
void setSelectionDirection(const String&);
void select();
virtual void setRangeText(const String& replacement, ExceptionState&);
virtual void setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState&);
void setSelectionRange(int start, int end, const String& direction);
void setSelectionRange(int start, int end, TextFieldSelectionDirection = SelectionHasNoDirection);
PassRefPtr<Range> selection() const;
String selectedText() const;
virtual void dispatchFormControlChangeEvent();
virtual String value() const {};
virtual HTMLElement* innerTextElement() const { }
void selectionChanged(bool userTriggered);
bool lastChangeWasUserEdit() const;
void setInnerTextValue(const String&);
String innerTextValue() const;
String directionForFormData() const;
virtual void dispatchFormControlInputEvent();
void setNeedsValidityCheck();
void notifyFormStateChanged();
bool isDisabledOrReadOnly() const { return false; }
protected:
WMLFormControlElement(const QualifiedName&, Document*);
bool isPlaceholderEmpty() const;
virtual void updatePlaceholderText() { }
virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
void cacheSelection(int start, int end, TextFieldSelectionDirection direction)
{
m_cachedSelectionStart = start;
m_cachedSelectionEnd = end;
m_cachedSelectionDirection = direction;
}
void restoreCachedSelection();
bool hasCachedSelection() const { return m_cachedSelectionStart >= 0; }
virtual void defaultEventHandler(Event*);
virtual void subtreeHasChanged() {}
void setLastChangeWasNotUserEdit() { m_lastChangeWasUserEdit = false; }
String valueWithHardLineBreaks() const;
private:
int computeSelectionStart() const;
int computeSelectionEnd() const;
TextFieldSelectionDirection computeSelectionDirection() const;
// FIXME: Author shadows should be allowed
// https://bugs.webkit.org/show_bug.cgi?id=92608
virtual bool areAuthorShadowsAllowed() const OVERRIDE { return false; }
virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection) OVERRIDE;
virtual void dispatchBlurEvent(Element* newFocusedElement) OVERRIDE;
// Returns true if user-editable value is empty. Used to check placeholder visibility.
virtual bool isEmptyValue() const {}
// Returns true if suggested value is empty. Used to check placeholder visibility.
virtual bool isEmptySuggestedValue() const { return true; }
// Called in dispatchFocusEvent(), after placeholder process, before calling parent's dispatchFocusEvent().
virtual void handleFocusEvent(Element* /* oldFocusedNode */, FocusDirection) { }
// Called in dispatchBlurEvent(), after placeholder process, before calling parent's dispatchBlurEvent().
virtual void handleBlurEvent() { }
String m_textAsOfLastFormControlChangeEvent;
bool m_lastChangeWasUserEdit;
int m_cachedSelectionStart;
int m_cachedSelectionEnd;
TextFieldSelectionDirection m_cachedSelectionDirection;
bool m_valueMatchesRenderer;
};
inline bool isWMLFormControlElement(const Node* node)
{
return node->isElementNode() && toElement(node)->isTextFormControl();
}
inline WMLFormControlElement* toWMLFormControlElement(Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || isWMLFormControlElement(node));
return static_cast<WMLFormControlElement*>(node);
}
WMLFormControlElement* enclosingFormControl(const Position&);
/Fix me, Neo/
}
Source/core/wml/WMLFormControlElement.cpp
WMLFormControlElement::WMLFormControlElement(const QualifiedName& tagName, Document* document)
: WMLElement(tagName, document)
, m_valueMatchesRenderer(false)
, m_lastChangeWasUserEdit(false)
, m_cachedSelectionStart(-1)
, m_cachedSelectionEnd(-1)
, m_cachedSelectionDirection(SelectionHasNoDirection)
void WMLFormControlElement::attach(const AttachContext& context)
{
ASSERT(!attached());
PostAttachCallbackDisabler disabler(this);
WMLElement::attach(context);
if (renderer())
renderer()->updateFromElement();
Node::InsertionNotificationRequest WMLFormControlElement::insertedInto(ContainerNode* insertionPoint)
{
WMLElement::insertedInto(insertionPoint);
if (!insertionPoint->inDocument())
return InsertionDone;
String initialValue = value();
setTextAsOfLastFormControlChangeEvent(initialValue.isNull() ? emptyString() : initialValue);
return InsertionDone;
}
void WMLFormControlElement::dispatchFocusEvent(Element* oldFocusedElement, FocusDirection direction)
{
handleFocusEvent(oldFocusedElement, direction);
WMLElement::dispatchFocusEvent(oldFocusedElement, direction);
}
void WMLFormControlElement::dispatchBlurEvent(Element* newFocusedElement)
{
handleBlurEvent();
WMLElement::dispatchBlurEvent(newFocusedElement);
}
void WMLFormControlElement::defaultEventHandler(Event* event)
{
if (event->type() == eventNames().webkitEditableContentChangedEvent && renderer() && renderer()->isTextControl()) {
m_lastChangeWasUserEdit = true;
subtreeHasChanged();
return;
}
WMLFormControlElement::defaultEventHandler(event);
}
void WMLFormControlElement::forwardEvent(Event* event)
{
if (event->type() == eventNames().blurEvent || event->type() == eventNames().focusEvent)
return;
innerTextElement()->defaultEventHandler(event);
}
String WMLFormControlElement::strippedPlaceholder() const
{
// According to the HTML5 specification, we need to remove CR and LF from
// the attribute value.
const AtomicString& attributeValue = fastGetAttribute(HTMLNames::placeholderAttr);
if (!attributeValue.contains(newlineCharacter) && !attributeValue.contains(carriageReturn))
return attributeValue;
StringBuilder stripped;
unsigned length = attributeValue.length();
stripped.reserveCapacity(length);
for (unsigned i = 0; i < length; ++i) {
UChar character = attributeValue[i];
if (character == newlineCharacter || character == carriageReturn)
continue;
stripped.append(character);
}
return stripped.toString();
}
static bool isNotLineBreak(UChar ch) { return ch != newlineCharacter && ch != carriageReturn; }
bool WMLFormControlElement::isPlaceholderEmpty() const
{
return true;
// const AtomicString& attributeValue = fastGetAttribute(placeholderAttr);
// return attributeValue.string().find(isNotLineBreak) == notFound;
}
bool WMLFormControlElement::placeholderShouldBeVisible() const
{
return supportsPlaceholder()
&& isEmptyValue()
&& isEmptySuggestedValue()
&& !isPlaceholderEmpty()
&& (document()->focusedElement() != this || (renderer() && renderer()->theme()->shouldShowPlaceholderWhenFocused()))
&& (!renderer() || renderer()->style()->visibility() == VISIBLE);
}
void WMLFormControlElement::updatePlaceholderVisibility(bool placeholderValueChanged)
{
if (!supportsPlaceholder())
return;
if (!placeholderElement() || placeholderValueChanged)
updatePlaceholderText();
HTMLElement* placeholder = placeholderElement();
if (!placeholder)
return;
placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShouldBeVisible() ? CSSValueVisible : CSSValueHidden);
}
void WMLFormControlElement::fixPlaceholderRenderer(HTMLElement* placeholder, HTMLElement* siblingElement)
{
// FIXME: We should change the order of DOM nodes. But it makes an assertion
// failure in editing code.
if (!placeholder || !placeholder->renderer())
return;
RenderObject* placeholderRenderer = placeholder->renderer();
RenderObject* siblingRenderer = siblingElement->renderer();
if (!siblingRenderer)
return;
if (placeholderRenderer->nextSibling() == siblingRenderer)
return;
RenderObject* parentRenderer = placeholderRenderer->parent();
ASSERT(siblingRenderer->parent() == parentRenderer);
parentRenderer->removeChild(placeholderRenderer);
parentRenderer->addChild(placeholderRenderer, siblingRenderer);
}
void WMLFormControlElement::setSelectionStart(int start)
{
setSelectionRange(start, max(start, selectionEnd()), selectionDirection());
}
void WMLFormControlElement::setSelectionEnd(int end)
{
setSelectionRange(min(end, selectionStart()), end, selectionDirection());
}
void WMLFormControlElement::setSelectionDirection(const String& direction)
{
setSelectionRange(selectionStart(), selectionEnd(), direction);
}
void WMLFormControlElement::select()
{
setSelectionRange(0, numeric_limits::max(), SelectionHasNoDirection);
}
String WMLFormControlElement::selectedText() const
{
if (!isTextFormControl())
return String();
return value().substring(selectionStart(), selectionEnd() - selectionStart());
}
void WMLFormControlElement::dispatchFormControlChangeEvent()
{
if (m_textAsOfLastFormControlChangeEvent != value()) {
WMLElement::dispatchChangeEvent();
setTextAsOfLastFormControlChangeEvent(value());
}
setChangedSinceLastFormControlChangeEvent(false);
}
static inline bool hasVisibleTextArea(RenderTextControl* textControl, HTMLElement* innerText)
{
ASSERT(textControl);
return textControl->style()->visibility() != HIDDEN && innerText && innerText->renderer() && innerText->renderBox()->height();
}
void WMLFormControlElement::setRangeText(const String& replacement, ExceptionState& es)
{
setRangeText(replacement, selectionStart(), selectionEnd(), String(), es);
}
void WMLFormControlElement::setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState& es)
{
if (start > end) {
es.throwDOMException(IndexSizeError);
return;
}
String text = innerTextValue();
unsigned textLength = text.length();
unsigned replacementLength = replacement.length();
unsigned newSelectionStart = selectionStart();
unsigned newSelectionEnd = selectionEnd();
start = std::min(start, textLength);
end = std::min(end, textLength);
if (start < end)
text.replace(start, end - start, replacement);
else
text.insert(replacement, start);
setInnerTextValue(text);
// FIXME: What should happen to the value (as in value()) if there's no renderer?
if (!renderer())
return;
subtreeHasChanged();
if (equalIgnoringCase(selectionMode, "select")) {
newSelectionStart = start;
newSelectionEnd = start + replacementLength;
} else if (equalIgnoringCase(selectionMode, "start"))
newSelectionStart = newSelectionEnd = start;
else if (equalIgnoringCase(selectionMode, "end"))
newSelectionStart = newSelectionEnd = start + replacementLength;
else {
// Default is "preserve".
long delta = replacementLength - (end - start);
if (newSelectionStart > end)
newSelectionStart += delta;
else if (newSelectionStart > start)
newSelectionStart = start;
if (newSelectionEnd > end)
newSelectionEnd += delta;
else if (newSelectionEnd > start)
newSelectionEnd = start + replacementLength;
}
setSelectionRange(newSelectionStart, newSelectionEnd, SelectionHasNoDirection);
}
void WMLFormControlElement::setSelectionRange(int start, int end, const String& directionString)
{
TextFieldSelectionDirection direction = SelectionHasNoDirection;
if (directionString == “forward”)
direction = SelectionHasForwardDirection;
else if (directionString == “backward”)
direction = SelectionHasBackwardDirection;
return setSelectionRange(start, end, direction);
}
void WMLFormControlElement::setSelectionRange(int start, int end, TextFieldSelectionDirection direction)
{
document()->updateLayoutIgnorePendingStylesheets();
if (!renderer() || !renderer()->isTextControl())
return;
end = max(end, 0);
start = min(max(start, 0), end);
if (!hasVisibleTextArea(toRenderTextControl(renderer()), innerTextElement())) {
cacheSelection(start, end, SelectionHasNoDirection);
return;
}
VisiblePosition startPosition = visiblePositionForIndex(start);
VisiblePosition endPosition;
if (start == end)
endPosition = startPosition;
else
endPosition = visiblePositionForIndex(end);
// startPosition and endPosition can be null position for example when
// "-webkit-user-select: none" style attribute is specified.
if (startPosition.isNotNull() && endPosition.isNotNull()) {
ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() == this
&& endPosition.deepEquivalent().deprecatedNode()->shadowHost() == this);
}
VisibleSelection newSelection;
if (direction == SelectionHasBackwardDirection)
newSelection = VisibleSelection(endPosition, startPosition);
else
newSelection = VisibleSelection(startPosition, endPosition);
newSelection.setIsDirectional(direction != SelectionHasNoDirection);
if (Frame* frame = document()->frame())
frame->selection()->setSelection(newSelection);
}
VisiblePosition WMLFormControlElement::visiblePositionForIndex(int index) const
{
if (index <= 0)
return VisiblePosition(firstPositionInNode(innerTextElement()), DOWNSTREAM);
RefPtr range = Range::create(document());
range->selectNodeContents(innerTextElement(), ASSERT_NO_EXCEPTION);
CharacterIterator it(range.get());
it.advance(index - 1);
return VisiblePosition(it.range()->endPosition(), UPSTREAM);
}
int WMLFormControlElement::indexForVisiblePosition(const VisiblePosition& pos) const
{
Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent();
if (enclosingFormControl(indexPosition) != this)
return 0;
RefPtr range = Range::create(indexPosition.document());
range->setStart(innerTextElement(), 0, ASSERT_NO_EXCEPTION);
range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainerNode(), ASSERT_NO_EXCEPTION);
return TextIterator::rangeLength(range.get());
}
int WMLFormControlElement::selectionStart() const
{
if (!isTextFormControl())
return 0;
if (document()->focusedElement() != this && hasCachedSelection())
return m_cachedSelectionStart;
return computeSelectionStart();
}
int WMLFormControlElement::computeSelectionStart() const
{
ASSERT(isTextFormControl());
Frame* frame = document()->frame();
if (!frame)
return 0;
return indexForVisiblePosition(frame->selection()->start());
}
int WMLFormControlElement::selectionEnd() const
{
if (!isTextFormControl())
return 0;
if (document()->focusedElement() != this && hasCachedSelection())
return m_cachedSelectionEnd;
return computeSelectionEnd();
}
int WMLFormControlElement::computeSelectionEnd() const
{
ASSERT(isTextFormControl());
Frame* frame = document()->frame();
if (!frame)
return 0;
return indexForVisiblePosition(frame->selection()->end());
}
static const AtomicString& directionString(TextFieldSelectionDirection direction)
{
DEFINE_STATIC_LOCAL(const AtomicString, none, (“none”, AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, forward, (“forward”, AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, backward, (“backward”, AtomicString::ConstructFromLiteral));
switch (direction) {
case SelectionHasNoDirection:
return none;
case SelectionHasForwardDirection:
return forward;
case SelectionHasBackwardDirection:
return backward;
}
ASSERT_NOT_REACHED();
return none;
}
const AtomicString& WMLFormControlElement::selectionDirection() const
{
if (!isTextFormControl())
return directionString(SelectionHasNoDirection);
if (document()->focusedElement() != this && hasCachedSelection())
return directionString(m_cachedSelectionDirection);
return directionString(computeSelectionDirection());
}
TextFieldSelectionDirection WMLFormControlElement::computeSelectionDirection() const
{
ASSERT(isTextFormControl());
Frame* frame = document()->frame();
if (!frame)
return SelectionHasNoDirection;
const VisibleSelection& selection = frame->selection()->selection();
return selection.isDirectional() ? (selection.isBaseFirst() ? SelectionHasForwardDirection : SelectionHasBackwardDirection) : SelectionHasNoDirection;
}
static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& containerNode, int& offsetInContainer)
{
if (node->isTextNode()) {
containerNode = node;
offsetInContainer = offset;
} else {
containerNode = node->parentNode();
offsetInContainer = node->nodeIndex() + offset;
}
}
PassRefPtr WMLFormControlElement::selection() const
{
if (!renderer() || !isTextFormControl() || !hasCachedSelection())
return 0;
int start = m_cachedSelectionStart;
int end = m_cachedSelectionEnd;
ASSERT(start <= end);
HTMLElement* innerText = innerTextElement();
if (!innerText)
return 0;
if (!innerText->firstChild())
return Range::create(document(), innerText, 0, innerText, 0);
int offset = 0;
Node* startNode = 0;
Node* endNode = 0;
for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(node, innerText)) {
ASSERT(!node->firstChild());
ASSERT(node->isTextNode() || node->hasTagName(WMLNames::brTag));
int length = node->isTextNode() ? lastOffsetInNode(node) : 1;
if (offset <= start && start <= offset + length)
setContainerAndOffsetForRange(node, start - offset, startNode, start);
if (offset <= end && end <= offset + length) {
setContainerAndOffsetForRange(node, end - offset, endNode, end);
break;
}
offset += length;
}
if (!startNode || !endNode)
return 0;
return Range::create(document(), startNode, start, endNode, end);
}
void WMLFormControlElement::restoreCachedSelection()
{
setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSelectionDirection);
}
void WMLFormControlElement::selectionChanged(bool userTriggered)
{
if (!renderer() || !isTextFormControl())
return;
// selectionStart() or selectionEnd() will return cached selection when this node doesn't have focus
cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSelectionDirection());
if (Frame* frame = document()->frame()) {
if (frame->selection()->isRange() && userTriggered)
dispatchEvent(Event::create(eventNames().selectEvent, true, false));
}
}
void WMLFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
if (name == HTMLNames::placeholderAttr) {
updatePlaceholderVisibility(true);
UseCounter::count(document(), UseCounter::PlaceholderAttribute);
}
WMLElement::parseAttribute(name, value);
}
bool WMLFormControlElement::lastChangeWasUserEdit() const
{
if (!isTextFormControl())
return false;
return m_lastChangeWasUserEdit;
}
void WMLFormControlElement::setInnerTextValue(const String& value)
{
if (!isTextFormControl())
return;
bool textIsChanged = value != innerTextValue();
if (textIsChanged || !innerTextElement()->hasChildNodes()) {
innerTextElement()->setInnerText(value, ASSERT_NO_EXCEPTION);
if (value.endsWith('\n') || value.endsWith('\r'))
innerTextElement()->appendChild(WMLBRElement::create(WMLNames::brTag, document()), ASSERT_NO_EXCEPTION, AttachLazily);
}
setFormControlValueMatchesRenderer(true);
}
static String finishText(StringBuilder& result)
{
// Remove one trailing newline; there’s always one that’s collapsed out by rendering.
size_t size = result.length();
if (size && result[size - 1] == ‘\n’)
result.resize(–size);
return result.toString();
}
String WMLFormControlElement::innerTextValue() const
{
HTMLElement* innerText = innerTextElement();
if (!innerText || !isTextFormControl())
return emptyString();
StringBuilder result;
for (Node* node = innerText; node; node = NodeTraversal::next(node, innerText)) {
if (node->hasTagName(WMLNames::brTag))
result.append(newlineCharacter);
else if (node->isTextNode())
result.append(toText(node)->data());
}
return finishText(result);
}
static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& breakOffset)
{
RootInlineBox* next;
for (; line; line = next) {
next = line->nextRootBox();
if (next && !line->endsWithBreak()) {
ASSERT(line->lineBreakObj());
breakNode = line->lineBreakObj()->node();
breakOffset = line->lineBreakPos();
line = next;
return;
}
}
breakNode = 0;
breakOffset = 0;
}
String WMLFormControlElement::valueWithHardLineBreaks() const
{
// FIXME: It’s not acceptable to ignore the HardWrap setting when there is no renderer.
// While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
HTMLElement* innerText = innerTextElement();
if (!innerText || !isTextFormControl())
return value();
RenderBlock* renderer = toRenderBlock(innerText->renderer());
if (!renderer)
return value();
Node* breakNode;
unsigned breakOffset;
RootInlineBox* line = renderer->firstRootBox();
if (!line)
return value();
getNextSoftBreak(line, breakNode, breakOffset);
StringBuilder result;
for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(node, innerText)) {
if (node->hasTagName(WMLNames::brTag))
result.append(newlineCharacter);
else if (node->isTextNode()) {
String data = toText(node)->data();
unsigned length = data.length();
unsigned position = 0;
while (breakNode == node && breakOffset <= length) {
if (breakOffset > position) {
result.append(data, position, breakOffset - position);
position = breakOffset;
result.append(newlineCharacter);
}
getNextSoftBreak(line, breakNode, breakOffset);
}
result.append(data, position, length - position);
}
while (breakNode == node)
getNextSoftBreak(line, breakNode, breakOffset);
}
return finishText(result);
}
WMLFormControlElement* enclosingFormControl(const Position& position)
{
ASSERT(position.isNull() || position.anchorType() == Position::PositionIsOffsetInAnchor
|| position.containerNode() || !position.anchorNode()->shadowHost()
|| (position.anchorNode()->parentNode() && position.anchorNode()->parentNode()->isShadowRoot()));
Node* container = position.containerNode();
if (!container)
return 0;
Element* ancestor = container->shadowHost();
return ancestor && isWMLFormControlElement(ancestor) ? toWMLFormControlElement(ancestor) : 0;
}
String WMLFormControlElement::directionForFormData() const
{
/* for (const Element* element = this; element; element = parentHTMLElement(element)) {
const AtomicString& dirAttributeValue = element->fastGetAttribute(dirAttr);
if (dirAttributeValue.isNull())
continue;
if (equalIgnoringCase(dirAttributeValue, "rtl") || equalIgnoringCase(dirAttributeValue, "ltr"))
return dirAttributeValue;
if (equalIgnoringCase(dirAttributeValue, "auto")) {
bool isAuto;
TextDirection textDirection = static_cast<const HTMLElement*>(element)->directionalityIfhasDirAutoAttribute(isAuto);
return textDirection == RTL ? "rtl" : "ltr";
}
}
*/
return “ltr”;
}
void WMLFormControlElement::dispatchFormControlInputEvent()
{
setChangedSinceLastFormControlChangeEvent(true);
WMLElement::dispatchInputEvent();
}
void WMLFormControlElement::notifyFormStateChanged()
{
Frame* frame = document()->frame();
if (!frame)
return;
if (Page* page = frame->page())
page->chrome().client()->formStateDidChange(this);
}
Source/core/wml/WMLInputElement.h
class InputType;
class VisiblePosition;
class WMLInputElement : public WMLFormControlElement{
public:
static PassRefPtr create(const QualifiedName&, Document*);
WMLInputElement(const QualifiedName& tagName, Document*);
virtual ~WMLInputElement();
// virtual InputElement* toInputElement() { return this; }
// virtual bool isKeyboardFocusable(KeyboardEvent*) const;
virtual bool isMouseFocusable() const;
virtual void updateFocusAppearance(bool restorePreviousSelection);
// virtual void aboutToUnload();
virtual bool isChecked() const { return false; }
virtual bool isAutofilled() const { return false; }
virtual bool isIndeterminate() const { return false; }
virtual bool isCheckbox() const ;
virtual bool isInputTypeHidden() const;
// virtual bool isPasswordField() const { return m_isPasswordField; }
virtual bool searchEventsShouldBeDispatched() const { return false; }
virtual const AtomicString& formControlName() const { }
virtual String convertFromVisibleValue(const String& value) const { }
virtual bool wasChangedSinceLastFormControlChangeEvent() const { return false; }
virtual void setChangedSinceLastFormControlChangeEvent(bool) {}
// virtual void select();
// virtual void parseMappedAttribute(Attribute*) { }
// virtual void copyNonAttributeProperties(const Element* source);
virtual void detach(const AttachContext& = AttachContext()) OVERRIDE;
// virtual void cacheSelection(int start, int end);
virtual bool isAcceptableValue(const String&) const { return true; }
// virtual void documentDidBecomeActive();
// virtual void willMoveToNewOwnerDocument();
// virtual void didMoveToNewOwnerDocument();
bool isConformedToInputMask(const String&);
bool isConformedToInputMask(UChar, unsigned, bool isUserInput = true);
#if ENABLE(WCSS)
virtual InputElementData data() const { return m_data; }
#endif
// void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection direction);
// void dispatchBlurEvent(Element* newFocusedElement);
VisiblePosition visiblePositionForIndex(int) const;
bool isRequired() const {return !m_isEmptyOk; }
// void fixPlaceholderRenderer(HTMLElement* placeholder, HTMLElement* siblingElement);
virtual bool hasBadInput() const OVERRIDE;
virtual bool patternMismatch() const OVERRIDE;
virtual bool rangeUnderflow() const OVERRIDE;
virtual bool rangeOverflow() const;
// virtual bool stepMismatch() const OVERRIDE;
virtual bool tooLong() const OVERRIDE;
virtual bool typeMismatch() const OVERRIDE;
virtual bool valueMissing() const OVERRIDE;
virtual String validationMessage() const OVERRIDE;
// Returns the minimum value for type=date, number, or range. Don't call this for other types.
double minimum() const;
// Returns the maximum value for type=date, number, or range. Don't call this for other types.
// This always returns a value which is >= minimum().
double maximum() const;
// Sets the "allowed value step" defined in the HTML spec to the specified double pointer.
// Returns false if there is no "allowed value step."
// bool getAllowedValueStep(Decimal*) const;
// StepRange createStepRange(AnyStepHandling) const;
// Decimal findClosestTickMarkValue(const Decimal&);
// Implementations of HTMLInputElement::stepUp() and stepDown().
/* void stepUp(int, ExceptionState&);
void stepDown(int, ExceptionState&);
void stepUp(ExceptionState& es) { stepUp(1, es); }
void stepDown(ExceptionState& es) { stepDown(1, es); }
// stepUp()/stepDown() for user-interaction.
bool isSteppable() const;
*/
bool isTextButton() const;
bool isRadioButton() const;
bool isTextField() const;
bool isSearchField() const;
bool isPasswordField() const;
bool isRangeControl() const;
bool isColorControl() const;
// FIXME: It's highly likely that any call site calling this function should instead
// be using a different one. Many input elements behave like text fields, and in addition
// any unknown input type is treated as text. Consider, for example, isTextField or
// isTextField && !isPasswordField.
bool isText() const;
bool isEmailField() const;
bool isFileUpload() const;
bool isImageButton() const;
bool isNumberField() const;
bool isSubmitButton() const;
bool isTelephoneField() const;
bool isURLField() const;
bool isDateField() const;
bool isDateTimeLocalField() const;
bool isMonthField() const;
bool isTimeField() const;
bool isWeekField() const;
#if ENABLE(INPUT_SPEECH)
bool isSpeechEnabled() const;
#endif
HTMLElement* containerElement() const;
virtual HTMLElement* innerTextElement() const;
HTMLElement* innerBlockElement() const;
HTMLElement* innerSpinButtonElement() const;
#if ENABLE(INPUT_SPEECH)
HTMLElement* speechButtonElement() const;
#endif
HTMLElement* sliderThumbElement() const;
HTMLElement* sliderTrackElement() const;
HTMLElement* passwordGeneratorButtonElement() const;
virtual HTMLElement* placeholderElement() const;
// bool checked() const { return m_isChecked; }
// 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; }
void setIndeterminate(bool);
// shouldAppearChecked is used by the rendering tree/CSS while checked() is used by JS to determine checked state
bool shouldAppearChecked() const;
virtual bool shouldAppearIndeterminate() const OVERRIDE;
int size() const;
bool sizeShouldIncludeDecoration(int& preferredSize) const;
// void setType(const String&);
String value() const;
void setValue(const String&, ExceptionState&, TextFieldEventBehavior = DispatchNoEvent);
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.
bool isValidValue(const String&) const;
bool hasDirtyValue() const { return !m_valueIfDirty.isNull(); };
String sanitizeValue(const String&) const;
String localizeValue(const String&) const;
// The value which is drawn by a renderer.
String visibleValue() const;
const String& suggestedValue() const;
void setSuggestedValue(const String&);
void setEditingValue(const String&);
/*
double valueAsDate() const;
void setValueAsDate(double, ExceptionState&);
double valueAsNumber() const;
void setValueAsNumber(double, ExceptionState&, TextFieldEventBehavior = DispatchNoEvent);
*/
String valueWithDefault() const;
void setValueFromRenderer(const String&);
/* int selectionStartForBinding(ExceptionState&) const;
int selectionEndForBinding(ExceptionState&) const;
String selectionDirectionForBinding(ExceptionState&) const;
void setSelectionStartForBinding(int, ExceptionState&);
void setSelectionEndForBinding(int, ExceptionState&);
void setSelectionDirectionForBinding(const String&, ExceptionState&);
void setSelectionRangeForBinding(int start, int end, ExceptionState&);
void setSelectionRangeForBinding(int start, int end, const String& direction, ExceptionState&);
/
virtual bool rendererIsNeeded(const NodeRenderingContext&);
virtual RenderObject createRenderer(RenderStyle*);
// virtual void detach(const AttachContext& = AttachContext()) OVERRIDE;
// FIXME: For isActivatedSubmit and setActivatedSubmit, we should use the NVI-idiom here by making
// it private virtual in all classes and expose a public method in HTMLFormControlElement to call
// the private virtual method.
virtual bool isActivatedSubmit() const;
virtual void setActivatedSubmit(bool flag);
// String altText() const;
// int maxResults() const { return m_maxResults; }
String defaultValue() const;
void setDefaultValue(const String&);
// Vector acceptMIMETypes();
// Vector acceptFileExtensions();
// String accept() const;
// String alt() const;
void setSize(unsigned);
void setSize(unsigned, ExceptionState&);
// KURL src() const;
virtual int maxLength() const;
// void setMaxLength(int, ExceptionState&);
// bool multiple() const;
// bool isAutofilled() const { return m_isAutofilled; }
// void setAutofilled(bool = true);
// FileList* files();
// void setFiles(PassRefPtr);
// Returns true if the given DragData has more than one dropped files.
// bool receiveDroppedFiles(const DragData*);
// String droppedFileSystemId();
// Icon* icon() const;
// These functions are used for rendering the input active during a
// drag-and-drop operation.
// bool canReceiveDroppedFiles() const;
// void setCanReceiveDroppedFiles(bool);
// void onSearch();
void updateClearButtonVisibility();
// virtual bool willRespondToMouseClickEvents() OVERRIDE;
// HTMLElement* list() const;
// HTMLDataListElement* dataList() const;
// void listAttributeTargetChanged();
WMLInputElement* checkedRadioButtonForGroup() const;
bool isInRequiredRadioButtonGroup();
// Functions for InputType classes.
void setValueInternal(const String&, TextFieldEventBehavior);
bool valueAttributeWasUpdatedAfterParsing() const { return m_valueAttributeWasUpdatedAfterParsing; }
void cacheSelectionInResponseToSetValue(int caretOffset) { cacheSelection(caretOffset, caretOffset, SelectionHasNoDirection); }
// For test purposes.
// void selectColorInColorChooser(const Color&);
String defaultToolTip() const;
static const unsigned maximumLength;
unsigned height() const;
unsigned width() const;
void setHeight(unsigned);
void setWidth(unsigned);
virtual void blur() OVERRIDE;
void defaultBlur();
virtual const AtomicString& name() const OVERRIDE;
void beginEditing();
void endEditing();
virtual bool matchesReadOnlyPseudoClass() const OVERRIDE;
virtual bool matchesReadWritePseudoClass() const OVERRIDE;
virtual void setRangeText(const String& replacement, ExceptionState&) OVERRIDE;
virtual void setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState&) OVERRIDE;
// bool setupDateTimeChooserParameters(DateTimeChooserParameters&);
bool supportsInputModeAttribute() const;
virtual bool shouldAutocomplete() const;
virtual bool willRespondToMouseClickEvents() OVERRIDE;
bool isSteppable() const;
protected:
virtual void defaultEventHandler(Event*);
private:
friend class WMLCardElement;
void initialize();
virtual void didAddUserAgentShadowRoot(ShadowRoot*) OVERRIDE;
virtual void willChangeForm() OVERRIDE;
virtual void didChangeForm() OVERRIDE;
virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
virtual void removedFrom(ContainerNode*) OVERRIDE;
// virtual void didMoveToNewDocument(Document* oldDocument) OVERRIDE;
virtual bool hasCustomFocusLogic() const OVERRIDE;
virtual bool isKeyboardFocusable() const OVERRIDE;
virtual bool shouldShowFocusRingOnMouseFocus() const OVERRIDE;
virtual bool isEnumeratable() const;
virtual bool supportLabels() const OVERRIDE;
virtual bool shouldUseInputMethod();
virtual bool isTextFormControl() const { return isTextField(); }
virtual bool canTriggerImplicitSubmission() const { return isTextField(); }
virtual const AtomicString& formControlType() const;
virtual bool shouldSaveAndRestoreFormControlState() const OVERRIDE;
// virtual FormControlState saveFormControlState() const OVERRIDE;
// virtual void restoreFormControlState(const FormControlState&) OVERRIDE;
virtual bool canStartSelection() const;
virtual void accessKeyAction(bool sendMouseEvents);
virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE;
// virtual void finishParsingChildren();
virtual void copyNonAttributePropertiesFromElement(const Element&);
virtual void attach(const AttachContext& = AttachContext()) OVERRIDE;
virtual bool appendFormData(FormDataList&, bool);
virtual bool isSuccessfulSubmitButton() const;
virtual void reset();
virtual void* preDispatchEventHandler(Event*);
virtual void postDispatchEventHandler(Event*, void* dataFromPreDispatch);
virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
virtual bool isInRange() const;
virtual bool isOutOfRange() const;
// virtual void addSubresourceAttributeURLs(ListHashSet&) const;
bool supportsMaxLength() const { return isTextType(); }
bool isTextType() const;
bool tooLong(const String&, NeedsToCheckDirtyFlag) const;
virtual bool supportsPlaceholder() const;
virtual void updatePlaceholderText();
virtual bool isEmptyValue() const OVERRIDE { return innerTextValue().isEmpty(); }
virtual bool isEmptySuggestedValue() const { return suggestedValue().isEmpty(); }
virtual void handleFocusEvent(Element* oldFocusedElement, FocusDirection) OVERRIDE;
virtual void handleBlurEvent();
virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); }
virtual bool isRequiredFormControl() const;
virtual bool recalcWillValidate() const;
virtual void requiredAttributeChanged() OVERRIDE;
void updateType();
virtual void subtreeHasChanged();
// void resetListAttributeTargetObserver();
void parseMaxLengthAttribute(const AtomicString&);
void updateValueIfNeeded();
bool canHaveSelection() const;
// Returns null if this isn't associated with any radio button group.
// CheckedRadioButtons* checkedRadioButtons() const;
// void addToRadioButtonGroup();
// void removeFromRadioButtonGroup();
String validateInputMask(const String&);
unsigned cursorPositionToMaskIndex(unsigned);
String constrainValue(const String&) const;
AtomicString m_name;
String m_valueIfDirty;
String m_suggestedValue;
int m_size;
int m_maxLength;
short m_maxResults;
bool m_isChecked : 1;
bool m_reflectsCheckedAttribute : 1;
bool m_isIndeterminate : 1;
bool m_hasType : 1;
bool m_isActivatedSubmit : 1;
unsigned m_autocomplete : 2; // AutoCompleteSetting
bool m_isAutofilled : 1;
bool m_hasNonEmptyList : 1;
bool m_stateRestored : 1;
bool m_parsingInProgress : 1;
bool m_valueAttributeWasUpdatedAfterParsing : 1;
bool m_wasModifiedByUser : 1;
bool m_canReceiveDroppedFiles : 1;
bool m_hasTouchEventHandler : 1;
bool m_isEmptyOk;
// InputElementData m_data;
// bool m_isPasswordField;
// bool m_wasChangedSinceLastChangeEvent;
// String m_formatMask;
// unsigned m_numOfCharsAllowedByMask;
OwnPtr m_inputType;
};
inline WMLInputElement* toWMLInputElement(Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(WMLNames::inputTag));
return static_cast<WMLInputElement*>(node);
}
inline const WMLInputElement* toWMLInputElement(const Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(WMLNames::inputTag));
return static_cast<const WMLInputElement*>(node);
}
Source/core/wml/WMLInputElement.cpp
WMLInputElement::WMLInputElement(const QualifiedName& tagName, Document* doc)
: WMLFormControlElement(tagName, doc)
, m_isEmptyOk(false)
, m_maxResults(-1)
, m_isChecked(false)
, m_reflectsCheckedAttribute(true)
, m_isIndeterminate(false)
, m_hasType(false)
, m_isActivatedSubmit(false)
, m_isAutofilled(false)
, m_hasNonEmptyList(false)
, m_stateRestored(false)
, m_valueAttributeWasUpdatedAfterParsing(false)
, m_wasModifiedByUser(false)
, m_hasTouchEventHandler(false)
, m_inputType(InputType::createText(this))
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, %x”,this);
}
PassRefPtr WMLInputElement::create(const QualifiedName& tagName, Document* document)
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, tagname=%s”,tagName.toString().utf8().data());
/android::CallStack stack;
stack.update();
stack.dump(“Neo callstack”);/
RefPtr inputElement = adoptRef(new WMLInputElement(tagName, document));
inputElement->ensureUserAgentShadowRoot();
return inputElement.release();
}
void WMLInputElement::didAddUserAgentShadowRoot(ShadowRoot*)
{
m_inputType->createShadowSubtree();
}
WMLInputElement::~WMLInputElement()
{
// Need to remove form association while this is still an HTMLInputElement
// so that virtual functions are called correctly.
// setForm(0);
// setForm(0) may register this to a document-level radio button group.
// We should unregister it to avoid accessing a deleted object.
// if (isRadioButton())
// document()->formController()->checkedRadioButtons().removeButton(this);
}
/static const AtomicString& formatCodes()
{
DEFINE_STATIC_LOCAL(AtomicString, codes, (“AaNnXxMm”));
return codes;
}/
const AtomicString& WMLInputElement::name() const
{
return m_name.isNull() ? emptyAtom : m_name;
}
/Vector WMLInputElement::filesFromFileInputFormControlState(const FormControlState& state)
{
return NULL;
}/
HTMLElement* WMLInputElement::containerElement() const
{
return m_inputType->containerElement();
}
HTMLElement* WMLInputElement::innerTextElement() const
{
return m_inputType->innerTextElement();
}
HTMLElement* WMLInputElement::innerBlockElement() const
{
return m_inputType->innerBlockElement();
}
HTMLElement* WMLInputElement::innerSpinButtonElement() const
{
return NULL;
}
#if ENABLE(INPUT_SPEECH)
HTMLElement* WMLInputElement::speechButtonElement() const
{
return NULL;
}
#endif
HTMLElement* WMLInputElement::passwordGeneratorButtonElement() const
{
return NULL;
}
HTMLElement* WMLInputElement::sliderThumbElement() const
{
return NULL;
}
HTMLElement* WMLInputElement::sliderTrackElement() const
{
return NULL;
}
HTMLElement* WMLInputElement::placeholderElement() const
{
return m_inputType->placeholderElement();
}
bool WMLInputElement::shouldAutocomplete() const
{
return false;
}
bool WMLInputElement::isValidValue(const String& value) const
{
if (!m_inputType->canSetStringValue()) {
ASSERT_NOT_REACHED();
return false;
}
return !m_inputType->typeMismatchFor(value)
&& !m_inputType->stepMismatch(value)
&& !m_inputType->rangeUnderflow(value)
&& !m_inputType->rangeOverflow(value)
&& !tooLong(value, IgnoreDirtyFlag)
&& !m_inputType->patternMismatch(value)
&& !m_inputType->valueMissing(value);
}
bool WMLInputElement::tooLong() const
{
return willValidate() && tooLong(value(), CheckDirtyFlag);
}
bool WMLInputElement::typeMismatch() const
{
return willValidate() && m_inputType->typeMismatch();
}
bool WMLInputElement::valueMissing() const
{
return willValidate() && m_inputType->valueMissing(value());
}
bool WMLInputElement::hasBadInput() const
{
return willValidate() && m_inputType->hasBadInput();
}
bool WMLInputElement::patternMismatch() const
{
return willValidate() && m_inputType->patternMismatch(value());
}
bool WMLInputElement::tooLong(const String& value, NeedsToCheckDirtyFlag check) const
{
// We use isTextType() instead of supportsMaxLength() because of the
// ‘virtual’ overhead.
/* if (!isTextType())
return false;
int max = maxLength();
if (max < 0)
return false;
if (check == CheckDirtyFlag) {
// Return false for the default value or a value set by a script even if
// it is longer than maxLength.
if (!hasDirtyValue() || !m_wasModifiedByUser)
return false;
}
return numGraphemeClusters(value) > static_cast(max);
*/
return false;
}
bool WMLInputElement::rangeUnderflow() const
{
return false;
// return willValidate() && m_inputType->rangeUnderflow(value());
}
bool WMLInputElement::rangeOverflow() const
{ return false;
// return willValidate() && m_inputType->rangeOverflow(value());
}
String WMLInputElement::validationMessage() const
{
/* if (!willValidate())
return String();
if (customError())
return customValidationMessage();
return m_inputType->validationMessage();*/
return String();
}
double WMLInputElement::minimum() const
{
return m_inputType->minimum();
}
double WMLInputElement::maximum() const
{
return m_inputType->maximum();
}
void WMLInputElement::blur()
{
m_inputType->blur();
}
void WMLInputElement::defaultBlur()
{
WMLFormControlElement::blur();
}
bool WMLInputElement::hasCustomFocusLogic() const
{
return m_inputType->hasCustomFocusLogic();
}
bool WMLInputElement::isKeyboardFocusable() const
{
return m_inputType->isKeyboardFocusable();
// return WMLFormControlElement::isFocusable();
}
bool WMLInputElement::shouldShowFocusRingOnMouseFocus() const
{
return m_inputType->shouldShowFocusRingOnMouseFocus();
}
void WMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
{
if (isTextField()) {
if (!restorePreviousSelection || !hasCachedSelection())
select();
else
restoreCachedSelection();
if (document()->frame())
document()->frame()->selection()->revealSelection();
} else
WMLFormControlElement::updateFocusAppearance(restorePreviousSelection);
}
void WMLInputElement::beginEditing()
{
if (!isTextField())
return;
if (Frame* frame = document()->frame())
frame->editor()->textFieldDidBeginEditing(this);
}
void WMLInputElement::endEditing()
{
if (!isTextField())
return;
if (Frame* frame = document()->frame())
frame->editor()->textFieldDidEndEditing(this);
}
bool WMLInputElement::shouldUseInputMethod()
{
return m_inputType->shouldUseInputMethod();
}
void WMLInputElement::handleFocusEvent(Element* oldFocusedElement, FocusDirection direction)
{
m_inputType->handleFocusEvent(oldFocusedElement, direction);
}
void WMLInputElement::handleBlurEvent()
{
m_inputType->handleBlurEvent();
}
void WMLInputElement::updateType()
{
OwnPtr newType = InputType::create(this, fastGetAttribute(HTMLNames::typeAttr));
bool hadType = m_hasType;
m_hasType = true;
if (m_inputType->formControlType() == newType->formControlType()) {
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, %x,formcontroltype=%s,typeAttr=%s”,this,newType->formControlType().string().utf8().data(),fastGetAttribute(HTMLNames::typeAttr).string().utf8().data());
return;
}
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, exe %x,formcontroltype=%s,typeAttr=%s”,this,newType->formControlType().string().utf8().data(),fastGetAttribute(HTMLNames::typeAttr).string().utf8().data());
if (hadType && !newType->canChangeFromAnotherType()) {
// Set the attribute back to the old value.
// Useful in case we were called from inside parseAttribute.
setAttribute(HTMLNames::typeAttr, formControlType());
return;
}
// removeFromRadioButtonGroup();
bool didStoreValue = m_inputType->storesValueSeparateFromAttribute();
bool didRespectHeightAndWidth = m_inputType->shouldRespectHeightAndWidthAttributes();
m_inputType->destroyShadowSubtree();
bool wasAttached = attached();
if (wasAttached)
detach();
m_inputType = newType.release();
m_inputType->createShadowSubtree();
bool hasTouchEventHandler = m_inputType->hasTouchEventHandler();
if (hasTouchEventHandler != m_hasTouchEventHandler) {
if (hasTouchEventHandler)
document()->didAddTouchEventHandler(this);
else
document()->didRemoveTouchEventHandler(this);
m_hasTouchEventHandler = hasTouchEventHandler;
}
// setNeedsWillValidateCheck();
bool willStoreValue = m_inputType->storesValueSeparateFromAttribute();
if (didStoreValue && !willStoreValue && hasDirtyValue()) {
setAttribute(HTMLNames::valueAttr, m_valueIfDirty);
m_valueIfDirty = String();
}
if (!didStoreValue && willStoreValue) {
AtomicString valueString = fastGetAttribute(HTMLNames::valueAttr);
m_valueIfDirty = sanitizeValue(valueString);
} else
updateValueIfNeeded();
setFormControlValueMatchesRenderer(false);
m_inputType->updateInnerTextValue();
m_wasModifiedByUser = false;
if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) {
ASSERT(elementData());
if (const Attribute* height = getAttributeItem(HTMLNames::heightAttr))
attributeChanged(HTMLNames::heightAttr, height->value());
if (const Attribute* width = getAttributeItem(HTMLNames::widthAttr))
attributeChanged(HTMLNames::widthAttr, width->value());
if (const Attribute* align = getAttributeItem(HTMLNames::alignAttr))
attributeChanged(HTMLNames::alignAttr, align->value());
}
if (wasAttached) {
lazyAttach();
if (document()->focusedElement() == this)
document()->updateFocusAppearanceSoon(true /* restore selection */);
}
setChangedSinceLastFormControlChangeEvent(false);
// addToRadioButtonGroup();
setNeedsValidityCheck();
notifyFormStateChanged();
}
void WMLInputElement::subtreeHasChanged()
{
m_inputType->subtreeHasChanged();
// When typing in an input field, childrenChanged is not called, so we need to force the directionality check.
//calculateAndAdjustDirectionality();
}
const AtomicString& WMLInputElement::formControlType() const
{
return m_inputType->formControlType();
}
bool WMLInputElement::shouldSaveAndRestoreFormControlState() const
{
return false;
}
/*FormControlState HTMLInputElement::saveFormControlState() const
{
return m_inputType->saveFormControlState();
}
void HTMLInputElement::restoreFormControlState(const FormControlState& state)
{
m_inputType->restoreFormControlState(state);
m_stateRestored = true;
}*/
bool WMLInputElement::canStartSelection() const
{
if (!isTextField())
return false;
return WMLFormControlElement::canStartSelection();
}
bool WMLInputElement::canHaveSelection() const
{
return isTextField();
}
void WMLInputElement::accessKeyAction(bool sendMouseEvents)
{
m_inputType->accessKeyAction(sendMouseEvents);
}
bool WMLInputElement::isPresentationAttribute(const QualifiedName& name) const
{
if (name == HTMLNames::vspaceAttr || name == HTMLNames::hspaceAttr || name == HTMLNames::alignAttr || name == HTMLNames::widthAttr || name == HTMLNames::heightAttr)
return true;
return WMLFormControlElement::isPresentationAttribute(name);
}
void WMLInputElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
{
if (name == HTMLNames::vspaceAttr) {
addWMLLengthToStyle(style, CSSPropertyMarginTop, value);
addWMLLengthToStyle(style, CSSPropertyMarginBottom, value);
} else if (name == HTMLNames::hspaceAttr) {
addWMLLengthToStyle(style, CSSPropertyMarginLeft, value);
addWMLLengthToStyle(style, CSSPropertyMarginRight, value);
} else if (name == HTMLNames::alignAttr) {
if (m_inputType->shouldRespectAlignAttribute())
applyAlignmentAttributeToStyle(value, style);
} else if (name == HTMLNames::widthAttr) {
if (m_inputType->shouldRespectHeightAndWidthAttributes())
addWMLLengthToStyle(style, CSSPropertyWidth, value);
} else if (name == HTMLNames::heightAttr) {
if (m_inputType->shouldRespectHeightAndWidthAttributes())
addWMLLengthToStyle(style, CSSPropertyHeight, value);
} else
WMLFormControlElement::collectStyleForPresentationAttribute(name, value, style);
}
void WMLInputElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
if (name == HTMLNames::nameAttr) {
m_name = value;
WMLFormControlElement::parseAttribute(name, value);
// m_data.setName(parseValueForbiddingVariableReferences(value));
} else if (name == HTMLNames::typeAttr) {
// String type = parseValueForbiddingVariableReferences(value);
updateType();
/* if (value == “password”) {
OwnPtr newType = PasswordInputType::create(this);
m_inputType->destroyShadowSubtree();
m_inputType = newType.release();
m_inputType->createShadowSubtree();
}*/
} else if (name == HTMLNames::valueAttr) {
if (!hasDirtyValue()) {
updatePlaceholderVisibility(false);
setNeedsStyleRecalc();
}
setFormControlValueMatchesRenderer(false);
setNeedsValidityCheck();
m_valueAttributeWasUpdatedAfterParsing = !m_parsingInProgress;
m_inputType->valueAttributeChanged();
// We only need to setChanged if the form is looking at the default value right now.
// if (m_data.value().isNull())
// setNeedsStyleRecalc();
// setFormControlValueMatchesRenderer(false);
} else if (name == HTMLNames::maxlengthAttr)
parseMaxLengthAttribute(value);
//InputElement::parseMaxLengthAttribute(m_data, this, this, NULL);
else if (name == HTMLNames::sizeAttr) {
int oldSize = m_size;
int valueAsInteger = value.toInt();
m_size = valueAsInteger > 0 ? valueAsInteger : 20;
if (m_size != oldSize && renderer())
renderer()->setNeedsLayoutAndPrefWidthsRecalc();
//InputElement::parseSizeAttribute(m_data, this, NULL);
} else if (name == WMLNames::formatAttr)
;//m_formatMask = validateInputMask(parseValueForbiddingVariableReferences(value));
else if (name == WMLNames::emptyokAttr)
m_isEmptyOk = (value == “true”);
else
WMLFormControlElement::parseAttribute(name, value);
// FIXME: Handle 'accesskey' attribute
// FIXME: Handle 'tabindex' attribute
// FIXME: Handle 'title' attribute
}
/void WMLInputElement::finishParsingChildren()
{
m_parsingInProgress = false;
WMLTextFormControlElement::finishParsingChildren();
if (!m_stateRestored) {
bool checked = hasAttribute(checkedAttr);
if (checked)
setChecked(checked);
m_reflectsCheckedAttribute = true;
}
}/
bool WMLInputElement::rendererIsNeeded(const NodeRenderingContext& context)
{
return m_inputType->rendererIsNeeded() && WMLFormControlElement::rendererIsNeeded(context);
}
RenderObject* WMLInputElement::createRenderer(RenderStyle* style)
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, %x”,this);
return m_inputType->createRenderer(style);
// return new RenderTextControlSingleLine(this);
}
void WMLInputElement::attach(const AttachContext& context)
{
PostAttachCallbackDisabler disabler(this);
if (!m_hasType)
updateType();
WMLFormControlElement::attach(context);
m_inputType->attach();
if (document()->focusedElement() == this)
document()->updateFocusAppearanceSoon(true /* restore selection */);
}
void WMLInputElement::detach(const AttachContext& context)
{
WMLElement::detach(context);
setFormControlValueMatchesRenderer(false);
m_inputType->detach();
}
bool WMLInputElement::isSuccessfulSubmitButton() const
{
// HTML spec says that buttons must have names to be considered successful.
// However, other browsers do not impose this constraint. So we do not.
return false;//!isDisabledFormControl() && m_inputType->canBeSuccessfulSubmitButton();
}
bool WMLInputElement::isActivatedSubmit() const
{
return m_isActivatedSubmit;
}
void WMLInputElement::setActivatedSubmit(bool flag)
{
m_isActivatedSubmit = flag;
}
bool WMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
{
return m_inputType->isFormDataAppendable() && m_inputType->appendFormData(encoding, multipart);
}
void WMLInputElement::reset()
{
/* if (m_inputType->storesValueSeparateFromAttribute())
setValue(String());
setAutofilled(false);
setChecked(hasAttribute(checkedAttr));
m_reflectsCheckedAttribute = true;*/
}
bool WMLInputElement::isTextField() const
{
return m_inputType->isTextField();
}
bool WMLInputElement::isTextType() const
{
return m_inputType->isTextType();
}
int WMLInputElement::size() const
{
return m_size;
}
bool WMLInputElement::sizeShouldIncludeDecoration(int& preferredSize) const
{
return m_inputType->sizeShouldIncludeDecoration(20, preferredSize);
}
void WMLInputElement::copyNonAttributePropertiesFromElement(const Element& source)
{
/* const WMLInputElement& sourceElement = static_cast<const WMLInputElement&>(source);
m_valueIfDirty = sourceElement.m_valueIfDirty;
m_wasModifiedByUser = false;
setChecked(sourceElement.m_isChecked);
m_reflectsCheckedAttribute = sourceElement.m_reflectsCheckedAttribute;
m_isIndeterminate = sourceElement.m_isIndeterminate;
WMLFormControlElement::copyNonAttributePropertiesFromElement(source);
setFormControlValueMatchesRenderer(false);
m_inputType->updateInnerTextValue();*/
}
String WMLInputElement::value() const
{
String value;
if (m_inputType->getTypeSpecificValue(value))
return value;
value = m_valueIfDirty;
if (!value.isNull())
return value;
AtomicString valueString = fastGetAttribute(HTMLNames::valueAttr);
value = sanitizeValue(valueString);
if (!value.isNull())
return value;
return m_inputType->fallbackValue();
}
String WMLInputElement::valueWithDefault() const
{
String value = this->value();
if (!value.isNull())
return value;
return m_inputType->defaultValue();
}
void WMLInputElement::setValueForUser(const String& value)
{
// Call setValue and make it send a change event.
setValue(value, DispatchChangeEvent);
}
const String& WMLInputElement::suggestedValue() const
{
return m_suggestedValue;
}
void WMLInputElement::setSuggestedValue(const String& value)
{
if (!m_inputType->canSetSuggestedValue())
return;
setFormControlValueMatchesRenderer(false);
m_suggestedValue = sanitizeValue(value);
setNeedsStyleRecalc();
m_inputType->updateInnerTextValue();
}
void WMLInputElement::setEditingValue(const String& value)
{
if (!renderer() || !isTextField())
return;
setInnerTextValue(value);
subtreeHasChanged();
unsigned max = value.length();
if (focused())
setSelectionRange(max, max);
else
cacheSelectionInResponseToSetValue(max);
dispatchInputEvent();
}
void WMLInputElement::setValue(const String& value, ExceptionState& es, TextFieldEventBehavior eventBehavior)
{
if (isFileUpload() && !value.isEmpty()) {
es.throwDOMException(InvalidStateError);
return;
}
setValue(value, eventBehavior);
}
void WMLInputElement::setValue(const String& value, TextFieldEventBehavior eventBehavior)
{
if (!m_inputType->canSetValue(value))
return;
RefPtr<WMLInputElement> protector(this);
EventQueueScope scope;
String sanitizedValue = sanitizeValue(value);
bool valueChanged = sanitizedValue != this->value();
setLastChangeWasNotUserEdit();
setFormControlValueMatchesRenderer(false);
m_suggestedValue = String(); // Prevent TextFieldInputType::setValue from using the suggested value.
m_inputType->setValue(sanitizedValue, valueChanged, eventBehavior);
if (!valueChanged)
return;
// notifyFormStateChanged();
}
void WMLInputElement::setValueInternal(const String& sanitizedValue, TextFieldEventBehavior eventBehavior)
{
m_valueIfDirty = sanitizedValue;
m_wasModifiedByUser = eventBehavior != DispatchNoEvent;
setNeedsValidityCheck();
}
void WMLInputElement::setValueFromRenderer(const String& value)
{
// File upload controls will never use this.
ASSERT(!isFileUpload());
m_suggestedValue = String();
// Renderer and our event handler are responsible for sanitizing values.
ASSERT(value == sanitizeValue(value) || sanitizeValue(value).isEmpty());
m_valueIfDirty = value;
setFormControlValueMatchesRenderer(true);
m_wasModifiedByUser = true;
// Input event is fired by the Node::defaultEventHandler for editable controls.
if (!isTextField())
dispatchInputEvent();
// notifyFormStateChanged();
setNeedsValidityCheck();
// Clear autofill flag (and yellow background) on user edit.
// setAutofilled(false);
}
void* WMLInputElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().textInputEvent && m_inputType->shouldSubmitImplicitly(event)) {
event->stopPropagation();
return 0;
}
if (event->type() != eventNames().clickEvent)
return 0;
if (!event->isMouseEvent() || toMouseEvent(event)->button() != LeftButton)
return 0;
// FIXME: Check whether there are any cases where this actually ends up leaking.
return m_inputType->willDispatchClick().leakPtr();
}
void WMLInputElement::postDispatchEventHandler(Event* event, void* dataFromPreDispatch)
{
OwnPtr state = adoptPtr(static_cast<ClickHandlingState*>(dataFromPreDispatch));
if (!state)
return;
m_inputType->didDispatchClick(event, *state);
}
void WMLInputElement::defaultEventHandler(Event* evt)
{
if (evt->isMouseEvent() && evt->type() == eventNames().clickEvent && toMouseEvent(evt)->button() == LeftButton) {
m_inputType->handleClickEvent(toMouseEvent(evt));
if (evt->defaultHandled())
return;
}
if (evt->isTouchEvent()) {
m_inputType->handleTouchEvent(static_cast<TouchEvent*>(evt));
if (evt->defaultHandled())
return;
}
if (evt->isKeyboardEvent() && evt->type() == eventNames().keydownEvent) {
m_inputType->handleKeydownEvent(toKeyboardEvent(evt));
if (evt->defaultHandled())
return;
}
// Call the base event handler before any of our own event handling for almost all events in text fields.
// Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
bool callBaseClassEarly = isTextField() && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
if (callBaseClassEarly) {
WMLFormControlElement::defaultEventHandler(evt);
if (evt->defaultHandled())
return;
}
// DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
// actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
// on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
// must dispatch a DOMActivate event - a click event will not do the job.
if (evt->type() == eventNames().DOMActivateEvent) {
m_inputType->handleDOMActivateEvent(evt);
if (evt->defaultHandled())
return;
}
// Use key press event here since sending simulated mouse events
// on key down blocks the proper sending of the key press event.
if (evt->isKeyboardEvent() && evt->type() == eventNames().keypressEvent) {
m_inputType->handleKeypressEvent(toKeyboardEvent(evt));
if (evt->defaultHandled())
return;
}
if (evt->isKeyboardEvent() && evt->type() == eventNames().keyupEvent) {
m_inputType->handleKeyupEvent(toKeyboardEvent(evt));
if (evt->defaultHandled())
return;
}
if (m_inputType->shouldSubmitImplicitly(evt)) {
// Form submission finishes editing, just as loss of focus does.
// If there was a change, send the event now.
if (wasChangedSinceLastFormControlChangeEvent())
dispatchFormControlChangeEvent();
/* RefPtr formForSubmission = m_inputType->formForSubmission();
// Form may never have been present, or may have been destroyed by code responding to the change event.
if (formForSubmission)
formForSubmission->submitImplicitly(evt, canTriggerImplicitSubmission());
*/
evt->setDefaultHandled();
return;
}
if (evt->isBeforeTextInsertedEvent())
m_inputType->handleBeforeTextInsertedEvent(static_cast<BeforeTextInsertedEvent*>(evt));
if (evt->isMouseEvent() && evt->type() == eventNames().mousedownEvent) {
m_inputType->handleMouseDownEvent(toMouseEvent(evt));
if (evt->defaultHandled())
return;
}
m_inputType->forwardEvent(evt);
if (!callBaseClassEarly && !evt->defaultHandled())
WMLFormControlElement::defaultEventHandler(evt);
}
bool WMLInputElement::willRespondToMouseClickEvents()
{
return true;
// FIXME: Consider implementing willRespondToMouseClickEvents() in InputType if more accurate results are necessary.
/* if (!isDisabledFormControl())
return true;
return WMLFormControlElement::willRespondToMouseClickEvents();*/
}
bool WMLInputElement::isURLAttribute(const Attribute& attribute) const
{
return false;
// return attribute.name() == srcAttr || attribute.name() == formactionAttr || WMLFormControlElement::isURLAttribute(attribute);
}
String WMLInputElement::defaultValue() const
{
return fastGetAttribute(HTMLNames::valueAttr);
}
void WMLInputElement::setDefaultValue(const String &value)
{
// setAttribute(valueAttr, value);
}
int WMLInputElement::maxLength() const
{
return m_maxLength;
}
String WMLInputElement::visibleValue() const
{
return m_inputType->visibleValue();
}
String WMLInputElement::sanitizeValue(const String& proposedValue) const
{
if (proposedValue.isNull())
return proposedValue;
return m_inputType->sanitizeValue(proposedValue);
}
String WMLInputElement::localizeValue(const String& proposedValue) const
{
if (proposedValue.isNull())
return proposedValue;
return m_inputType->localizeValue(proposedValue);
}
bool WMLInputElement::isInRange() const
{
return m_inputType->isInRange(value());
}
bool WMLInputElement::isOutOfRange() const
{
return m_inputType->isOutOfRange(value());
}
bool WMLInputElement::isRequiredFormControl() const
{
return false;
// return m_inputType->supportsRequired() && isRequired();
}
bool WMLInputElement::matchesReadOnlyPseudoClass() const
{
return false;//m_inputType->supportsReadOnly() && isReadOnly();
}
bool WMLInputElement::matchesReadWritePseudoClass() const
{
return false;//m_inputType->supportsReadOnly() && !isReadOnly();
}
void WMLInputElement::updateClearButtonVisibility()
{
//m_inputType->updateClearButtonVisibility();
}
void WMLInputElement::willChangeForm()
{
// removeFromRadioButtonGroup();
// WMLFormControlElement::willChangeForm();
}
void WMLInputElement::didChangeForm()
{
// HTMLTextFormControlElement::didChangeForm();
// addToRadioButtonGroup();
}
Node::InsertionNotificationRequest WMLInputElement::insertedInto(ContainerNode* insertionPoint)
{
WMLFormControlElement::insertedInto(insertionPoint);
return InsertionDone;
}
void WMLInputElement::removedFrom(ContainerNode* insertionPoint)
{
/* if (insertionPoint->inDocument() && !form())
removeFromRadioButtonGroup();
HTMLTextFormControlElement::removedFrom(insertionPoint);
ASSERT(!inDocument());
resetListAttributeTargetObserver();*/
}
/void WMLInputElement::didMoveToNewDocument(Document oldDocument)
{
if (hasImageLoader())
imageLoader()->elementDidMoveToNewDocument();
if (oldDocument) {
if (isRadioButton())
oldDocument->formController()->checkedRadioButtons().removeButton(this);
if (m_hasTouchEventHandler)
oldDocument->didRemoveEventTargetNode(this);
}
if (m_hasTouchEventHandler)
document()->didAddTouchEventHandler(this);
HTMLTextFormControlElement::didMoveToNewDocument(oldDocument);
}
void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet& urls) const
{
HTMLTextFormControlElement::addSubresourceAttributeURLs(urls);
addSubresourceURL(urls, src());
}*/
bool WMLInputElement::recalcWillValidate() const
{
return true;//m_inputType->supportsValidation() && WMLFormControlElement::recalcWillValidate();
}
void WMLInputElement::requiredAttributeChanged()
{
// WMLFormControlElement::requiredAttributeChanged();
m_inputType->requiredAttributeChanged();
}
/*
void WMLInputElement::selectColorInColorChooser(const Color& color)
{
if (!m_inputType->isColorControl())
return;
static_cast<ColorInputType*>(m_inputType.get())->didChooseColor(color);
}
HTMLElement* HTMLInputElement::list() const
{
return dataList();
}
HTMLDataListElement* HTMLInputElement::dataList() const
{
if (!m_hasNonEmptyList)
return 0;
if (!m_inputType->shouldRespectListAttribute())
return 0;
Element* element = treeScope()->getElementById(fastGetAttribute(listAttr));
if (!element)
return 0;
if (!element->hasTagName(datalistTag))
return 0;
return static_cast<HTMLDataListElement*>(element);
}
void HTMLInputElement::resetListAttributeTargetObserver()
{
if (inDocument())
m_listAttributeTargetObserver = ListAttributeTargetObserver::create(fastGetAttribute(listAttr), this);
else
m_listAttributeTargetObserver = nullptr;
}
void HTMLInputElement::listAttributeTargetChanged()
{
m_inputType->listAttributeTargetChanged();
}
*/
bool WMLInputElement::isSteppable() const
{
return false;//m_inputType->isSteppable();
}
bool WMLInputElement::isTextButton() const
{
return m_inputType->isTextButton();
}
bool WMLInputElement::isRadioButton() const
{
return m_inputType->isRadioButton();
}
bool WMLInputElement::isSearchField() const
{
return m_inputType->isSearchField();
}
bool WMLInputElement::isInputTypeHidden() const
{
return m_inputType->isHiddenType();
}
bool WMLInputElement::isPasswordField() const
{
return m_inputType->isPasswordField();
}
bool WMLInputElement::isCheckbox() const
{
return m_inputType->isCheckbox();
}
bool WMLInputElement::isRangeControl() const
{
return m_inputType->isRangeControl();
}
bool WMLInputElement::isColorControl() const
{
return m_inputType->isColorControl();
}
bool WMLInputElement::isText() const
{
return m_inputType->isTextType();
}
bool WMLInputElement::isEmailField() const
{
return m_inputType->isEmailField();
}
bool WMLInputElement::isFileUpload() const
{
return m_inputType->isFileUpload();
}
bool WMLInputElement::isImageButton() const
{
return m_inputType->isImageButton();
}
bool WMLInputElement::isNumberField() const
{
return m_inputType->isNumberField();
}
bool WMLInputElement::isSubmitButton() const
{
return m_inputType->isSubmitButton();
}
bool WMLInputElement::isTelephoneField() const
{
return m_inputType->isTelephoneField();
}
bool WMLInputElement::isURLField() const
{
return m_inputType->isURLField();
}
bool WMLInputElement::isDateField() const
{
return m_inputType->isDateField();
}
bool WMLInputElement::isDateTimeLocalField() const
{
return m_inputType->isDateTimeLocalField();
}
bool WMLInputElement::isMonthField() const
{
return m_inputType->isMonthField();
}
bool WMLInputElement::isTimeField() const
{
return m_inputType->isTimeField();
}
bool WMLInputElement::isWeekField() const
{
return m_inputType->isWeekField();
}
bool WMLInputElement::isEnumeratable() const
{
return m_inputType->isEnumeratable();
}
bool WMLInputElement::supportLabels() const
{
return m_inputType->supportLabels();
}
bool WMLInputElement::shouldAppearChecked() const
{
return m_inputType->isCheckable();
}
bool WMLInputElement::supportsPlaceholder() const
{
return m_inputType->supportsPlaceholder();
}
void WMLInputElement::updatePlaceholderText()
{
return m_inputType->updatePlaceholderText();
}
void WMLInputElement::parseMaxLengthAttribute(const AtomicString& value)
{
int maxLength;
if (!parseHTMLInteger(value, maxLength))
maxLength = maximumLength;
if (maxLength < 0 || maxLength > maximumLength)
maxLength = maximumLength;
int oldMaxLength = m_maxLength;
m_maxLength = maxLength;
if (oldMaxLength != maxLength)
updateValueIfNeeded();
setNeedsStyleRecalc();
setNeedsValidityCheck();
}
void WMLInputElement::updateValueIfNeeded()
{
String newValue = sanitizeValue(m_valueIfDirty);
ASSERT(!m_valueIfDirty.isNull() || newValue.isNull());
if (newValue != m_valueIfDirty)
setValue(newValue);
}
String WMLInputElement::defaultToolTip() const
{
return m_inputType->defaultToolTip();
}
bool WMLInputElement::shouldAppearIndeterminate() const
{
return false;//m_inputType->supportsIndeterminateAppearance() && indeterminate();
}
bool WMLInputElement::isInRequiredRadioButtonGroup()
{
/* ASSERT(isRadioButton());
if (CheckedRadioButtons* buttons = checkedRadioButtons())
return buttons->isInRequiredGroup(this);*/
return false;
}
WMLInputElement* WMLInputElement::checkedRadioButtonForGroup() const
{
/*
if (CheckedRadioButtons* buttons = checkedRadioButtons())
return buttons->checkedButtonForGroup(name());*/
return 0;
}
/*
CheckedRadioButtons* WMLInputElement::checkedRadioButtons() const
{
if (!isRadioButton())
return 0;
if (HTMLFormElement* formElement = form())
return &formElement->checkedRadioButtons();
if (inDocument())
return &document()->formController()->checkedRadioButtons();
return 0;
}
inline void WMLInputElement::addToRadioButtonGroup()
{
if (CheckedRadioButtons* buttons = checkedRadioButtons())
buttons->addButton(this);
}
inline void HTMLInputElement::removeFromRadioButtonGroup()
{
if (CheckedRadioButtons* buttons = checkedRadioButtons())
buttons->removeButton(this);
}*/
unsigned WMLInputElement::height() const
{
return m_inputType->height();
}
unsigned WMLInputElement::width() const
{
return m_inputType->width();
}
void WMLInputElement::setHeight(unsigned height)
{
setAttribute(HTMLNames::heightAttr, String::number(height));
}
void WMLInputElement::setWidth(unsigned width)
{
setAttribute(HTMLNames::widthAttr, String::number(width));
}
/PassOwnPtr ListAttributeTargetObserver::create(const AtomicString& id, HTMLInputElement element)
{
return adoptPtr(new ListAttributeTargetObserver(id, element));
}
-
ListAttributeTargetObserver::ListAttributeTargetObserver(const AtomicString& id, HTMLInputElement* element)
-
IdTargetObserver(element->treeScope()->idTargetObserverRegistry(), id)
, m_element(element)
{
}
void ListAttributeTargetObserver::idTargetChanged()
{
m_element->listAttributeTargetChanged();
}*/
void WMLInputElement::setRangeText(const String& replacement, ExceptionState& es)
{
if (!m_inputType->supportsSelectionAPI()) {
es.throwDOMException(InvalidStateError);
return;
}
WMLFormControlElement::setRangeText(replacement, es);
}
void WMLInputElement::setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState& es)
{
if (!m_inputType->supportsSelectionAPI()) {
es.throwDOMException(InvalidStateError);
return;
}
WMLFormControlElement::setRangeText(replacement, start, end, selectionMode, es);
}
bool WMLInputElement::supportsInputModeAttribute() const
{
return m_inputType->supportsInputModeAttribute();
}
Source/core/wml/WMLOptGroupElement.h
inline bool isWMLOptGroupElement(const Node* node)
{
return node->hasTagName(WMLNames::optgroupTag);
}
inline bool isWMLOptGroupElement(const Element* element)
{
return element->hasTagName(WMLNames::optgroupTag);
}
inline WMLOptGroupElement* toWMLOptGroupElement(Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || isWMLOptGroupElement(node));
return static_cast<WMLOptGroupElement*>(node);
}
Source/core/wml/WMLOptGroupElement.cpp
void WMLOptGroupElement::attach(const AttachContext& context)
{
if (parentNode()->renderStyle())
setRenderStyle(styleForRenderer());
WMLFormControlElement::attach(context);
}
void WMLOptGroupElement::detach(AttachContext& context)
{
m_style.clear();
WMLFormControlElement::detach(context);
}
Source/core/wml/WMLOptionElement.h
inline WMLOptionElement* toWMLOptionElement(Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(WMLNames::optionTag));
return static_cast<WMLOptionElement*>(node);
}
inline const WMLOptionElement* toWMLOptionElement(const Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(WMLNames::optionTag));
return static_cast<const WMLOptionElement*>(node);
}
Source/core/wml/WMLOptionElement.cpp
void WMLOptionElement::attach(const AttachContext& context)
{
if (parentNode()->renderStyle())
setRenderStyle(styleForRenderer());
WMLFormControlElement::attach(context);
}
void WMLOptionElement::detach(AttachContext& context)
{
m_style.clear();
WMLFormControlElement::detach(context);
}