void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool processingUserGesture) { FrameView* view = document().view(); LocalFrame* frame = document().frame(); if (!view || !frame || !frame->page()) return; if (m_isSubmittingOrInUserJSSubmitEvent) { m_shouldSubmit = true; return; } m_isSubmittingOrInUserJSSubmitEvent = true; m_wasUserSubmitted = processingUserGesture; RefPtrWillBeRawPtr<HTMLFormControlElement> firstSuccessfulSubmitButton = nullptr; bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button? const FormAssociatedElement::List& elements = associatedElements(); for (unsigned i = 0; i < elements.size(); ++i) { FormAssociatedElement* associatedElement = elements[i]; if (!associatedElement->isFormControlElement()) continue; if (needButtonActivation) { HTMLFormControlElement* control = toHTMLFormControlElement(associatedElement); if (control->isActivatedSubmit()) needButtonActivation = false; else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton()) firstSuccessfulSubmitButton = control; } } if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(true); RefPtrWillBeRawPtr<FormSubmission> formSubmission = FormSubmission::create(this, m_attributes, event); EventQueueScope scopeForDialogClose; // Delay dispatching 'close' to dialog until done submitting. if (formSubmission->method() == FormSubmission::DialogMethod) submitDialog(formSubmission.release()); else scheduleFormSubmission(formSubmission.release()); if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(false); m_shouldSubmit = false; m_isSubmittingOrInUserJSSubmitEvent = false; }
void HTMLFormControlsCollection::updateIdNameCache() const { if (hasValidIdNameCache()) return; NamedItemCache* cache = NamedItemCache::create(); HashSet<StringImpl*> foundInputElements; const FormAssociatedElement::List& elementsArray = formControlElements(); for (unsigned i = 0; i < elementsArray.size(); ++i) { FormAssociatedElement* associatedElement = elementsArray[i]; if (associatedElement->isEnumeratable()) { HTMLElement* element = toHTMLElement(associatedElement); const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute(); if (!idAttrVal.isEmpty()) { cache->addElementWithId(idAttrVal, element); foundInputElements.add(idAttrVal.impl()); } if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal) { cache->addElementWithName(nameAttrVal, element); foundInputElements.add(nameAttrVal.impl()); } } } if (isHTMLFormElement(ownerNode())) { // HTMLFormControlsCollection doesn't support named getter for IMG // elements. However we still need to handle IMG elements here because // HTMLFormElement named getter relies on this. const HeapVector<Member<HTMLImageElement>>& imageElementsArray = formImageElements(); for (unsigned i = 0; i < imageElementsArray.size(); ++i) { HTMLImageElement* element = imageElementsArray[i]; const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute(); if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl())) cache->addElementWithId(idAttrVal, element); if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl())) cache->addElementWithName(nameAttrVal, element); } } // Set the named item cache last as traversing the tree may cause cache invalidation. setNamedItemCache(cache); }
void HTMLFormControlsCollection::updateIdNameCache() const { if (hasValidIdNameCache()) return; OwnPtr<NamedItemCache> cache = NamedItemCache::create(); HashSet<StringImpl*> foundInputElements; const FormAssociatedElement::List& elementsArray = formControlElements(); for (unsigned i = 0; i < elementsArray.size(); ++i) { FormAssociatedElement* associatedElement = elementsArray[i]; if (associatedElement->isEnumeratable()) { HTMLElement* element = toHTMLElement(associatedElement); const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute(); if (!idAttrVal.isEmpty()) { cache->addElementWithId(idAttrVal, element); foundInputElements.add(idAttrVal.impl()); } if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal) { cache->addElementWithName(nameAttrVal, element); foundInputElements.add(nameAttrVal.impl()); } } } if (isHTMLFormElement(ownerNode())) { const Vector<HTMLImageElement*>& imageElementsArray = formImageElements(); for (unsigned i = 0; i < imageElementsArray.size(); ++i) { HTMLImageElement* element = imageElementsArray[i]; const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute(); if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl())) cache->addElementWithId(idAttrVal, element); if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl())) cache->addElementWithName(nameAttrVal, element); } } // Set the named item cache last as traversing the tree may cause cache invalidation. setNamedItemCache(cache.release()); }
void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool processingUserGesture, FormSubmissionTrigger formSubmissionTrigger) { FrameView* view = document()->view(); Frame* frame = document()->frame(); if (!view || !frame) return; if (m_isSubmittingOrPreparingForSubmission) { m_shouldSubmit = true; return; } m_isSubmittingOrPreparingForSubmission = true; m_wasUserSubmitted = processingUserGesture; HTMLFormControlElement* firstSuccessfulSubmitButton = 0; bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button? for (unsigned i = 0; i < m_associatedElements.size(); ++i) { FormAssociatedElement* associatedElement = m_associatedElements[i]; if (!associatedElement->isFormControlElement()) continue; if (needButtonActivation) { HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(associatedElement); if (control->isActivatedSubmit()) needButtonActivation = false; else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton()) firstSuccessfulSubmitButton = control; } } if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(true); bool lockHistory = !processingUserGesture; frame->loader()->submitForm(FormSubmission::create(this, m_attributes, event, lockHistory, formSubmissionTrigger)); if (needButtonActivation && firstSuccessfulSubmitButton) firstSuccessfulSubmitButton->setActivatedSubmit(false); m_shouldSubmit = false; m_isSubmittingOrPreparingForSubmission = false; }
void HTMLFormElement::submitImplicitly(Event* event, bool fromImplicitSubmissionTrigger) { int submissionTriggerCount = 0; for (unsigned i = 0; i < m_associatedElements.size(); ++i) { FormAssociatedElement* formAssociatedElement = m_associatedElements[i]; if (!formAssociatedElement->isFormControlElement()) continue; HTMLFormControlElement* formElement = static_cast<HTMLFormControlElement*>(formAssociatedElement); if (formElement->isSuccessfulSubmitButton()) { if (formElement->renderer()) { formElement->dispatchSimulatedClick(event); return; } } else if (formElement->canTriggerImplicitSubmission()) ++submissionTriggerCount; } if (fromImplicitSubmissionTrigger && submissionTriggerCount == 1) prepareForSubmission(event); }
void HTMLFormControlsCollection::updateNameCache() const { if (hasNameCache()) return; HashSet<AtomicStringImpl*> foundInputElements; const Vector<FormAssociatedElement*>& elementsArray = formControlElements(); for (unsigned i = 0; i < elementsArray.size(); ++i) { FormAssociatedElement* associatedElement = elementsArray[i]; if (associatedElement->isEnumeratable()) { HTMLElement* element = toHTMLElement(associatedElement); const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute(); if (!idAttrVal.isEmpty()) { appendIdCache(idAttrVal, element); foundInputElements.add(idAttrVal.impl()); } if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal) { appendNameCache(nameAttrVal, element); foundInputElements.add(nameAttrVal.impl()); } } } if (isHTMLFormElement(ownerNode())) { const Vector<HTMLImageElement*>& imageElementsArray = formImageElements(); for (unsigned i = 0; i < imageElementsArray.size(); ++i) { HTMLImageElement* element = imageElementsArray[i]; const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getNameAttribute(); if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl())) appendIdCache(idAttrVal, element); if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl())) appendNameCache(nameAttrVal, element); } } setHasNameCache(); }
Element* HTMLFormControlsCollection::virtualItemAfter(Element* previous) const { const FormAssociatedElement::List& associatedElements = formControlElements(); unsigned offset; if (!previous) offset = 0; else if (m_cachedElement == previous) offset = m_cachedElementOffsetInArray + 1; else offset = findFormAssociatedElement(associatedElements, previous) + 1; for (unsigned i = offset; i < associatedElements.size(); ++i) { FormAssociatedElement* associatedElement = associatedElements[i]; if (associatedElement->isEnumeratable()) { m_cachedElement = toHTMLElement(associatedElement); m_cachedElementOffsetInArray = i; return m_cachedElement; } } return 0; }
void HTMLFormCollection::updateNameCache() const { if (m_cache.hasNameCache) return; HashSet<AtomicStringImpl*> foundInputElements; HTMLFormElement* f = static_cast<HTMLFormElement*>(base()); for (unsigned i = 0; i < f->m_associatedElements.size(); ++i) { FormAssociatedElement* associatedElement = f->m_associatedElements[i]; if (associatedElement->isEnumeratable()) { HTMLElement* element = toHTMLElement(associatedElement); const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getAttribute(nameAttr); if (!idAttrVal.isEmpty()) { append(m_cache.idCache, idAttrVal, element); foundInputElements.add(idAttrVal.impl()); } if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal) { append(m_cache.nameCache, nameAttrVal, element); foundInputElements.add(nameAttrVal.impl()); } } } for (unsigned i = 0; i < f->m_imageElements.size(); ++i) { HTMLImageElement* element = f->m_imageElements[i]; const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getAttribute(nameAttr); if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl())) append(m_cache.idCache, idAttrVal, element); if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl())) append(m_cache.nameCache, nameAttrVal, element); } m_cache.hasNameCache = true; }
FormAttributeTargetObserver::FormAttributeTargetObserver(const AtomicString& id, FormAssociatedElement& element) : IdTargetObserver(element.asHTMLElement().treeScope().idTargetObserverRegistry(), id) , m_element(element) { }
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()) { for (Node* node = event->target()->toNode(); node; node = node->parentNode()) { if (node->isElementNode() && toElement(node)->isFormControlElement()) { submitButton = static_cast<HTMLFormControlElement*>(node); break; } } } 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; bool containsPasswordData = false; for (unsigned i = 0; i < form->associatedElements().size(); ++i) { FormAssociatedElement* control = form->associatedElements()[i]; HTMLElement* element = toHTMLElement(control); if (!element->isDisabledFormControl()) 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())); input->addSearchResult(); } if (input->isPasswordField() && !input->value().isEmpty()) containsPasswordData = true; } } 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()); formData->setContainsPasswordData(containsPasswordData); String targetOrBaseTarget = copiedAttributes.target().isEmpty() ? document->baseTarget() : copiedAttributes.target(); RefPtr<FormState> formState = FormState::create(form, formValues, document, trigger); return adoptRef(new FormSubmission(copiedAttributes.method(), actionURL, targetOrBaseTarget, encodingType, formState.release(), formData.release(), boundary, lockHistory, event)); }
void HTMLFormCollection::updateNameCache() const { if (info()->hasNameCache) return; HashSet<AtomicStringImpl*> foundInputElements; HTMLFormElement* f = static_cast<HTMLFormElement*>(base()); for (unsigned i = 0; i < f->m_associatedElements.size(); ++i) { FormAssociatedElement* associatedElement = f->m_associatedElements[i]; if (associatedElement->isEnumeratable()) { HTMLElement* element = toHTMLElement(associatedElement); const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getAttribute(nameAttr); if (!idAttrVal.isEmpty()) { // add to id cache Vector<Element*>* idVector = info()->idCache.get(idAttrVal.impl()); if (!idVector) { idVector = new Vector<Element*>; info()->idCache.add(idAttrVal.impl(), idVector); } idVector->append(element); foundInputElements.add(idAttrVal.impl()); } if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal) { // add to name cache Vector<Element*>* nameVector = info()->nameCache.get(nameAttrVal.impl()); if (!nameVector) { nameVector = new Vector<Element*>; info()->nameCache.add(nameAttrVal.impl(), nameVector); } nameVector->append(element); foundInputElements.add(nameAttrVal.impl()); } } } for (unsigned i = 0; i < f->m_imageElements.size(); ++i) { HTMLImageElement* element = f->m_imageElements[i]; const AtomicString& idAttrVal = element->getIdAttribute(); const AtomicString& nameAttrVal = element->getAttribute(nameAttr); if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl())) { // add to id cache Vector<Element*>* idVector = info()->idCache.get(idAttrVal.impl()); if (!idVector) { idVector = new Vector<Element*>; info()->idCache.add(idAttrVal.impl(), idVector); } idVector->append(element); } if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl())) { // add to name cache Vector<Element*>* nameVector = info()->nameCache.get(nameAttrVal.impl()); if (!nameVector) { nameVector = new Vector<Element*>; info()->nameCache.add(nameAttrVal.impl(), nameVector); } nameVector->append(element); } } info()->hasNameCache = true; }
PassRefPtrWillBeRawPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, PassRefPtrWillBeRawPtr<Event> event) { ASSERT(form); HTMLFormControlElement* submitButton = 0; if (event && event->target()) { for (Node* node = event->target()->toNode(); node; node = node->parentOrShadowHostNode()) { if (node->isElementNode() && toElement(node)->isFormControlElement()) { submitButton = toHTMLFormControlElement(node); break; } } } FormSubmission::Attributes copiedAttributes; copiedAttributes.copyFrom(attributes); if (submitButton) { AtomicString attributeValue; if (!(attributeValue = submitButton->fastGetAttribute(formactionAttr)).isNull()) copiedAttributes.parseAction(attributeValue); if (!(attributeValue = submitButton->fastGetAttribute(formenctypeAttr)).isNull()) copiedAttributes.updateEncodingType(attributeValue); if (!(attributeValue = submitButton->fastGetAttribute(formmethodAttr)).isNull()) copiedAttributes.updateMethodType(attributeValue); if (!(attributeValue = submitButton->fastGetAttribute(formtargetAttr)).isNull()) copiedAttributes.setTarget(attributeValue); } if (copiedAttributes.method() == DialogMethod) { if (submitButton) return adoptRefWillBeNoop(new FormSubmission(submitButton->resultForDialogSubmit())); return adoptRefWillBeNoop(new FormSubmission("")); } Document& document = form->document(); KURL actionURL = document.completeURL(copiedAttributes.action().isEmpty() ? document.url().string() : copiedAttributes.action()); bool isMailtoForm = actionURL.protocolIs("mailto"); bool isMultiPartForm = false; AtomicString encodingType = copiedAttributes.encodingType(); if (copiedAttributes.method() == PostMethod) { isMultiPartForm = copiedAttributes.isMultiPartForm(); if (isMultiPartForm && isMailtoForm) { encodingType = AtomicString("application/x-www-form-urlencoded", AtomicString::ConstructFromLiteral); isMultiPartForm = false; } } WTF::TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataEncoder::encodingFromAcceptCharset(copiedAttributes.acceptCharset(), document.encoding()); FormData* domFormData = FormData::create(dataEncoding.encodingForFormSubmission()); bool containsPasswordData = false; for (unsigned i = 0; i < form->associatedElements().size(); ++i) { FormAssociatedElement* control = form->associatedElements()[i]; ASSERT(control); HTMLElement& element = toHTMLElement(*control); if (!element.isDisabledFormControl()) control->appendToFormData(*domFormData); if (isHTMLInputElement(element)) { HTMLInputElement& input = toHTMLInputElement(element); if (input.type() == InputTypeNames::password && !input.value().isEmpty()) containsPasswordData = true; } } RefPtr<EncodedFormData> formData; String boundary; if (isMultiPartForm) { formData = domFormData->encodeMultiPartFormData(); boundary = formData->boundary().data(); } else { formData = domFormData->encodeFormData(attributes.method() == GetMethod ? EncodedFormData::FormURLEncoded : EncodedFormData::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 = EncodedFormData::create(); } } formData->setIdentifier(generateFormDataIdentifier()); formData->setContainsPasswordData(containsPasswordData); AtomicString targetOrBaseTarget = copiedAttributes.target().isEmpty() ? document.baseTarget() : copiedAttributes.target(); return adoptRefWillBeNoop(new FormSubmission(copiedAttributes.method(), actionURL, targetOrBaseTarget, encodingType, form, formData.release(), boundary, event)); }