HTMLFormElement.cpp revision cad810f21b803229eb11403f9209855525a25d57
1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 * 23 */ 24 25#include "config.h" 26#include "HTMLFormElement.h" 27 28#include "Attribute.h" 29#include "DOMFormData.h" 30#include "DOMWindow.h" 31#include "Document.h" 32#include "Event.h" 33#include "EventNames.h" 34#include "FileList.h" 35#include "FileSystem.h" 36#include "FormData.h" 37#include "FormDataList.h" 38#include "FormState.h" 39#include "Frame.h" 40#include "FrameLoader.h" 41#include "FrameLoaderClient.h" 42#include "HTMLDocument.h" 43#include "HTMLFormCollection.h" 44#include "HTMLImageElement.h" 45#include "HTMLInputElement.h" 46#include "HTMLNames.h" 47#include "MIMETypeRegistry.h" 48#include "Page.h" 49#include "RenderTextControl.h" 50#include "ScriptEventListener.h" 51#include "Settings.h" 52#include "ValidityState.h" 53#include <limits> 54 55#if PLATFORM(WX) 56#include <wx/defs.h> 57#include <wx/filename.h> 58#endif 59 60using namespace std; 61 62namespace WebCore { 63 64using namespace HTMLNames; 65 66HTMLFormElement::HTMLFormElement(const QualifiedName& tagName, Document* document) 67 : HTMLElement(tagName, document) 68 , m_associatedElementsBeforeIndex(0) 69 , m_associatedElementsAfterIndex(0) 70 , m_wasUserSubmitted(false) 71 , m_isSubmittingOrPreparingForSubmission(false) 72 , m_shouldSubmit(false) 73 , m_isInResetFunction(false) 74 , m_wasMalformed(false) 75 , m_wasDemoted(false) 76{ 77 ASSERT(hasTagName(formTag)); 78} 79 80PassRefPtr<HTMLFormElement> HTMLFormElement::create(Document* document) 81{ 82 return adoptRef(new HTMLFormElement(formTag, document)); 83} 84 85PassRefPtr<HTMLFormElement> HTMLFormElement::create(const QualifiedName& tagName, Document* document) 86{ 87 return adoptRef(new HTMLFormElement(tagName, document)); 88} 89 90HTMLFormElement::~HTMLFormElement() 91{ 92 if (!autoComplete()) 93 document()->unregisterForDocumentActivationCallbacks(this); 94 95 for (unsigned i = 0; i < m_associatedElements.size(); ++i) 96 m_associatedElements[i]->formDestroyed(); 97 for (unsigned i = 0; i < m_imageElements.size(); ++i) 98 m_imageElements[i]->m_form = 0; 99} 100 101bool HTMLFormElement::formWouldHaveSecureSubmission(const String& url) 102{ 103 return document()->completeURL(url).protocolIs("https"); 104} 105 106bool HTMLFormElement::rendererIsNeeded(RenderStyle* style) 107{ 108 if (!m_wasDemoted) 109 return HTMLElement::rendererIsNeeded(style); 110 111 ContainerNode* node = parentNode(); 112 RenderObject* parentRenderer = node->renderer(); 113 bool parentIsTableElementPart = (parentRenderer->isTable() && node->hasTagName(tableTag)) 114 || (parentRenderer->isTableRow() && node->hasTagName(trTag)) 115 || (parentRenderer->isTableSection() && node->hasTagName(tbodyTag)) 116 || (parentRenderer->isTableCol() && node->hasTagName(colTag)) 117 || (parentRenderer->isTableCell() && node->hasTagName(trTag)); 118 119 if (!parentIsTableElementPart) 120 return true; 121 122 EDisplay display = style->display(); 123 bool formIsTablePart = display == TABLE || display == INLINE_TABLE || display == TABLE_ROW_GROUP 124 || display == TABLE_HEADER_GROUP || display == TABLE_FOOTER_GROUP || display == TABLE_ROW 125 || display == TABLE_COLUMN_GROUP || display == TABLE_COLUMN || display == TABLE_CELL 126 || display == TABLE_CAPTION; 127 128 return formIsTablePart; 129} 130 131void HTMLFormElement::insertedIntoDocument() 132{ 133 if (document()->isHTMLDocument()) 134 static_cast<HTMLDocument*>(document())->addNamedItem(m_name); 135 136 HTMLElement::insertedIntoDocument(); 137 138 if (hasID()) 139 document()->resetFormElementsOwner(this); 140} 141 142void HTMLFormElement::removedFromDocument() 143{ 144 if (document()->isHTMLDocument()) 145 static_cast<HTMLDocument*>(document())->removeNamedItem(m_name); 146 147 HTMLElement::removedFromDocument(); 148 149 if (hasID()) 150 document()->resetFormElementsOwner(0); 151} 152 153void HTMLFormElement::handleLocalEvents(Event* event) 154{ 155 Node* targetNode = event->target()->toNode(); 156 if (event->eventPhase() != Event::CAPTURING_PHASE && targetNode && targetNode != this && (event->type() == eventNames().submitEvent || event->type() == eventNames().resetEvent)) { 157 event->stopPropagation(); 158 return; 159 } 160 HTMLElement::handleLocalEvents(event); 161} 162 163unsigned HTMLFormElement::length() const 164{ 165 unsigned len = 0; 166 for (unsigned i = 0; i < m_associatedElements.size(); ++i) 167 if (m_associatedElements[i]->isEnumeratable()) 168 ++len; 169 return len; 170} 171 172Node* HTMLFormElement::item(unsigned index) 173{ 174 return elements()->item(index); 175} 176 177void HTMLFormElement::submitImplicitly(Event* event, bool fromImplicitSubmissionTrigger) 178{ 179 int submissionTriggerCount = 0; 180 for (unsigned i = 0; i < m_associatedElements.size(); ++i) { 181 FormAssociatedElement* formAssociatedElement = m_associatedElements[i]; 182 if (!formAssociatedElement->isFormControlElement()) 183 continue; 184 HTMLFormControlElement* formElement = static_cast<HTMLFormControlElement*>(formAssociatedElement); 185 if (formElement->isSuccessfulSubmitButton()) { 186 if (formElement->renderer()) { 187 formElement->dispatchSimulatedClick(event); 188 return; 189 } 190 } else if (formElement->canTriggerImplicitSubmission()) 191 ++submissionTriggerCount; 192 } 193 if (fromImplicitSubmissionTrigger && submissionTriggerCount == 1) 194 prepareForSubmission(event); 195} 196 197static inline HTMLFormControlElement* submitElementFromEvent(const Event* event) 198{ 199 Node* targetNode = event->target()->toNode(); 200 if (!targetNode || !targetNode->isElementNode()) 201 return 0; 202 Element* targetElement = static_cast<Element*>(targetNode); 203 if (!targetElement->isFormControlElement()) 204 return 0; 205 return static_cast<HTMLFormControlElement*>(targetElement); 206} 207 208bool HTMLFormElement::validateInteractively(Event* event) 209{ 210 ASSERT(event); 211 if (!document()->page() || !document()->page()->settings()->interactiveFormValidationEnabled() || noValidate()) 212 return true; 213 214 HTMLFormControlElement* submitElement = submitElementFromEvent(event); 215 if (submitElement && submitElement->formNoValidate()) 216 return true; 217 218 for (unsigned i = 0; i < m_associatedElements.size(); ++i) { 219 if (m_associatedElements[i]->isFormControlElement()) 220 static_cast<HTMLFormControlElement*>(m_associatedElements[i])->hideVisibleValidationMessage(); 221 } 222 223 Vector<RefPtr<FormAssociatedElement> > unhandledInvalidControls; 224 collectUnhandledInvalidControls(unhandledInvalidControls); 225 if (unhandledInvalidControls.isEmpty()) 226 return true; 227 // If the form has invalid controls, abort submission. 228 229 RefPtr<HTMLFormElement> protector(this); 230 // Focus on the first focusable control and show a validation message. 231 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { 232 FormAssociatedElement* unhandledAssociatedElement = unhandledInvalidControls[i].get(); 233 HTMLElement* unhandled = toHTMLElement(unhandledAssociatedElement); 234 if (unhandled->isFocusable() && unhandled->inDocument()) { 235 RefPtr<Document> originalDocument(unhandled->document()); 236 unhandled->scrollIntoViewIfNeeded(false); 237 // scrollIntoViewIfNeeded() dispatches events, so the state 238 // of 'unhandled' might be changed so it's no longer focusable or 239 // moved to another document. 240 if (unhandled->isFocusable() && unhandled->inDocument() && originalDocument == unhandled->document()) { 241 unhandled->focus(); 242 if (unhandled->isFormControlElement()) 243 static_cast<HTMLFormControlElement*>(unhandled)->updateVisibleValidationMessage(); 244 break; 245 } 246 } 247 } 248 // Warn about all of unfocusable controls. 249 if (Frame* frame = document()->frame()) { 250 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { 251 FormAssociatedElement* unhandledAssociatedElement = unhandledInvalidControls[i].get(); 252 HTMLElement* unhandled = toHTMLElement(unhandledAssociatedElement); 253 if (unhandled->isFocusable() && unhandled->inDocument()) 254 continue; 255 String message("An invalid form control with name='%name' is not focusable."); 256 message.replace("%name", unhandledAssociatedElement->name()); 257 frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, ErrorMessageLevel, message, 0, document()->url().string()); 258 } 259 } 260 return false; 261} 262 263bool HTMLFormElement::prepareForSubmission(Event* event) 264{ 265 Frame* frame = document()->frame(); 266 if (m_isSubmittingOrPreparingForSubmission || !frame) 267 return m_isSubmittingOrPreparingForSubmission; 268 269 m_isSubmittingOrPreparingForSubmission = true; 270 m_shouldSubmit = false; 271 272 // Interactive validation must be done before dispatching the submit event. 273 if (!validateInteractively(event)) { 274 m_isSubmittingOrPreparingForSubmission = false; 275 return false; 276 } 277 278 frame->loader()->client()->dispatchWillSendSubmitEvent(this); 279 280 if (dispatchEvent(Event::create(eventNames().submitEvent, true, true))) 281 m_shouldSubmit = true; 282 283 m_isSubmittingOrPreparingForSubmission = false; 284 285 if (m_shouldSubmit) 286 submit(event, true, true, NotSubmittedByJavaScript); 287 288 return m_shouldSubmit; 289} 290 291void HTMLFormElement::submit() 292{ 293 submit(0, false, true, NotSubmittedByJavaScript); 294} 295 296void HTMLFormElement::submitFromJavaScript() 297{ 298 Frame* frame = document()->frame(); 299 if (!frame) 300 return; 301 submit(0, false, frame->script()->anyPageIsProcessingUserGesture(), SubmittedByJavaScript); 302} 303 304void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool processingUserGesture, FormSubmissionTrigger formSubmissionTrigger) 305{ 306 FrameView* view = document()->view(); 307 Frame* frame = document()->frame(); 308 if (!view || !frame) 309 return; 310 311 if (m_isSubmittingOrPreparingForSubmission) { 312 m_shouldSubmit = true; 313 return; 314 } 315 316 m_isSubmittingOrPreparingForSubmission = true; 317 m_wasUserSubmitted = processingUserGesture; 318 319 HTMLFormControlElement* firstSuccessfulSubmitButton = 0; 320 bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button? 321 322 for (unsigned i = 0; i < m_associatedElements.size(); ++i) { 323 FormAssociatedElement* associatedElement = m_associatedElements[i]; 324 if (!associatedElement->isFormControlElement()) 325 continue; 326 if (needButtonActivation) { 327 HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(associatedElement); 328 if (control->isActivatedSubmit()) 329 needButtonActivation = false; 330 else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton()) 331 firstSuccessfulSubmitButton = control; 332 } 333 } 334 335 if (needButtonActivation && firstSuccessfulSubmitButton) 336 firstSuccessfulSubmitButton->setActivatedSubmit(true); 337 338 frame->loader()->submitForm(FormSubmission::create(this, m_attributes, event, !processingUserGesture, formSubmissionTrigger)); 339 340 if (needButtonActivation && firstSuccessfulSubmitButton) 341 firstSuccessfulSubmitButton->setActivatedSubmit(false); 342 343 m_shouldSubmit = false; 344 m_isSubmittingOrPreparingForSubmission = false; 345} 346 347void HTMLFormElement::reset() 348{ 349 Frame* frame = document()->frame(); 350 if (m_isInResetFunction || !frame) 351 return; 352 353 m_isInResetFunction = true; 354 355 if (!dispatchEvent(Event::create(eventNames().resetEvent, true, true))) { 356 m_isInResetFunction = false; 357 return; 358 } 359 360 for (unsigned i = 0; i < m_associatedElements.size(); ++i) { 361 if (m_associatedElements[i]->isFormControlElement()) 362 static_cast<HTMLFormControlElement*>(m_associatedElements[i])->reset(); 363 } 364 365 m_isInResetFunction = false; 366} 367 368void HTMLFormElement::parseMappedAttribute(Attribute* attr) 369{ 370 if (attr->name() == actionAttr) 371 m_attributes.parseAction(attr->value()); 372 else if (attr->name() == targetAttr) 373 m_attributes.setTarget(attr->value()); 374 else if (attr->name() == methodAttr) 375 m_attributes.parseMethodType(attr->value()); 376 else if (attr->name() == enctypeAttr) 377 m_attributes.parseEncodingType(attr->value()); 378 else if (attr->name() == accept_charsetAttr) 379 m_attributes.setAcceptCharset(attr->value()); 380 else if (attr->name() == autocompleteAttr) { 381 if (!autoComplete()) 382 document()->registerForDocumentActivationCallbacks(this); 383 else 384 document()->unregisterForDocumentActivationCallbacks(this); 385 } else if (attr->name() == onsubmitAttr) 386 setAttributeEventListener(eventNames().submitEvent, createAttributeEventListener(this, attr)); 387 else if (attr->name() == onresetAttr) 388 setAttributeEventListener(eventNames().resetEvent, createAttributeEventListener(this, attr)); 389 else if (attr->name() == nameAttr) { 390 const AtomicString& newName = attr->value(); 391 if (inDocument() && document()->isHTMLDocument()) { 392 HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); 393 document->removeNamedItem(m_name); 394 document->addNamedItem(newName); 395 } 396 m_name = newName; 397 } else 398 HTMLElement::parseMappedAttribute(attr); 399} 400 401template<class T, size_t n> static void removeFromVector(Vector<T*, n> & vec, T* item) 402{ 403 size_t size = vec.size(); 404 for (size_t i = 0; i != size; ++i) 405 if (vec[i] == item) { 406 vec.remove(i); 407 break; 408 } 409} 410 411unsigned HTMLFormElement::formElementIndexWithFormAttribute(Element* element) 412{ 413 // Compares the position of the form element and the inserted element. 414 // Updates the indeces in order to the relation of the position: 415 unsigned short position = compareDocumentPosition(element); 416 if (position & DOCUMENT_POSITION_CONTAINS) 417 ++m_associatedElementsAfterIndex; 418 else if (position & DOCUMENT_POSITION_PRECEDING) { 419 ++m_associatedElementsBeforeIndex; 420 ++m_associatedElementsAfterIndex; 421 } 422 423 if (m_associatedElements.isEmpty()) 424 return 0; 425 426 // Does binary search on m_associatedElements in order to find the index 427 // to be inserted. 428 unsigned left = 0, right = m_associatedElements.size() - 1; 429 while (left != right) { 430 unsigned middle = left + ((right - left) / 2); 431 position = element->compareDocumentPosition(toHTMLElement(m_associatedElements[middle])); 432 if (position & DOCUMENT_POSITION_FOLLOWING) 433 right = middle; 434 else 435 left = middle + 1; 436 } 437 438 position = element->compareDocumentPosition(toHTMLElement(m_associatedElements[left])); 439 if (position & DOCUMENT_POSITION_FOLLOWING) 440 return left; 441 return left + 1; 442} 443 444unsigned HTMLFormElement::formElementIndex(FormAssociatedElement* associatedElement) 445{ 446 HTMLElement* element = toHTMLElement(associatedElement); 447 // Treats separately the case where this element has the form attribute 448 // for performance consideration. 449 if (element->fastHasAttribute(formAttr)) 450 return formElementIndexWithFormAttribute(element); 451 452 // Check for the special case where this element is the very last thing in 453 // the form's tree of children; we don't want to walk the entire tree in that 454 // common case that occurs during parsing; instead we'll just return a value 455 // that says "add this form element to the end of the array". 456 if (element->traverseNextNode(this)) { 457 unsigned i = m_associatedElementsBeforeIndex; 458 for (Node* node = this; node; node = node->traverseNextNode(this)) { 459 if (node == element) { 460 ++m_associatedElementsAfterIndex; 461 return i; 462 } 463 if (node->isHTMLElement() 464 && (static_cast<Element*>(node)->isFormControlElement() 465 || node->hasTagName(objectTag)) 466 && static_cast<HTMLElement*>(node)->form() == this) 467 ++i; 468 } 469 } 470 return m_associatedElementsAfterIndex++; 471} 472 473void HTMLFormElement::registerFormElement(FormAssociatedElement* e) 474{ 475 if (e->isFormControlElement()) { 476 HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(e); 477 document()->checkedRadioButtons().removeButton(element); 478 m_checkedRadioButtons.addButton(element); 479 } 480 m_associatedElements.insert(formElementIndex(e), e); 481} 482 483void HTMLFormElement::removeFormElement(FormAssociatedElement* e) 484{ 485 if (e->isFormControlElement()) 486 m_checkedRadioButtons.removeButton(static_cast<HTMLFormControlElement*>(e)); 487 HTMLElement* element = toHTMLElement(e); 488 if (element->fastHasAttribute(formAttr)) { 489 unsigned index; 490 for (index = 0; index < m_associatedElements.size(); ++index) 491 if (m_associatedElements[index] == e) 492 break; 493 ASSERT(index < m_associatedElements.size()); 494 if (index < m_associatedElementsBeforeIndex) 495 --m_associatedElementsBeforeIndex; 496 if (index < m_associatedElementsAfterIndex) 497 --m_associatedElementsAfterIndex; 498 } else 499 --m_associatedElementsAfterIndex; 500 removeFromVector(m_associatedElements, e); 501} 502 503bool HTMLFormElement::isURLAttribute(Attribute* attr) const 504{ 505 return attr->name() == actionAttr; 506} 507 508void HTMLFormElement::registerImgElement(HTMLImageElement* e) 509{ 510 ASSERT(m_imageElements.find(e) == notFound); 511 m_imageElements.append(e); 512} 513 514void HTMLFormElement::removeImgElement(HTMLImageElement* e) 515{ 516 ASSERT(m_imageElements.find(e) != notFound); 517 removeFromVector(m_imageElements, e); 518} 519 520PassRefPtr<HTMLCollection> HTMLFormElement::elements() 521{ 522 return HTMLFormCollection::create(this); 523} 524 525String HTMLFormElement::name() const 526{ 527 return getAttribute(nameAttr); 528} 529 530bool HTMLFormElement::noValidate() const 531{ 532 return fastHasAttribute(novalidateAttr); 533} 534 535// FIXME: This function should be removed because it does not do the same thing as the 536// JavaScript binding for action, which treats action as a URL attribute. Last time I 537// (Darin Adler) removed this, someone added it back, so I am leaving it in for now. 538String HTMLFormElement::action() const 539{ 540 return getAttribute(actionAttr); 541} 542 543void HTMLFormElement::setAction(const String &value) 544{ 545 setAttribute(actionAttr, value); 546} 547 548void HTMLFormElement::setEnctype(const String &value) 549{ 550 setAttribute(enctypeAttr, value); 551} 552 553String HTMLFormElement::method() const 554{ 555 return getAttribute(methodAttr); 556} 557 558void HTMLFormElement::setMethod(const String &value) 559{ 560 setAttribute(methodAttr, value); 561} 562 563String HTMLFormElement::target() const 564{ 565 return getAttribute(targetAttr); 566} 567 568bool HTMLFormElement::wasUserSubmitted() const 569{ 570 return m_wasUserSubmitted; 571} 572 573HTMLFormControlElement* HTMLFormElement::defaultButton() const 574{ 575 for (unsigned i = 0; i < m_associatedElements.size(); ++i) { 576 if (!m_associatedElements[i]->isFormControlElement()) 577 continue; 578 HTMLFormControlElement* control = static_cast<HTMLFormControlElement*>(m_associatedElements[i]); 579 if (control->isSuccessfulSubmitButton()) 580 return control; 581 } 582 583 return 0; 584} 585 586bool HTMLFormElement::checkValidity() 587{ 588 Vector<RefPtr<FormAssociatedElement> > controls; 589 collectUnhandledInvalidControls(controls); 590 return controls.isEmpty(); 591} 592 593void HTMLFormElement::collectUnhandledInvalidControls(Vector<RefPtr<FormAssociatedElement> >& unhandledInvalidControls) 594{ 595 RefPtr<HTMLFormElement> protector(this); 596 // Copy m_associatedElements because event handlers called from 597 // HTMLFormControlElement::checkValidity() might change m_associatedElements. 598 Vector<RefPtr<FormAssociatedElement> > elements; 599 elements.reserveCapacity(m_associatedElements.size()); 600 for (unsigned i = 0; i < m_associatedElements.size(); ++i) 601 elements.append(m_associatedElements[i]); 602 for (unsigned i = 0; i < elements.size(); ++i) { 603 if (elements[i]->form() == this && elements[i]->isFormControlElement()) 604 static_cast<HTMLFormControlElement*>(elements[i].get())->checkValidity(&unhandledInvalidControls); 605 } 606} 607 608HTMLFormControlElement* HTMLFormElement::elementForAlias(const AtomicString& alias) 609{ 610 if (alias.isEmpty() || !m_elementAliases) 611 return 0; 612 return m_elementAliases->get(alias.impl()).get(); 613} 614 615void HTMLFormElement::addElementAlias(HTMLFormControlElement* element, const AtomicString& alias) 616{ 617 if (alias.isEmpty()) 618 return; 619 if (!m_elementAliases) 620 m_elementAliases = adoptPtr(new AliasMap); 621 m_elementAliases->set(alias.impl(), element); 622} 623 624void HTMLFormElement::getNamedElements(const AtomicString& name, Vector<RefPtr<Node> >& namedItems) 625{ 626 elements()->namedItems(name, namedItems); 627 628 HTMLFormControlElement* aliasElement = elementForAlias(name); 629 if (aliasElement) { 630 if (namedItems.find(aliasElement) == notFound) { 631 // We have seen it before but it is gone now. Still, we need to return it. 632 // FIXME: The above comment is not clear enough; it does not say why we need to do this. 633 namedItems.append(aliasElement); 634 } 635 } 636 if (namedItems.size() && namedItems.first() != aliasElement) 637 addElementAlias(static_cast<HTMLFormControlElement*>(namedItems.first().get()), name); 638} 639 640void HTMLFormElement::documentDidBecomeActive() 641{ 642 ASSERT(!autoComplete()); 643 644 for (unsigned i = 0; i < m_associatedElements.size(); ++i) { 645 if (m_associatedElements[i]->isFormControlElement()) 646 static_cast<HTMLFormControlElement*>(m_associatedElements[i])->reset(); 647 } 648} 649 650void HTMLFormElement::willMoveToNewOwnerDocument() 651{ 652 if (!autoComplete()) 653 document()->unregisterForDocumentActivationCallbacks(this); 654 HTMLElement::willMoveToNewOwnerDocument(); 655} 656 657void HTMLFormElement::didMoveToNewOwnerDocument() 658{ 659 if (!autoComplete()) 660 document()->registerForDocumentActivationCallbacks(this); 661 HTMLElement::didMoveToNewOwnerDocument(); 662} 663 664bool HTMLFormElement::autoComplete() const 665{ 666 return !equalIgnoringCase(fastGetAttribute(autocompleteAttr), "off"); 667} 668 669} // namespace 670