root/Source/core/html/forms/BaseMultipleFieldsDateAndTimeInputType.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. m_hasSecond
  2. visitLiteral
  3. visitField
  4. validateFormat
  5. dateTimeEditElement
  6. spinButtonElement
  7. clearButtonElement
  8. pickerIndicatorElement
  9. containsFocusedShadowElement
  10. didBlurFromControl
  11. didFocusOnControl
  12. editControlValueChanged
  13. hasCustomFocusLogic
  14. isEditControlOwnerDisabled
  15. isEditControlOwnerReadOnly
  16. focusAndSelectSpinButtonOwner
  17. shouldSpinButtonRespondToMouseEvents
  18. shouldSpinButtonRespondToWheelEvents
  19. spinButtonStepDown
  20. spinButtonStepUp
  21. isPickerIndicatorOwnerDisabledOrReadOnly
  22. pickerIndicatorChooseValue
  23. pickerIndicatorChooseValue
  24. setupDateTimeChooserParameters
  25. m_pickerIndicatorIsAlwaysVisible
  26. badInputText
  27. blur
  28. customStyleForRenderer
  29. createShadowSubtree
  30. destroyShadowSubtree
  31. handleFocusEvent
  32. forwardEvent
  33. disabledAttributeChanged
  34. requiredAttributeChanged
  35. handleKeydownEvent
  36. hasBadInput
  37. localeIdentifier
  38. minOrMaxAttributeChanged
  39. readonlyAttributeChanged
  40. restoreFormControlState
  41. saveFormControlState
  42. setValue
  43. shouldUseInputMethod
  44. stepAttributeChanged
  45. updateView
  46. valueAttributeChanged
  47. listAttributeTargetChanged
  48. updatePickerIndicatorVisibility
  49. hidePickerIndicator
  50. showPickerIndicator
  51. shouldHaveSecondField
  52. focusAndSelectClearButtonOwner
  53. shouldClearButtonRespondToMouseEvents
  54. clearValue
  55. updateClearButtonVisibility

/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
#include "core/html/forms/BaseMultipleFieldsDateAndTimeInputType.h"

#include "CSSValueKeywords.h"
#include "RuntimeEnabledFeatures.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/events/KeyboardEvent.h"
#include "core/html/HTMLDataListElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLOptionElement.h"
#include "core/html/forms/DateTimeFieldsState.h"
#include "core/html/forms/FormController.h"
#include "core/html/shadow/ShadowElementNames.h"
#include "core/page/FocusController.h"
#include "core/page/Page.h"
#include "core/rendering/RenderTheme.h"
#include "platform/DateComponents.h"
#include "platform/text/DateTimeFormat.h"
#include "platform/text/PlatformLocale.h"
#include "wtf/DateMath.h"

namespace WebCore {

class DateTimeFormatValidator : public DateTimeFormat::TokenHandler {
public:
    DateTimeFormatValidator()
        : m_hasYear(false)
        , m_hasMonth(false)
        , m_hasWeek(false)
        , m_hasDay(false)
        , m_hasAMPM(false)
        , m_hasHour(false)
        , m_hasMinute(false)
        , m_hasSecond(false) { }

    virtual void visitField(DateTimeFormat::FieldType, int) OVERRIDE FINAL;
    virtual void visitLiteral(const String&) OVERRIDE FINAL { }

    bool validateFormat(const String& format, const BaseMultipleFieldsDateAndTimeInputType&);

private:
    bool m_hasYear;
    bool m_hasMonth;
    bool m_hasWeek;
    bool m_hasDay;
    bool m_hasAMPM;
    bool m_hasHour;
    bool m_hasMinute;
    bool m_hasSecond;
};

void DateTimeFormatValidator::visitField(DateTimeFormat::FieldType fieldType, int)
{
    switch (fieldType) {
    case DateTimeFormat::FieldTypeYear:
        m_hasYear = true;
        break;
    case DateTimeFormat::FieldTypeMonth: // Fallthrough.
    case DateTimeFormat::FieldTypeMonthStandAlone:
        m_hasMonth = true;
        break;
    case DateTimeFormat::FieldTypeWeekOfYear:
        m_hasWeek = true;
        break;
    case DateTimeFormat::FieldTypeDayOfMonth:
        m_hasDay = true;
        break;
    case DateTimeFormat::FieldTypePeriod:
        m_hasAMPM = true;
        break;
    case DateTimeFormat::FieldTypeHour11: // Fallthrough.
    case DateTimeFormat::FieldTypeHour12:
        m_hasHour = true;
        break;
    case DateTimeFormat::FieldTypeHour23: // Fallthrough.
    case DateTimeFormat::FieldTypeHour24:
        m_hasHour = true;
        m_hasAMPM = true;
        break;
    case DateTimeFormat::FieldTypeMinute:
        m_hasMinute = true;
        break;
    case DateTimeFormat::FieldTypeSecond:
        m_hasSecond = true;
        break;
    default:
        break;
    }
}

bool DateTimeFormatValidator::validateFormat(const String& format, const BaseMultipleFieldsDateAndTimeInputType& inputType)
{
    if (!DateTimeFormat::parse(format, *this))
        return false;
    return inputType.isValidFormat(m_hasYear, m_hasMonth, m_hasWeek, m_hasDay, m_hasAMPM, m_hasHour, m_hasMinute, m_hasSecond);
}

DateTimeEditElement* BaseMultipleFieldsDateAndTimeInputType::dateTimeEditElement() const
{
    return toDateTimeEditElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::dateTimeEdit()));
}

SpinButtonElement* BaseMultipleFieldsDateAndTimeInputType::spinButtonElement() const
{
    return toSpinButtonElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::spinButton()));
}

ClearButtonElement* BaseMultipleFieldsDateAndTimeInputType::clearButtonElement() const
{
    return toClearButtonElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::clearButton()));
}

PickerIndicatorElement* BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorElement() const
{
    return toPickerIndicatorElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::pickerIndicator()));
}

inline bool BaseMultipleFieldsDateAndTimeInputType::containsFocusedShadowElement() const
{
    return element().userAgentShadowRoot()->contains(element().document().focusedElement());
}

void BaseMultipleFieldsDateAndTimeInputType::didBlurFromControl()
{
    // We don't need to call blur(). This function is called when control
    // lost focus.

    if (containsFocusedShadowElement())
        return;
    RefPtr<HTMLInputElement> protector(element());
    // Remove focus ring by CSS "focus" pseudo class.
    element().setFocus(false);
}

void BaseMultipleFieldsDateAndTimeInputType::didFocusOnControl()
{
    // We don't need to call focus(). This function is called when control
    // got focus.

    if (!containsFocusedShadowElement())
        return;
    // Add focus ring by CSS "focus" pseudo class.
    // FIXME: Setting the focus flag to non-focused element is too tricky.
    element().setFocus(true);
}

void BaseMultipleFieldsDateAndTimeInputType::editControlValueChanged()
{
    RefPtr<HTMLInputElement> input(element());
    String oldValue = input->value();
    String newValue = sanitizeValue(dateTimeEditElement()->value());
    // Even if oldValue is null and newValue is "", we should assume they are same.
    if ((oldValue.isEmpty() && newValue.isEmpty()) || oldValue == newValue) {
        input->setNeedsValidityCheck();
    } else {
        input->setValueInternal(newValue, DispatchNoEvent);
        input->setNeedsStyleRecalc(SubtreeStyleChange);
        input->dispatchFormControlInputEvent();
        input->dispatchFormControlChangeEvent();
    }
    input->notifyFormStateChanged();
    input->updateClearButtonVisibility();
}

bool BaseMultipleFieldsDateAndTimeInputType::hasCustomFocusLogic() const
{
    return false;
}

bool BaseMultipleFieldsDateAndTimeInputType::isEditControlOwnerDisabled() const
{
    return element().isDisabledFormControl();
}

bool BaseMultipleFieldsDateAndTimeInputType::isEditControlOwnerReadOnly() const
{
    return element().isReadOnly();
}

void BaseMultipleFieldsDateAndTimeInputType::focusAndSelectSpinButtonOwner()
{
    if (DateTimeEditElement* edit = dateTimeEditElement())
        edit->focusIfNoFocus();
}

bool BaseMultipleFieldsDateAndTimeInputType::shouldSpinButtonRespondToMouseEvents()
{
    return !element().isDisabledOrReadOnly();
}

bool BaseMultipleFieldsDateAndTimeInputType::shouldSpinButtonRespondToWheelEvents()
{
    if (!shouldSpinButtonRespondToMouseEvents())
        return false;
    if (DateTimeEditElement* edit = dateTimeEditElement())
        return edit->hasFocusedField();
    return false;
}

void BaseMultipleFieldsDateAndTimeInputType::spinButtonStepDown()
{
    if (DateTimeEditElement* edit = dateTimeEditElement())
        edit->stepDown();
}

void BaseMultipleFieldsDateAndTimeInputType::spinButtonStepUp()
{
    if (DateTimeEditElement* edit = dateTimeEditElement())
        edit->stepUp();
}

bool BaseMultipleFieldsDateAndTimeInputType::isPickerIndicatorOwnerDisabledOrReadOnly() const
{
    return element().isDisabledOrReadOnly();
}

void BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorChooseValue(const String& value)
{
    if (element().isValidValue(value)) {
        element().setValue(value, DispatchInputAndChangeEvent);
        return;
    }

    DateTimeEditElement* edit = this->dateTimeEditElement();
    if (!edit)
        return;
    DateComponents date;
    unsigned end;
    if (date.parseDate(value, 0, end) && end == value.length())
        edit->setOnlyYearMonthDay(date);
}

void BaseMultipleFieldsDateAndTimeInputType::pickerIndicatorChooseValue(double value)
{
    ASSERT(std::isfinite(value) || std::isnan(value));
    if (std::isnan(value))
        element().setValue(emptyString(), DispatchInputAndChangeEvent);
    else
        element().setValueAsNumber(value, ASSERT_NO_EXCEPTION, DispatchInputAndChangeEvent);
}

bool BaseMultipleFieldsDateAndTimeInputType::setupDateTimeChooserParameters(DateTimeChooserParameters& parameters)
{
    return element().setupDateTimeChooserParameters(parameters);
}

BaseMultipleFieldsDateAndTimeInputType::BaseMultipleFieldsDateAndTimeInputType(HTMLInputElement& element)
    : BaseDateAndTimeInputType(element)
    , m_isDestroyingShadowSubtree(false)
    , m_pickerIndicatorIsVisible(false)
    , m_pickerIndicatorIsAlwaysVisible(false)
{
}

BaseMultipleFieldsDateAndTimeInputType::~BaseMultipleFieldsDateAndTimeInputType()
{
    if (SpinButtonElement* element = spinButtonElement())
        element->removeSpinButtonOwner();
    if (ClearButtonElement* element = clearButtonElement())
        element->removeClearButtonOwner();
    if (DateTimeEditElement* element = dateTimeEditElement())
        element->removeEditControlOwner();
    if (PickerIndicatorElement* element = pickerIndicatorElement())
        element->removePickerIndicatorOwner();
}

String BaseMultipleFieldsDateAndTimeInputType::badInputText() const
{
    return locale().queryString(blink::WebLocalizedString::ValidationBadInputForDateTime);
}

void BaseMultipleFieldsDateAndTimeInputType::blur()
{
    if (DateTimeEditElement* edit = dateTimeEditElement())
        edit->blurByOwner();
}

PassRefPtr<RenderStyle> BaseMultipleFieldsDateAndTimeInputType::customStyleForRenderer(PassRefPtr<RenderStyle> originalStyle)
{
    EDisplay originalDisplay = originalStyle->display();
    EDisplay newDisplay = originalDisplay;
    if (originalDisplay == INLINE || originalDisplay == INLINE_BLOCK)
        newDisplay = INLINE_FLEX;
    else if (originalDisplay == BLOCK)
        newDisplay = FLEX;
    TextDirection contentDirection = element().locale().isRTL() ? RTL : LTR;
    if (originalStyle->direction() == contentDirection && originalDisplay == newDisplay)
        return originalStyle;

    RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get());
    style->setDirection(contentDirection);
    style->setDisplay(newDisplay);
    style->setUnique();
    return style.release();
}

void BaseMultipleFieldsDateAndTimeInputType::createShadowSubtree()
{
    ASSERT(element().shadow());

    // Element must not have a renderer here, because if it did
    // DateTimeEditElement::customStyleForRenderer() is called in appendChild()
    // before the field wrapper element is created.
    // FIXME: This code should not depend on such craziness.
    ASSERT(!element().renderer());

    Document& document = element().document();
    ContainerNode* container = element().userAgentShadowRoot();

    container->appendChild(DateTimeEditElement::create(document, *this));
    element().updateView();
    container->appendChild(ClearButtonElement::create(document, *this));
    container->appendChild(SpinButtonElement::create(document, *this));

    if (RenderTheme::theme().supportsCalendarPicker(formControlType()))
        m_pickerIndicatorIsAlwaysVisible = true;
    container->appendChild(PickerIndicatorElement::create(document, *this));
    m_pickerIndicatorIsVisible = true;
    updatePickerIndicatorVisibility();
}

void BaseMultipleFieldsDateAndTimeInputType::destroyShadowSubtree()
{
    ASSERT(!m_isDestroyingShadowSubtree);
    m_isDestroyingShadowSubtree = true;
    if (SpinButtonElement* element = spinButtonElement())
        element->removeSpinButtonOwner();
    if (ClearButtonElement* element = clearButtonElement())
        element->removeClearButtonOwner();
    if (DateTimeEditElement* element = dateTimeEditElement())
        element->removeEditControlOwner();
    if (PickerIndicatorElement* element = pickerIndicatorElement())
        element->removePickerIndicatorOwner();

    // If a field element has focus, set focus back to the <input> itself before
    // deleting the field. This prevents unnecessary focusout/blur events.
    if (containsFocusedShadowElement())
        element().focus();

    BaseDateAndTimeInputType::destroyShadowSubtree();
    m_isDestroyingShadowSubtree = false;
}

void BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent(Element* oldFocusedElement, FocusType type)
{
    DateTimeEditElement* edit = dateTimeEditElement();
    if (!edit || m_isDestroyingShadowSubtree)
        return;
    if (type == FocusTypeBackward) {
        if (element().document().page())
            element().document().page()->focusController().advanceFocus(type);
    } else if (type == FocusTypeNone || type == FocusTypeMouse || type == FocusTypePage) {
        edit->focusByOwner(oldFocusedElement);
    } else {
        edit->focusByOwner();
    }
}

void BaseMultipleFieldsDateAndTimeInputType::forwardEvent(Event* event)
{
    if (SpinButtonElement* element = spinButtonElement()) {
        element->forwardEvent(event);
        if (event->defaultHandled())
            return;
    }

    if (DateTimeEditElement* edit = dateTimeEditElement())
        edit->defaultEventHandler(event);
}

void BaseMultipleFieldsDateAndTimeInputType::disabledAttributeChanged()
{
    spinButtonElement()->releaseCapture();
    clearButtonElement()->releaseCapture();
    if (DateTimeEditElement* edit = dateTimeEditElement())
        edit->disabledStateChanged();
}

void BaseMultipleFieldsDateAndTimeInputType::requiredAttributeChanged()
{
    clearButtonElement()->releaseCapture();
    updateClearButtonVisibility();
}

void BaseMultipleFieldsDateAndTimeInputType::handleKeydownEvent(KeyboardEvent* event)
{
    if (m_pickerIndicatorIsVisible
        && ((event->keyIdentifier() == "Down" && event->getModifierState("Alt")) || (RenderTheme::theme().shouldOpenPickerWithF4Key() && event->keyIdentifier() == "F4"))) {
        if (PickerIndicatorElement* element = pickerIndicatorElement())
            element->openPopup();
        event->setDefaultHandled();
    } else {
        forwardEvent(event);
    }
}

bool BaseMultipleFieldsDateAndTimeInputType::hasBadInput() const
{
    DateTimeEditElement* edit = dateTimeEditElement();
    return element().value().isEmpty() && edit && edit->anyEditableFieldsHaveValues();
}

AtomicString BaseMultipleFieldsDateAndTimeInputType::localeIdentifier() const
{
    return element().computeInheritedLanguage();
}

void BaseMultipleFieldsDateAndTimeInputType::minOrMaxAttributeChanged()
{
    updateView();
}

void BaseMultipleFieldsDateAndTimeInputType::readonlyAttributeChanged()
{
    spinButtonElement()->releaseCapture();
    clearButtonElement()->releaseCapture();
    if (DateTimeEditElement* edit = dateTimeEditElement())
        edit->readOnlyStateChanged();
}

void BaseMultipleFieldsDateAndTimeInputType::restoreFormControlState(const FormControlState& state)
{
    DateTimeEditElement* edit = dateTimeEditElement();
    if (!edit)
        return;
    DateTimeFieldsState dateTimeFieldsState = DateTimeFieldsState::restoreFormControlState(state);
    edit->setValueAsDateTimeFieldsState(dateTimeFieldsState);
    element().setValueInternal(sanitizeValue(edit->value()), DispatchNoEvent);
    updateClearButtonVisibility();
}

FormControlState BaseMultipleFieldsDateAndTimeInputType::saveFormControlState() const
{
    if (DateTimeEditElement* edit = dateTimeEditElement())
        return edit->valueAsDateTimeFieldsState().saveFormControlState();
    return FormControlState();
}

void BaseMultipleFieldsDateAndTimeInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
{
    InputType::setValue(sanitizedValue, valueChanged, eventBehavior);
    DateTimeEditElement* edit = dateTimeEditElement();
    if (valueChanged || (sanitizedValue.isEmpty() && edit && edit->anyEditableFieldsHaveValues())) {
        element().updateView();
        element().setNeedsValidityCheck();
    }
}

bool BaseMultipleFieldsDateAndTimeInputType::shouldUseInputMethod() const
{
    return false;
}

void BaseMultipleFieldsDateAndTimeInputType::stepAttributeChanged()
{
    updateView();
}

void BaseMultipleFieldsDateAndTimeInputType::updateView()
{
    DateTimeEditElement* edit = dateTimeEditElement();
    if (!edit)
        return;

    DateTimeEditElement::LayoutParameters layoutParameters(element().locale(), createStepRange(AnyIsDefaultStep));

    DateComponents date;
    bool hasValue = false;
    if (!element().suggestedValue().isNull())
        hasValue = parseToDateComponents(element().suggestedValue(), &date);
    else
        hasValue = parseToDateComponents(element().value(), &date);
    if (!hasValue)
        setMillisecondToDateComponents(layoutParameters.stepRange.minimum().toDouble(), &date);

    setupLayoutParameters(layoutParameters, date);

    const AtomicString pattern = edit->fastGetAttribute(HTMLNames::patternAttr);
    if (!pattern.isEmpty())
        layoutParameters.dateTimeFormat = pattern;

    if (!DateTimeFormatValidator().validateFormat(layoutParameters.dateTimeFormat, *this))
        layoutParameters.dateTimeFormat = layoutParameters.fallbackDateTimeFormat;

    if (hasValue)
        edit->setValueAsDate(layoutParameters, date);
    else
        edit->setEmptyValue(layoutParameters, date);
    updateClearButtonVisibility();
}

void BaseMultipleFieldsDateAndTimeInputType::valueAttributeChanged()
{
    if (!element().hasDirtyValue())
        updateView();
}

void BaseMultipleFieldsDateAndTimeInputType::listAttributeTargetChanged()
{
    updatePickerIndicatorVisibility();
}

void BaseMultipleFieldsDateAndTimeInputType::updatePickerIndicatorVisibility()
{
    if (m_pickerIndicatorIsAlwaysVisible) {
        showPickerIndicator();
        return;
    }
    if (element().hasValidDataListOptions())
        showPickerIndicator();
    else
        hidePickerIndicator();
}

void BaseMultipleFieldsDateAndTimeInputType::hidePickerIndicator()
{
    if (!m_pickerIndicatorIsVisible)
        return;
    m_pickerIndicatorIsVisible = false;
    ASSERT(pickerIndicatorElement());
    pickerIndicatorElement()->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
}

void BaseMultipleFieldsDateAndTimeInputType::showPickerIndicator()
{
    if (m_pickerIndicatorIsVisible)
        return;
    m_pickerIndicatorIsVisible = true;
    ASSERT(pickerIndicatorElement());
    pickerIndicatorElement()->removeInlineStyleProperty(CSSPropertyDisplay);
}

bool BaseMultipleFieldsDateAndTimeInputType::shouldHaveSecondField(const DateComponents& date) const
{
    StepRange stepRange = createStepRange(AnyIsDefaultStep);
    return date.second() || date.millisecond()
        || !stepRange.minimum().remainder(static_cast<int>(msPerMinute)).isZero()
        || !stepRange.step().remainder(static_cast<int>(msPerMinute)).isZero();
}

void BaseMultipleFieldsDateAndTimeInputType::focusAndSelectClearButtonOwner()
{
    element().focus();
}

bool BaseMultipleFieldsDateAndTimeInputType::shouldClearButtonRespondToMouseEvents()
{
    return !element().isDisabledOrReadOnly() && !element().isRequired();
}

void BaseMultipleFieldsDateAndTimeInputType::clearValue()
{
    RefPtr<HTMLInputElement> input(element());
    input->setValue("", DispatchInputAndChangeEvent);
    input->updateClearButtonVisibility();
}

void BaseMultipleFieldsDateAndTimeInputType::updateClearButtonVisibility()
{
    ClearButtonElement* clearButton = clearButtonElement();
    if (!clearButton)
        return;

    if (element().isRequired() || !dateTimeEditElement()->anyEditableFieldsHaveValues()) {
        clearButton->setInlineStyleProperty(CSSPropertyOpacity, 0.0, CSSPrimitiveValue::CSS_NUMBER);
        clearButton->setInlineStyleProperty(CSSPropertyPointerEvents, CSSValueNone);
    } else {
        clearButton->removeInlineStyleProperty(CSSPropertyOpacity);
        clearButton->removeInlineStyleProperty(CSSPropertyPointerEvents);
    }
}

} // namespace WebCore

#endif

/* [<][>][^][v][top][bottom][index][help] */