void SearchFieldCancelButtonElement::defaultEventHandler(Event* event) { // If the element is visible, on mouseup, clear the value, and set selection HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode()); if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { if (renderer() && renderer()->visibleToHitTesting()) { if (Frame* frame = document()->frame()) { frame->eventHandler()->setCapturingMouseEventsNode(this); m_capturing = true; } } input->focus(); input->select(); event->setDefaultHandled(); } if (event->type() == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { if (m_capturing && renderer() && renderer()->visibleToHitTesting()) { if (Frame* frame = document()->frame()) { frame->eventHandler()->setCapturingMouseEventsNode(0); m_capturing = false; } #if !PLATFORM(OLYMPIA) // FIXME: It's always false on OLYMPIA platform. This problem depends on RIM bug #1067. if (hovered()) { #else if (event->target() == this) { #endif RefPtr<HTMLInputElement> protector(input); String oldValue = input->value(); input->setValue(""); if (!oldValue.isEmpty()) { toRenderTextControl(input->renderer())->setChangedSinceLastChangeEvent(true); input->dispatchEvent(Event::create(eventNames().inputEvent, true, false)); } input->onSearch(); event->setDefaultHandled(); } } } if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); } // ---------------------------- inline SpinButtonElement::SpinButtonElement(HTMLElement* shadowParent) : TextControlInnerElement(shadowParent->document(), shadowParent) , m_capturing(false) , m_upDownState(Indeterminate) , m_pressStartingState(Indeterminate) , m_repeatingTimer(this, &SpinButtonElement::repeatingTimerFired) { } PassRefPtr<SpinButtonElement> SpinButtonElement::create(HTMLElement* shadowParent) { return adoptRef(new SpinButtonElement(shadowParent)); } void SpinButtonElement::defaultEventHandler(Event* event) { if (!event->isMouseEvent()) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } RenderBox* box = renderBox(); if (!box) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode()); if (input->disabled() || input->isReadOnlyFormControl()) { if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); return; } MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent->absoluteLocation(), false, true)); if (mouseEvent->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) { if (box->borderBoxRect().contains(local)) { RefPtr<Node> protector(input); input->focus(); input->select(); input->stepUpFromRenderer(m_upDownState == Up ? 1 : -1); event->setDefaultHandled(); startRepeatingTimer(); } } else if (mouseEvent->type() == eventNames().mouseupEvent && mouseEvent->button() == LeftButton) stopRepeatingTimer(); else if (event->type() == eventNames().mousemoveEvent) { if (box->borderBoxRect().contains(local)) { if (!m_capturing) { if (Frame* frame = document()->frame()) { frame->eventHandler()->setCapturingMouseEventsNode(this); m_capturing = true; } } UpDownState oldUpDownState = m_upDownState; m_upDownState = local.y() < box->height() / 2 ? Up : Down; if (m_upDownState != oldUpDownState) renderer()->repaint(); } else { if (m_capturing) { stopRepeatingTimer(); if (Frame* frame = document()->frame()) { frame->eventHandler()->setCapturingMouseEventsNode(0); m_capturing = false; } } } } if (!event->defaultHandled()) HTMLDivElement::defaultEventHandler(event); } void SpinButtonElement::startRepeatingTimer() { m_pressStartingState = m_upDownState; ScrollbarTheme* theme = ScrollbarTheme::nativeTheme(); m_repeatingTimer.start(theme->initialAutoscrollTimerDelay(), theme->autoscrollTimerDelay()); }
bool SliderThumbElement::matchesReadWritePseudoClass() const { HTMLInputElement* input = hostInput(); return input && input->matchesReadWritePseudoClass(); }
uint64_t HTMLTextFieldAccessible::NativeState() const { uint64_t state = HyperTextAccessibleWrap::NativeState(); // Text fields are always editable, even if they are also read only or // disabled. state |= states::EDITABLE; // can be focusable, focused, protected. readonly, unavailable, selected if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type, nsGkAtoms::password, eIgnoreCase)) { state |= states::PROTECTED; } if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly)) { state |= states::READONLY; } // Is it an <input> or a <textarea> ? HTMLInputElement* input = HTMLInputElement::FromNode(mContent); state |= input && input->IsSingleLineTextControl() ? states::SINGLE_LINE : states::MULTI_LINE; if (state & (states::PROTECTED | states::MULTI_LINE | states::READONLY | states::UNAVAILABLE)) return state; // Expose autocomplete states if this input is part of autocomplete widget. Accessible* widget = ContainerWidget(); if (widget && widget-IsAutoComplete()) { state |= states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION; return state; } // Expose autocomplete state if it has associated autocomplete list. if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::list_)) return state | states::SUPPORTS_AUTOCOMPLETION | states::HASPOPUP; // Ordinal XUL textboxes don't support autocomplete. if (!BindingParent() && Preferences::GetBool("browser.formfill.enable")) { // Check to see if autocompletion is allowed on this input. We don't expose // it for password fields even though the entire password can be remembered // for a page if the user asks it to be. However, the kind of autocomplete // we're talking here is based on what the user types, where a popup of // possible choices comes up. nsAutoString autocomplete; mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::autocomplete, autocomplete); if (!autocomplete.LowerCaseEqualsLiteral("off")) { Element* formElement = input->GetFormElement(); if (formElement) { formElement->GetAttr(kNameSpaceID_None, nsGkAtoms::autocomplete, autocomplete); } if (!formElement || !autocomplete.LowerCaseEqualsLiteral("off")) state |= states::SUPPORTS_AUTOCOMPLETION; } } return state; }
nsresult nsNumberControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements) { nsresult rv; // We create an anonymous tree for our input element that is structured as // follows: // // input // div - outer wrapper with "display:flex" by default // input - text input field // div - spin box wrapping up/down arrow buttons // div - spin up (up arrow button) // div - spin down (down arrow button) // // If you change this, be careful to change the destruction order in // nsNumberControlFrame::DestroyFrom. // Create the anonymous outer wrapper: rv = MakeAnonymousElement(getter_AddRefs(mOuterWrapper), aElements, nsGkAtoms::div, nsCSSPseudoElements::ePseudo_mozNumberWrapper, mStyleContext); NS_ENSURE_SUCCESS(rv, rv); ContentInfo& outerWrapperCI = aElements.LastElement(); // Create the ::-moz-number-text pseudo-element: rv = MakeAnonymousElement(getter_AddRefs(mTextField), outerWrapperCI.mChildren, nsGkAtoms::input, nsCSSPseudoElements::ePseudo_mozNumberText, outerWrapperCI.mStyleContext); NS_ENSURE_SUCCESS(rv, rv); mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::type, NS_LITERAL_STRING("text"), PR_FALSE); HTMLInputElement* content = HTMLInputElement::FromContent(mContent); HTMLInputElement* textField = HTMLInputElement::FromContent(mTextField); // Initialize the text field value: nsAutoString value; content->GetValue(value); SetValueOfAnonTextControl(value); // If we're readonly, make sure our anonymous text control is too: nsAutoString readonly; if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly)) { mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly, false); } // Propogate our tabindex: int32_t tabIndex; content->GetTabIndex(&tabIndex); textField->SetTabIndex(tabIndex); // Initialize the text field's placeholder, if ours is set: nsAutoString placeholder; if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, placeholder)) { mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, placeholder, false); } if (mContent->AsElement()->State().HasState(NS_EVENT_STATE_FOCUS)) { // We don't want to focus the frame but the text field. nsIFocusManager* fm = nsFocusManager::GetFocusManager(); nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mTextField); NS_ASSERTION(element, "Really, this should be a nsIDOMElement!"); fm->SetFocus(element, 0); } if (StyleDisplay()->mAppearance == NS_THEME_TEXTFIELD) { // The author has elected to hide the spinner by setting this // -moz-appearance. We will reframe if it changes. return rv; } // Create the ::-moz-number-spin-box pseudo-element: rv = MakeAnonymousElement(getter_AddRefs(mSpinBox), outerWrapperCI.mChildren, nsGkAtoms::div, nsCSSPseudoElements::ePseudo_mozNumberSpinBox, outerWrapperCI.mStyleContext); NS_ENSURE_SUCCESS(rv, rv); ContentInfo& spinBoxCI = outerWrapperCI.mChildren.LastElement(); // Create the ::-moz-number-spin-up pseudo-element: rv = MakeAnonymousElement(getter_AddRefs(mSpinUp), spinBoxCI.mChildren, nsGkAtoms::div, nsCSSPseudoElements::ePseudo_mozNumberSpinUp, spinBoxCI.mStyleContext); NS_ENSURE_SUCCESS(rv, rv); // Create the ::-moz-number-spin-down pseudo-element: rv = MakeAnonymousElement(getter_AddRefs(mSpinDown), spinBoxCI.mChildren, nsGkAtoms::div, nsCSSPseudoElements::ePseudo_mozNumberSpinDown, spinBoxCI.mStyleContext); SyncDisabledState(); return rv; }
PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, PassRefPtr<Event> event, bool lockHistory, FormSubmissionTrigger trigger) { ASSERT(form); HTMLFormControlElement* submitButton = 0; if (event && event->target() && event->target()->toNode()) submitButton = static_cast<HTMLFormControlElement*>(event->target()->toNode()); FormSubmission::Attributes copiedAttributes; copiedAttributes.copyFrom(attributes); if (submitButton) { String attributeValue; if (!(attributeValue = submitButton->getAttribute(formactionAttr)).isNull()) copiedAttributes.parseAction(attributeValue); if (!(attributeValue = submitButton->getAttribute(formenctypeAttr)).isNull()) copiedAttributes.updateEncodingType(attributeValue); if (!(attributeValue = submitButton->getAttribute(formmethodAttr)).isNull()) copiedAttributes.updateMethodType(attributeValue); if (!(attributeValue = submitButton->getAttribute(formtargetAttr)).isNull()) copiedAttributes.setTarget(attributeValue); } Document* document = form->document(); KURL actionURL = document->completeURL(copiedAttributes.action().isEmpty() ? document->url().string() : copiedAttributes.action()); bool isMailtoForm = actionURL.protocolIs("mailto"); bool isMultiPartForm = false; String encodingType = copiedAttributes.encodingType(); if (copiedAttributes.method() == PostMethod) { isMultiPartForm = copiedAttributes.isMultiPartForm(); if (isMultiPartForm && isMailtoForm) { encodingType = "application/x-www-form-urlencoded"; isMultiPartForm = false; } } TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataBuilder::encodingFromAcceptCharset(copiedAttributes.acceptCharset(), document); RefPtr<DOMFormData> domFormData = DOMFormData::create(dataEncoding.encodingForFormSubmission()); Vector<pair<String, String> > formValues; for (unsigned i = 0; i < form->associatedElements().size(); ++i) { FormAssociatedElement* control = form->associatedElements()[i]; HTMLElement* element = toHTMLElement(control); if (!element->disabled()) control->appendFormData(*domFormData, isMultiPartForm); if (element->hasLocalName(inputTag)) { HTMLInputElement* input = static_cast<HTMLInputElement*>(control); if (input->isTextField()) { formValues.append(pair<String, String>(input->name().string(), input->value())); if (input->isSearchField()) input->addSearchResult(); } } } RefPtr<FormData> formData; String boundary; if (isMultiPartForm) { formData = FormData::createMultiPart(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding(), document); boundary = formData->boundary().data(); } else { formData = FormData::create(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding(), attributes.method() == GetMethod ? FormData::FormURLEncoded : FormData::parseEncodingType(encodingType)); if (copiedAttributes.method() == PostMethod && isMailtoForm) { // Convert the form data into a string that we put into the URL. appendMailtoPostFormDataToURL(actionURL, *formData, encodingType); formData = FormData::create(); } } formData->setIdentifier(generateFormDataIdentifier()); String targetOrBaseTarget = copiedAttributes.target().isEmpty() ? document->baseTarget() : copiedAttributes.target(); RefPtr<FormState> formState = FormState::create(form, formValues, document->frame(), trigger); return adoptRef(new FormSubmission(copiedAttributes.method(), actionURL, targetOrBaseTarget, encodingType, formState.release(), formData.release(), boundary, lockHistory, event)); }
void ChromeClientImpl::textFieldDataListChanged(HTMLInputElement& input) { WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(input.document().frame()); if (webframe->autofillClient()) webframe->autofillClient()->dataListOptionsChanged(WebInputElement(&input)); }
void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (style().visibility() != VISIBLE) return; // Push a clip. GraphicsContextStateSaver stateSaver(*paintInfo.context, false); if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) { IntRect clipRect = enclosingIntRect(LayoutRect(paintOffset.x() + borderLeft(), paintOffset.y() + borderTop(), width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop() + buttonShadowHeight)); if (clipRect.isEmpty()) return; stateSaver.save(); paintInfo.context->clip(clipRect); } if (paintInfo.phase == PaintPhaseForeground) { const String& displayedFilename = fileTextValue(); const Font& font = style().font(); TextRun textRun = constructTextRun(this, font, displayedFilename, style(), TextRun::AllowTrailingExpansion, RespectDirection | RespectDirectionOverride); textRun.disableRoundingHacks(); #if PLATFORM(IOS) int iconHeight = nodeHeight(uploadButton()); int iconWidth = iconHeight; #endif // Determine where the filename should be placed LayoutUnit contentLeft = paintOffset.x() + borderLeft() + paddingLeft(); HTMLInputElement* button = uploadButton(); if (!button) return; LayoutUnit buttonWidth = nodeWidth(button); LayoutUnit buttonAndIconWidth = buttonWidth + afterButtonSpacing + (inputElement().icon() ? iconWidth + iconFilenameSpacing : 0); LayoutUnit textX; if (style().isLeftToRightDirection()) textX = contentLeft + buttonAndIconWidth; else textX = contentLeft + contentWidth() - buttonAndIconWidth - font.width(textRun); LayoutUnit textY = 0; // We want to match the button's baseline // FIXME: Make this work with transforms. if (RenderButton* buttonRenderer = toRenderButton(button->renderer())) textY = paintOffset.y() + borderTop() + paddingTop() + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); else textY = baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); paintInfo.context->setFillColor(style().visitedDependentColor(CSSPropertyColor), style().colorSpace()); // Draw the filename paintInfo.context->drawBidiText(font, textRun, IntPoint(roundToInt(textX), roundToInt(textY))); if (inputElement().icon()) { // Determine where the icon should be placed LayoutUnit iconY = paintOffset.y() + borderTop() + paddingTop() + (contentHeight() - iconHeight) / 2; LayoutUnit iconX; if (style().isLeftToRightDirection()) iconX = contentLeft + buttonWidth + afterButtonSpacing; else iconX = contentLeft + contentWidth() - buttonWidth - afterButtonSpacing - iconWidth; #if PLATFORM(IOS) if (RenderButton* buttonRenderer = toRenderButton(button->renderer())) { // Draw the file icon and decorations. IntRect iconRect(iconX, iconY, iconWidth, iconHeight); RenderTheme::FileUploadDecorations decorationsType = inputElement().files()->length() == 1 ? RenderTheme::SingleFile : RenderTheme::MultipleFiles; theme().paintFileUploadIconDecorations(*this, *buttonRenderer, paintInfo, iconRect, inputElement().icon(), decorationsType); } #else // Draw the file icon inputElement().icon()->paint(paintInfo.context, IntRect(roundToInt(iconX), roundToInt(iconY), iconWidth, iconHeight)); #endif } } // Paint the children. RenderBlockFlow::paintObject(paintInfo, paintOffset); }
String RenderFileUploadControl::fileTextValue() const { HTMLInputElement* input = toHTMLInputElement(node()); ASSERT(input->files()); return RenderTheme::theme().fileListNameForWidth(input->locale(), input->files(), style()->font(), maxFilenameWidth()); }
void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockHistory, bool lockBackForwardList) { FrameView* view = document()->view(); Frame* frame = document()->frame(); if (!view || !frame) return; if (m_insubmit) { m_doingsubmit = true; return; } m_insubmit = true; HTMLFormControlElement* firstSuccessfulSubmitButton = 0; bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button? frame->loader()->clearRecordedFormValues(); frame->loader()->setFormAboutToBeSubmitted(this); for (unsigned i = 0; i < formElements.size(); ++i) { HTMLFormControlElement* control = formElements[i]; if (control->hasLocalName(inputTag)) { HTMLInputElement* input = static_cast<HTMLInputElement*>(control); if (input->isTextField()) { frame->loader()->recordFormValue(input->name(), input->value()); if (input->isSearchField()) input->addSearchResult(); } } if (needButtonActivation) { if (control->isActivatedSubmit()) needButtonActivation = false; else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton()) firstSuccessfulSubmitButton = control; } } if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(true); if (m_url.isEmpty()) m_url = document()->url().string(); if (m_formDataBuilder.isPostMethod()) { if (m_formDataBuilder.isMultiPartForm() && isMailtoForm()) { setEnctype("application/x-www-form-urlencoded"); ASSERT(!m_formDataBuilder.isMultiPartForm()); } if (!m_formDataBuilder.isMultiPartForm()) { RefPtr<FormData> data = createFormData(CString()); if (isMailtoForm()) { String body = data->flattenToString(); if (equalIgnoringCase(m_formDataBuilder.encodingType(), "text/plain")) { // Convention seems to be to decode, and s/&/\r\n/. Also, spaces are encoded as %20. body = decodeURLEscapeSequences(body.replace('&', "\r\n").replace('+', ' ') + "\r\n"); } Vector<char> bodyData; bodyData.append("body=", 5); FormDataBuilder::encodeStringAsFormData(bodyData, body.utf8()); data = FormData::create(String(bodyData.data(), bodyData.size()).replace('+', "%20").latin1()); } frame->loader()->submitForm("POST", m_url, data, m_target, m_formDataBuilder.encodingType(), String(), event, lockHistory, lockBackForwardList); } else { Vector<char> boundary = m_formDataBuilder.generateUniqueBoundaryString(); frame->loader()->submitForm("POST", m_url, createFormData(boundary.data()), m_target, m_formDataBuilder.encodingType(), boundary.data(), event, lockHistory, lockBackForwardList); } } else { m_formDataBuilder.setIsMultiPartForm(false); frame->loader()->submitForm("GET", m_url, createFormData(CString()), m_target, String(), String(), event, lockHistory, lockBackForwardList); } if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(false); m_doingsubmit = m_insubmit = false; }
void Chrome::setToolTip(const HitTestResult& result) { // First priority is a potential toolTip representing a spelling or grammar error TextDirection toolTipDirection; String toolTip = result.spellingToolTip(toolTipDirection); // Next priority is a toolTip from a URL beneath the mouse (if preference is set to show those). if (toolTip.isEmpty() && m_page->settings()->showsURLsInToolTips()) { if (Node* node = result.innerNonSharedNode()) { // Get tooltip representing form action, if relevant if (node->hasTagName(inputTag)) { HTMLInputElement* input = static_cast<HTMLInputElement*>(node); if (input->isSubmitButton()) if (HTMLFormElement* form = input->form()) { toolTip = form->action(); if (form->renderer()) toolTipDirection = form->renderer()->style()->direction(); else toolTipDirection = LTR; } } } // Get tooltip representing link's URL if (toolTip.isEmpty()) { // FIXME: Need to pass this URL through userVisibleString once that's in WebCore toolTip = result.absoluteLinkURL().string(); // URL always display as LTR. toolTipDirection = LTR; } } // Next we'll consider a tooltip for element with "title" attribute if (toolTip.isEmpty()) toolTip = result.title(toolTipDirection); // Lastly, for <input type="file"> that allow multiple files, we'll consider a tooltip for the selected filenames if (toolTip.isEmpty()) { if (Node* node = result.innerNonSharedNode()) { if (node->hasTagName(inputTag)) { HTMLInputElement* input = static_cast<HTMLInputElement*>(node); if (input->isFileUpload()) { FileList* files = input->files(); unsigned listSize = files->length(); if (files && listSize > 1) { Vector<UChar> names; for (size_t i = 0; i < listSize; ++i) { append(names, files->item(i)->fileName()); if (i != listSize - 1) names.append('\n'); } toolTip = String::adopt(names); // filename always display as LTR. toolTipDirection = LTR; } } } } } m_client->setToolTip(toolTip, toolTipDirection); }
// FIXME: Could share this with BaseCheckableInputType and RangeInputType if we had a common base class. void BaseClickableWithKeyInputType::accessKeyAction(HTMLInputElement& element, bool sendMouseEvents) { element.dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents); }
int RenderFileUploadControl::maxFilenameWidth() const { HTMLInputElement* input = toHTMLInputElement(node()); return max(0, contentBoxRect().pixelSnappedWidth() - nodeWidth(uploadButton()) - afterButtonSpacing - (input->icon() ? iconWidth + iconFilenameSpacing : 0)); }
TEST_F(InputMethodControllerTest, BackspaceFromEndOfInput) { document().write("<input id='sample'>"); HTMLInputElement* input = toHTMLInputElement(document().getElementById("sample")); document().updateLayout(); input->focus(); input->setValue("fooX"); controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_STREQ("fooX", input->value().utf8().data()); controller().extendSelectionAndDelete(1, 0); EXPECT_STREQ("foo", input->value().utf8().data()); input->setValue(String::fromUTF8("foo\xE2\x98\x85")); // U+2605 == "black star" controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_STREQ("foo\xE2\x98\x85", input->value().utf8().data()); controller().extendSelectionAndDelete(1, 0); EXPECT_STREQ("foo", input->value().utf8().data()); input->setValue(String::fromUTF8("foo\xF0\x9F\x8F\x86")); // U+1F3C6 == "trophy" controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_STREQ("foo\xF0\x9F\x8F\x86", input->value().utf8().data()); controller().extendSelectionAndDelete(1, 0); EXPECT_STREQ("foo", input->value().utf8().data()); input->setValue(String::fromUTF8("foo\xE0\xB8\x81\xE0\xB9\x89")); // composed U+0E01 "ka kai" + U+0E49 "mai tho" controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_STREQ("foo\xE0\xB8\x81\xE0\xB9\x89", input->value().utf8().data()); controller().extendSelectionAndDelete(1, 0); EXPECT_STREQ("foo", input->value().utf8().data()); }
RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement& input) : RenderBlockFlow(input) , m_canReceiveDroppedFiles(input.canReceiveDroppedFiles()) { }
void ChromeClientImpl::didEndEditingOnTextField(HTMLInputElement& inputElement) { WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(inputElement.document().frame()); if (webframe->autofillClient()) webframe->autofillClient()->textFieldDidEndEditing(WebInputElement(&inputElement)); }
RenderSlider::RenderSlider(HTMLInputElement& element, Ref<RenderStyle>&& style) : RenderFlexibleBox(element, WTFMove(style)) { // We assume RenderSlider works only with <input type=range>. ASSERT(element.isRangeControl()); }
void ChromeClientImpl::openTextDataListChooser(HTMLInputElement& input) { WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(input.document().frame()); if (webframe->autofillClient()) webframe->autofillClient()->openTextDataListChooser(WebInputElement(&input)); }
bool RenderFileUploadControl::allowsMultipleFiles() { HTMLInputElement* input = static_cast<HTMLInputElement*>(node()); return !input->getAttribute(multipleAttr).isNull(); }
bool nsIConstraintValidation::ReportValidity() { if (!IsCandidateForConstraintValidation() || IsValid()) { return true; } nsCOMPtr<nsIContent> content = do_QueryInterface(this); MOZ_ASSERT(content, "This class should be inherited by HTML elements only!"); bool defaultAction = true; nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content, NS_LITERAL_STRING("invalid"), false, true, &defaultAction); if (!defaultAction) { return false; } nsCOMPtr<nsIObserverService> service = mozilla::services::GetObserverService(); if (!service) { NS_WARNING("No observer service available!"); return true; } nsCOMPtr<nsISimpleEnumerator> theEnum; nsresult rv = service->EnumerateObservers(NS_INVALIDFORMSUBMIT_SUBJECT, getter_AddRefs(theEnum)); // Return true on error here because that's what we always did NS_ENSURE_SUCCESS(rv, true); bool hasObserver = false; rv = theEnum->HasMoreElements(&hasObserver); nsCOMPtr<nsIMutableArray> invalidElements = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); invalidElements->AppendElement(content, false); NS_ENSURE_SUCCESS(rv, true); nsCOMPtr<nsISupports> inst; nsCOMPtr<nsIFormSubmitObserver> observer; bool more = true; while (NS_SUCCEEDED(theEnum->HasMoreElements(&more)) && more) { theEnum->GetNext(getter_AddRefs(inst)); observer = do_QueryInterface(inst); if (observer) { observer->NotifyInvalidSubmit(nullptr, invalidElements); } } if (content->IsHTMLElement(nsGkAtoms::input) && nsContentUtils::IsFocusedContent(content)) { HTMLInputElement* inputElement = HTMLInputElement::FromContentOrNull(content); inputElement->UpdateValidityUIBits(true); } dom::Element* element = content->AsElement(); element->UpdateState(true); return false; }
bool RenderFileUploadControl::allowsDirectoryUpload() { HTMLInputElement* input = static_cast<HTMLInputElement*>(node()); return input->fastHasAttribute(webkitdirectoryAttr); }
RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement& input, PassRef<RenderStyle> style) : RenderBlockFlow(input, WTF::move(style)) , m_canReceiveDroppedFiles(input.canReceiveDroppedFiles()) { }
void PageSerializer::serializeFrame(Frame* frame) { Document* document = frame->document(); KURL url = document->url(); if (!url.isValid() || url.isBlankURL()) { // For blank frames we generate a fake URL so they can be referenced by their containing frame. url = urlForBlankFrame(frame); } if (m_resourceURLs.contains(url)) { // FIXME: We could have 2 frame with the same URL but which were dynamically changed and have now // different content. So we should serialize both and somehow rename the frame src in the containing // frame. Arg! return; } Vector<Node*> nodes; SerializerMarkupAccumulator accumulator(this, document, &nodes); WTF::TextEncoding textEncoding(document->charset()); CString data; if (!textEncoding.isValid()) { // FIXME: iframes used as images trigger this. We should deal with them correctly. return; } String text = accumulator.serializeNodes(document, IncludeNode); CString frameHTML = textEncoding.normalizeAndEncode(text, WTF::EntitiesForUnencodables); m_resources->append(SerializedResource(url, document->suggestedMIMEType(), SharedBuffer::create(frameHTML.data(), frameHTML.length()))); m_resourceURLs.add(url); for (Vector<Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++iter) { Node* node = *iter; if (!node->isElementNode()) continue; Element* element = toElement(node); // We have to process in-line style as it might contain some resources (typically background images). if (element->isStyledElement()) retrieveResourcesForProperties(element->inlineStyle(), document); if (element->hasTagName(HTMLNames::imgTag)) { HTMLImageElement* imageElement = toHTMLImageElement(element); KURL url = document->completeURL(imageElement->getAttribute(HTMLNames::srcAttr)); ImageResource* cachedImage = imageElement->cachedImage(); addImageToResources(cachedImage, imageElement->renderer(), url); } else if (element->hasTagName(HTMLNames::inputTag)) { HTMLInputElement* inputElement = toHTMLInputElement(element); if (inputElement->isImageButton() && inputElement->hasImageLoader()) { KURL url = inputElement->src(); ImageResource* cachedImage = inputElement->imageLoader()->image(); addImageToResources(cachedImage, inputElement->renderer(), url); } } else if (element->hasTagName(HTMLNames::linkTag)) { HTMLLinkElement* linkElement = toHTMLLinkElement(element); if (CSSStyleSheet* sheet = linkElement->sheet()) { KURL url = document->completeURL(linkElement->getAttribute(HTMLNames::hrefAttr)); serializeCSSStyleSheet(sheet, url); ASSERT(m_resourceURLs.contains(url)); } } else if (element->hasTagName(HTMLNames::styleTag)) { HTMLStyleElement* styleElement = toHTMLStyleElement(element); if (CSSStyleSheet* sheet = styleElement->sheet()) serializeCSSStyleSheet(sheet, KURL()); } } for (Frame* childFrame = frame->tree().firstChild(); childFrame; childFrame = childFrame->tree().nextSibling()) serializeFrame(childFrame); }
void RenderTheme::paintSliderTicks(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& rect) { Node* node = o.node(); if (!node) return; HTMLInputElement* input = node->toInputElement(); if (!input) return; HTMLDataListElement* dataList = toHTMLDataListElement(input->list()); if (!dataList) return; double min = input->minimum(); double max = input->maximum(); ControlPart part = o.style().appearance(); // We don't support ticks on alternate sliders like MediaVolumeSliders. if (part != SliderHorizontalPart && part != SliderVerticalPart) return; bool isHorizontal = part == SliderHorizontalPart; IntSize thumbSize; const RenderObject* thumbRenderer = input->sliderThumbElement()->renderer(); if (thumbRenderer) { const RenderStyle& thumbStyle = thumbRenderer->style(); int thumbWidth = thumbStyle.width().intValue(); int thumbHeight = thumbStyle.height().intValue(); thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight); thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth); } IntSize tickSize = sliderTickSize(); float zoomFactor = o.style().effectiveZoom(); FloatRect tickRect; int tickRegionSideMargin = 0; int tickRegionWidth = 0; IntRect trackBounds; RenderObject* trackRenderer = input->sliderTrackElement()->renderer(); // We can ignoring transforms because transform is handled by the graphics context. if (trackRenderer) trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms(); IntRect sliderBounds = o.absoluteBoundingBoxRectIgnoringTransforms(); // Make position relative to the transformed ancestor element. trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x()); trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y()); if (isHorizontal) { tickRect.setWidth(floor(tickSize.width() * zoomFactor)); tickRect.setHeight(floor(tickSize.height() * zoomFactor)); tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor)); tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0; tickRegionWidth = trackBounds.width() - thumbSize.width(); } else { tickRect.setWidth(floor(tickSize.height() * zoomFactor)); tickRect.setHeight(floor(tickSize.width() * zoomFactor)); tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor)); tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0; tickRegionWidth = trackBounds.height() - thumbSize.width(); } RefPtr<HTMLCollection> options = dataList->options(); GraphicsContextStateSaver stateSaver(*paintInfo.context); paintInfo.context->setFillColor(o.style().visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB); for (unsigned i = 0; Node* node = options->item(i); i++) { ASSERT(isHTMLOptionElement(node)); HTMLOptionElement* optionElement = toHTMLOptionElement(node); String value = optionElement->value(); if (!input->isValidValue(value)) continue; double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value)); double tickFraction = (parsedValue - min) / (max - min); double tickRatio = isHorizontal && o.style().isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction; double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio); if (isHorizontal) tickRect.setX(tickPosition); else tickRect.setY(tickPosition); paintInfo.context->fillRect(tickRect); } }
bool RenderTheme::shouldHaveSpinButton(HTMLInputElement& inputElement) const { return inputElement.isSteppable() && !inputElement.isRangeControl(); }
bool SliderThumbElement::isDisabledFormControl() const { HTMLInputElement* input = hostInput(); return !input || input->isDisabledFormControl(); }
void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockHistory, bool lockBackForwardList) { FrameView* view = document()->view(); Frame* frame = document()->frame(); if (!view || !frame) return; if (m_insubmit) { m_doingsubmit = true; return; } m_insubmit = true; HTMLFormControlElement* firstSuccessfulSubmitButton = 0; bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button? Vector<pair<String, String> > formValues; for (unsigned i = 0; i < formElements.size(); ++i) { HTMLFormControlElement* control = formElements[i]; if (control->hasLocalName(inputTag)) { HTMLInputElement* input = static_cast<HTMLInputElement*>(control); if (input->isTextField()) { formValues.append(pair<String, String>(input->name(), input->value())); if (input->isSearchField()) input->addSearchResult(); } } if (needButtonActivation) { if (control->isActivatedSubmit()) needButtonActivation = false; else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton()) firstSuccessfulSubmitButton = control; } } RefPtr<FormState> formState = FormState::create(this, formValues, frame); if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(true); if (m_url.isEmpty()) m_url = document()->url().string(); if (m_formDataBuilder.isPostMethod()) { if (m_formDataBuilder.isMultiPartForm() && isMailtoForm()) { setEnctype("application/x-www-form-urlencoded"); ASSERT(!m_formDataBuilder.isMultiPartForm()); } if (!m_formDataBuilder.isMultiPartForm()) { RefPtr<FormData> data = createFormData(CString()); if (isMailtoForm()) { // Convert the form data into a string that we put into the URL. KURL url = document()->completeURL(m_url); transferMailtoPostFormDataToURL(data, url, m_formDataBuilder.encodingType()); m_url = url.string(); } frame->loader()->submitForm("POST", m_url, data.release(), m_target, m_formDataBuilder.encodingType(), String(), lockHistory, lockBackForwardList, event, formState.release()); } else { Vector<char> boundary = m_formDataBuilder.generateUniqueBoundaryString(); frame->loader()->submitForm("POST", m_url, createFormData(boundary.data()), m_target, m_formDataBuilder.encodingType(), boundary.data(), lockHistory, lockBackForwardList, event, formState.release()); } } else { m_formDataBuilder.setIsMultiPartForm(false); frame->loader()->submitForm("GET", m_url, createFormData(CString()), m_target, String(), String(), lockHistory, lockBackForwardList, event, formState.release()); } if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(false); m_doingsubmit = m_insubmit = false; }
bool SelectorChecker::checkOne(const SelectorCheckingContext& context) const { Element* const & element = context.element; const CSSSelector* const & selector = context.selector; ASSERT(element); ASSERT(selector); if (selector->m_match == CSSSelector::Tag) return SelectorChecker::tagMatches(element, selector->tagQName()); if (selector->m_match == CSSSelector::Class) return element->hasClass() && element->classNames().contains(selector->value()); if (selector->m_match == CSSSelector::Id) return element->hasID() && element->idForStyleResolution() == selector->value(); if (selector->isAttributeSelector()) { const QualifiedName& attr = selector->attribute(); if (!element->hasAttributes()) return false; bool caseSensitive = !m_documentIsHTML || HTMLDocument::isCaseSensitiveAttribute(attr); if (!anyAttributeMatches(element, static_cast<CSSSelector::Match>(selector->m_match), attr, selector->value(), caseSensitive)) return false; } if (selector->m_match == CSSSelector::PseudoClass) { // Handle :not up front. if (selector->pseudoType() == CSSSelector::PseudoNot) { const CSSSelectorList* selectorList = selector->selectorList(); // FIXME: We probably should fix the parser and make it never produce :not rules with missing selector list. if (!selectorList) return false; SelectorCheckingContext subContext(context); subContext.isSubSelector = true; for (subContext.selector = selectorList->first(); subContext.selector; subContext.selector = subContext.selector->tagHistory()) { // :not cannot nest. I don't really know why this is a // restriction in CSS3, but it is, so let's honor it. // the parser enforces that this never occurs ASSERT(subContext.selector->pseudoType() != CSSSelector::PseudoNot); // We select between :visited and :link when applying. We don't know which one applied (or not) yet. if (subContext.selector->pseudoType() == CSSSelector::PseudoVisited || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subContext.visitedMatchType == VisitedMatchEnabled)) return true; if (!checkOne(subContext)) return true; } } else if (context.hasScrollbarPseudo) { // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each // (since there are no elements involved). return checkScrollbarPseudoClass(context, element->document(), selector); } else if (context.hasSelectionPseudo) { if (selector->pseudoType() == CSSSelector::PseudoWindowInactive) return !element->document()->page()->focusController()->isActive(); } // Normal element pseudo class checking. switch (selector->pseudoType()) { // Pseudo classes: case CSSSelector::PseudoNot: break; // Already handled up above. case CSSSelector::PseudoEmpty: { bool result = true; for (Node* n = element->firstChild(); n; n = n->nextSibling()) { if (n->isElementNode()) { result = false; break; } if (n->isTextNode()) { Text* textNode = toText(n); if (!textNode->data().isEmpty()) { result = false; break; } } } if (m_mode == ResolvingStyle) { element->setStyleAffectedByEmpty(); if (context.elementStyle) context.elementStyle->setEmptyState(result); else if (element->renderStyle() && (element->document()->styleSheetCollection()->usesSiblingRules() || element->renderStyle()->unique())) element->renderStyle()->setEmptyState(result); } return result; } case CSSSelector::PseudoFirstChild: // first-child matches the first child that is an element if (Element* parentElement = element->parentElement()) { bool result = isFirstChildElement(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle(); parentElement->setChildrenAffectedByFirstChildRules(); if (result && childStyle) childStyle->setFirstChildState(); } return result; } break; case CSSSelector::PseudoFirstOfType: // first-of-type matches the first element of its type if (Element* parentElement = element->parentElement()) { bool result = isFirstOfType(element, element->tagQName()); if (m_mode == ResolvingStyle) parentElement->setChildrenAffectedByForwardPositionalRules(); return result; } break; case CSSSelector::PseudoLastChild: // last-child matches the last child that is an element if (Element* parentElement = element->parentElement()) { bool result = parentElement->isFinishedParsingChildren() && isLastChildElement(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle(); parentElement->setChildrenAffectedByLastChildRules(); if (result && childStyle) childStyle->setLastChildState(); } return result; } break; case CSSSelector::PseudoLastOfType: // last-of-type matches the last element of its type if (Element* parentElement = element->parentElement()) { if (m_mode == ResolvingStyle) parentElement->setChildrenAffectedByBackwardPositionalRules(); if (!parentElement->isFinishedParsingChildren()) return false; return isLastOfType(element, element->tagQName()); } break; case CSSSelector::PseudoOnlyChild: if (Element* parentElement = element->parentElement()) { bool firstChild = isFirstChildElement(element); bool onlyChild = firstChild && parentElement->isFinishedParsingChildren() && isLastChildElement(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle(); parentElement->setChildrenAffectedByFirstChildRules(); parentElement->setChildrenAffectedByLastChildRules(); if (firstChild && childStyle) childStyle->setFirstChildState(); if (onlyChild && childStyle) childStyle->setLastChildState(); } return onlyChild; } break; case CSSSelector::PseudoOnlyOfType: // FIXME: This selector is very slow. if (Element* parentElement = element->parentElement()) { if (m_mode == ResolvingStyle) { parentElement->setChildrenAffectedByForwardPositionalRules(); parentElement->setChildrenAffectedByBackwardPositionalRules(); } if (!parentElement->isFinishedParsingChildren()) return false; return isFirstOfType(element, element->tagQName()) && isLastOfType(element, element->tagQName()); } break; case CSSSelector::PseudoNthChild: if (!selector->parseNth()) break; if (Element* parentElement = element->parentElement()) { int count = 1 + countElementsBefore(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle(); element->setChildIndex(count); if (childStyle) childStyle->setUnique(); parentElement->setChildrenAffectedByForwardPositionalRules(); } if (selector->matchNth(count)) return true; } break; case CSSSelector::PseudoNthOfType: if (!selector->parseNth()) break; if (Element* parentElement = element->parentElement()) { int count = 1 + countElementsOfTypeBefore(element, element->tagQName()); if (m_mode == ResolvingStyle) parentElement->setChildrenAffectedByForwardPositionalRules(); if (selector->matchNth(count)) return true; } break; case CSSSelector::PseudoNthLastChild: if (!selector->parseNth()) break; if (Element* parentElement = element->parentElement()) { if (m_mode == ResolvingStyle) parentElement->setChildrenAffectedByBackwardPositionalRules(); if (!parentElement->isFinishedParsingChildren()) return false; int count = 1 + countElementsAfter(element); if (selector->matchNth(count)) return true; } break; case CSSSelector::PseudoNthLastOfType: if (!selector->parseNth()) break; if (Element* parentElement = element->parentElement()) { if (m_mode == ResolvingStyle) parentElement->setChildrenAffectedByBackwardPositionalRules(); if (!parentElement->isFinishedParsingChildren()) return false; int count = 1 + countElementsOfTypeAfter(element, element->tagQName()); if (selector->matchNth(count)) return true; } break; case CSSSelector::PseudoTarget: if (element == element->document()->cssTarget()) return true; break; case CSSSelector::PseudoAny: { SelectorCheckingContext subContext(context); subContext.isSubSelector = true; PseudoId ignoreDynamicPseudo = NOPSEUDO; for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { if (match(subContext, ignoreDynamicPseudo) == SelectorMatches) return true; } } break; case CSSSelector::PseudoAutofill: if (!element->isFormControlElement()) break; if (HTMLInputElement* inputElement = element->toInputElement()) return inputElement->isAutofilled(); break; case CSSSelector::PseudoAnyLink: case CSSSelector::PseudoLink: // :visited and :link matches are separated later when applying the style. Here both classes match all links... return element->isLink(); case CSSSelector::PseudoVisited: // ...except if :visited matching is disabled for ancestor/sibling matching. return element->isLink() && context.visitedMatchType == VisitedMatchEnabled; case CSSSelector::PseudoDrag: if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByDrag(); else element->setChildrenAffectedByDrag(true); } if (element->renderer() && element->renderer()->isDragging()) return true; break; case CSSSelector::PseudoFocus: return matchesFocusPseudoClass(element); case CSSSelector::PseudoHover: // If we're in quirks mode, then hover should never match anchors with no // href and *:hover should not match anything. This is important for sites like wsj.com. if (m_strictParsing || context.isSubSelector || (selector->m_match == CSSSelector::Tag && selector->tagQName() != anyQName() && !isHTMLAnchorElement(element)) || element->isLink()) { if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByHover(); else element->setChildrenAffectedByHover(true); } if (element->hovered() || InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoHover)) return true; } break; case CSSSelector::PseudoActive: // If we're in quirks mode, then :active should never match anchors with no // href and *:active should not match anything. if (m_strictParsing || context.isSubSelector || (selector->m_match == CSSSelector::Tag && selector->tagQName() != anyQName() && !isHTMLAnchorElement(element)) || element->isLink()) { if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByActive(); else element->setChildrenAffectedByActive(true); } if (element->active() || InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoActive)) return true; } break; case CSSSelector::PseudoEnabled: if (element->isFormControlElement() || isHTMLOptionElement(element) || isHTMLOptGroupElement(element)) return !element->isDisabledFormControl(); break; case CSSSelector::PseudoFullPageMedia: return element->document() && element->document()->isMediaDocument(); break; case CSSSelector::PseudoDefault: return element->isDefaultButtonForForm(); case CSSSelector::PseudoDisabled: if (element->isFormControlElement() || isHTMLOptionElement(element) || isHTMLOptGroupElement(element)) return element->isDisabledFormControl(); break; case CSSSelector::PseudoReadOnly: return element->matchesReadOnlyPseudoClass(); case CSSSelector::PseudoReadWrite: return element->matchesReadWritePseudoClass(); case CSSSelector::PseudoOptional: return element->isOptionalFormControl(); case CSSSelector::PseudoRequired: return element->isRequiredFormControl(); case CSSSelector::PseudoValid: element->document()->setContainsValidityStyleRules(); return element->willValidate() && element->isValidFormControlElement(); case CSSSelector::PseudoInvalid: element->document()->setContainsValidityStyleRules(); return element->willValidate() && !element->isValidFormControlElement(); case CSSSelector::PseudoChecked: { // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just // obey the CSS spec here in the test for matching the pseudo. HTMLInputElement* inputElement = element->toInputElement(); if (inputElement && inputElement->shouldAppearChecked() && !inputElement->shouldAppearIndeterminate()) return true; if (isHTMLOptionElement(element) && toHTMLOptionElement(element)->selected()) return true; break; } case CSSSelector::PseudoIndeterminate: return element->shouldAppearIndeterminate(); case CSSSelector::PseudoRoot: if (element == element->document()->documentElement()) return true; break; case CSSSelector::PseudoLang: { AtomicString value; #if ENABLE(VIDEO_TRACK) if (element->isWebVTTElement()) value = toWebVTTElement(element)->language(); else #endif value = element->computeInheritedLanguage(); const AtomicString& argument = selector->argument(); if (value.isEmpty() || !value.startsWith(argument, false)) break; if (value.length() != argument.length() && value[argument.length()] != '-') break; return true; } #if ENABLE(FULLSCREEN_API) case CSSSelector::PseudoFullScreen: // While a Document is in the fullscreen state, and the document's current fullscreen // element is an element in the document, the 'full-screen' pseudoclass applies to // that element. Also, an <iframe>, <object> or <embed> element whose child browsing // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied. if (element->isFrameElementBase() && element->containsFullScreenElement()) return true; if (!element->document()->webkitIsFullScreen()) return false; return element == element->document()->webkitCurrentFullScreenElement(); case CSSSelector::PseudoAnimatingFullScreenTransition: if (element != element->document()->webkitCurrentFullScreenElement()) return false; return element->document()->isAnimatingFullScreen(); case CSSSelector::PseudoFullScreenAncestor: return element->containsFullScreenElement(); case CSSSelector::PseudoFullScreenDocument: // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies // to all elements of that Document. if (!element->document()->webkitIsFullScreen()) return false; return true; #endif #if ENABLE(IFRAME_SEAMLESS) case CSSSelector::PseudoSeamlessDocument: // While a document is rendered in a seamless iframe, the 'seamless-document' pseudoclass applies // to all elements of that Document. return element->document()->shouldDisplaySeamlesslyWithParent(); #endif case CSSSelector::PseudoInRange: element->document()->setContainsValidityStyleRules(); return element->isInRange(); case CSSSelector::PseudoOutOfRange: element->document()->setContainsValidityStyleRules(); return element->isOutOfRange(); #if ENABLE(VIDEO_TRACK) case CSSSelector::PseudoFutureCue: return (element->isWebVTTElement() && !toWebVTTElement(element)->isPastNode()); case CSSSelector::PseudoPastCue: return (element->isWebVTTElement() && toWebVTTElement(element)->isPastNode()); #endif case CSSSelector::PseudoScope: { const Node* contextualReferenceNode = !context.scope || context.behaviorAtBoundary == CrossesBoundary ? element->document()->documentElement() : context.scope; if (element == contextualReferenceNode) return true; break; } case CSSSelector::PseudoHorizontal: case CSSSelector::PseudoVertical: case CSSSelector::PseudoDecrement: case CSSSelector::PseudoIncrement: case CSSSelector::PseudoStart: case CSSSelector::PseudoEnd: case CSSSelector::PseudoDoubleButton: case CSSSelector::PseudoSingleButton: case CSSSelector::PseudoNoButton: case CSSSelector::PseudoCornerPresent: return false; case CSSSelector::PseudoUnknown: case CSSSelector::PseudoNotParsed: default: ASSERT_NOT_REACHED(); break; } return false; } #if ENABLE(VIDEO_TRACK) else if (selector->m_match == CSSSelector::PseudoElement && selector->pseudoType() == CSSSelector::PseudoCue) { SelectorCheckingContext subContext(context); subContext.isSubSelector = true; PseudoId ignoreDynamicPseudo = NOPSEUDO; const CSSSelector* const & selector = context.selector; for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { if (match(subContext, ignoreDynamicPseudo) == SelectorMatches) return true; } return false; } #endif // ### add the rest of the checks... return true; }
void ChromeClientImpl::handleKeyboardEventOnTextField(HTMLInputElement& inputElement, KeyboardEvent& event) { WebLocalFrameImpl* webframe = WebLocalFrameImpl::fromFrame(inputElement.document().frame()); if (webframe->autofillClient()) webframe->autofillClient()->textFieldDidReceiveKeyDown(WebInputElement(&inputElement), WebKeyboardEventBuilder(event)); }
bool DOMHTMLInputElement::disabled() { ASSERT(m_element && m_element->hasTagName(inputTag)); HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(m_element); return inputElement->disabled() ? true : false; }
/** * This is called when we receive a drop or a dragover. */ NS_IMETHODIMP nsFileControlFrame::DnDListener::HandleEvent(nsIDOMEvent* aEvent) { NS_ASSERTION(mFrame, "We should have been unregistered"); bool defaultPrevented = false; aEvent->GetDefaultPrevented(&defaultPrevented); if (defaultPrevented) { return NS_OK; } nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent); if (!dragEvent) { return NS_OK; } nsCOMPtr<nsIDOMDataTransfer> dataTransfer; dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer)); if (!IsValidDropData(dataTransfer)) { return NS_OK; } nsCOMPtr<nsIContent> content = mFrame->GetContent(); bool supportsMultiple = content && content->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple); if (!CanDropTheseFiles(dataTransfer, supportsMultiple)) { dataTransfer->SetDropEffect(NS_LITERAL_STRING("none")); aEvent->StopPropagation(); return NS_OK; } nsAutoString eventType; aEvent->GetType(eventType); if (eventType.EqualsLiteral("dragover")) { // Prevent default if we can accept this drag data aEvent->PreventDefault(); return NS_OK; } if (eventType.EqualsLiteral("drop")) { aEvent->StopPropagation(); aEvent->PreventDefault(); NS_ASSERTION(content, "The frame has no content???"); HTMLInputElement* inputElement = HTMLInputElement::FromContent(content); NS_ASSERTION(inputElement, "No input element for this file upload control frame!"); nsCOMPtr<nsIDOMFileList> fileList; dataTransfer->GetFiles(getter_AddRefs(fileList)); RefPtr<BlobImpl> webkitDir; nsresult rv = GetBlobImplForWebkitDirectory(fileList, getter_AddRefs(webkitDir)); NS_ENSURE_SUCCESS(rv, NS_OK); nsTArray<OwningFileOrDirectory> array; if (webkitDir) { AppendBlobImplAsDirectory(array, webkitDir, content); inputElement->MozSetDndFilesAndDirectories(array); } else { bool blinkFileSystemEnabled = Preferences::GetBool("dom.webkitBlink.filesystem.enabled", false); if (blinkFileSystemEnabled) { FileList* files = static_cast<FileList*>(fileList.get()); if (files) { for (uint32_t i = 0; i < files->Length(); ++i) { File* file = files->Item(i); if (file) { if (file->Impl() && file->Impl()->IsDirectory()) { AppendBlobImplAsDirectory(array, file->Impl(), content); } else { OwningFileOrDirectory* element = array.AppendElement(); element->SetAsFile() = file; } } } } } // This is rather ugly. Pass the directories as Files using SetFiles, // but then if blink filesystem API is enabled, it wants // FileOrDirectory array. inputElement->SetFiles(fileList, true); if (blinkFileSystemEnabled) { inputElement->UpdateEntries(array); } nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content, NS_LITERAL_STRING("input"), true, false); nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content, NS_LITERAL_STRING("change"), true, false); } } return NS_OK; }