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 "CSSHelper.h"
29 #include "Chrome.h"
30 #include "ChromeClient.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 "HTMLDocument.h"
42 #include "HTMLFormCollection.h"
43 #include "HTMLImageElement.h"
44 #include "HTMLInputElement.h"
45 #include "HTMLNames.h"
46 #include "ScriptEventListener.h"
47 #include "MIMETypeRegistry.h"
48 #include "MappedAttribute.h"
49 #include "Page.h"
50 #include "RenderTextControl.h"
51 #include "ValidityState.h"
52 #include <limits>
53 #include <wtf/CurrentTime.h>
54 #include <wtf/RandomNumber.h>
55
56 #if PLATFORM(WX)
57 #include <wx/defs.h>
58 #include <wx/filename.h>
59 #endif
60
61 using namespace std;
62
63 namespace WebCore {
64
65 using namespace HTMLNames;
66
generateFormDataIdentifier()67 static int64_t generateFormDataIdentifier()
68 {
69 // Initialize to the current time to reduce the likelihood of generating
70 // identifiers that overlap with those from past/future browser sessions.
71 static int64_t nextIdentifier = static_cast<int64_t>(currentTime() * 1000000.0);
72 return ++nextIdentifier;
73 }
74
HTMLFormElement(const QualifiedName & tagName,Document * doc)75 HTMLFormElement::HTMLFormElement(const QualifiedName& tagName, Document* doc)
76 : HTMLElement(tagName, doc)
77 , m_elementAliases(0)
78 , collectionInfo(0)
79 , m_autocomplete(true)
80 , m_insubmit(false)
81 , m_doingsubmit(false)
82 , m_inreset(false)
83 , m_malformed(false)
84 , m_demoted(false)
85 {
86 ASSERT(hasTagName(formTag));
87 }
88
~HTMLFormElement()89 HTMLFormElement::~HTMLFormElement()
90 {
91 if (!m_autocomplete)
92 document()->unregisterForDocumentActivationCallbacks(this);
93
94 delete m_elementAliases;
95 delete collectionInfo;
96
97 for (unsigned i = 0; i < formElements.size(); ++i)
98 formElements[i]->formDestroyed();
99 for (unsigned i = 0; i < imgElements.size(); ++i)
100 imgElements[i]->m_form = 0;
101 }
102
formWouldHaveSecureSubmission(const String & url)103 bool HTMLFormElement::formWouldHaveSecureSubmission(const String& url)
104 {
105 return document()->completeURL(url).protocolIs("https");
106 }
107
attach()108 void HTMLFormElement::attach()
109 {
110 HTMLElement::attach();
111 }
112
rendererIsNeeded(RenderStyle * style)113 bool HTMLFormElement::rendererIsNeeded(RenderStyle* style)
114 {
115 if (!isDemoted())
116 return HTMLElement::rendererIsNeeded(style);
117
118 Node* node = parentNode();
119 RenderObject* parentRenderer = node->renderer();
120 bool parentIsTableElementPart = (parentRenderer->isTable() && node->hasTagName(tableTag))
121 || (parentRenderer->isTableRow() && node->hasTagName(trTag))
122 || (parentRenderer->isTableSection() && node->hasTagName(tbodyTag))
123 || (parentRenderer->isTableCol() && node->hasTagName(colTag))
124 || (parentRenderer->isTableCell() && node->hasTagName(trTag));
125
126 if (!parentIsTableElementPart)
127 return true;
128
129 EDisplay display = style->display();
130 bool formIsTablePart = display == TABLE || display == INLINE_TABLE || display == TABLE_ROW_GROUP
131 || display == TABLE_HEADER_GROUP || display == TABLE_FOOTER_GROUP || display == TABLE_ROW
132 || display == TABLE_COLUMN_GROUP || display == TABLE_COLUMN || display == TABLE_CELL
133 || display == TABLE_CAPTION;
134
135 return formIsTablePart;
136 }
137
insertedIntoDocument()138 void HTMLFormElement::insertedIntoDocument()
139 {
140 if (document()->isHTMLDocument())
141 static_cast<HTMLDocument*>(document())->addNamedItem(m_name);
142
143 HTMLElement::insertedIntoDocument();
144 }
145
removedFromDocument()146 void HTMLFormElement::removedFromDocument()
147 {
148 if (document()->isHTMLDocument())
149 static_cast<HTMLDocument*>(document())->removeNamedItem(m_name);
150
151 HTMLElement::removedFromDocument();
152 }
153
handleLocalEvents(Event * event)154 void HTMLFormElement::handleLocalEvents(Event* event)
155 {
156 Node* targetNode = event->target()->toNode();
157 if (event->eventPhase() != Event::CAPTURING_PHASE && targetNode && targetNode != this && (event->type() == eventNames().submitEvent || event->type() == eventNames().resetEvent)) {
158 event->stopPropagation();
159 return;
160 }
161 HTMLElement::handleLocalEvents(event);
162 }
163
length() const164 unsigned HTMLFormElement::length() const
165 {
166 int len = 0;
167 for (unsigned i = 0; i < formElements.size(); ++i)
168 if (formElements[i]->isEnumeratable())
169 ++len;
170
171 return len;
172 }
173
item(unsigned index)174 Node* HTMLFormElement::item(unsigned index)
175 {
176 return elements()->item(index);
177 }
178
submitClick(Event * event)179 void HTMLFormElement::submitClick(Event* event)
180 {
181 bool submitFound = false;
182 for (unsigned i = 0; i < formElements.size(); ++i) {
183 if (formElements[i]->hasLocalName(inputTag)) {
184 HTMLInputElement* element = static_cast<HTMLInputElement*>(formElements[i]);
185 if (element->isSuccessfulSubmitButton() && element->renderer()) {
186 submitFound = true;
187 element->dispatchSimulatedClick(event);
188 break;
189 }
190 }
191 }
192 if (!submitFound) // submit the form without a submit or image input
193 prepareSubmit(event);
194 }
195
dataEncoding() const196 TextEncoding HTMLFormElement::dataEncoding() const
197 {
198 if (isMailtoForm())
199 return UTF8Encoding();
200
201 return m_formDataBuilder.dataEncoding(document());
202 }
203
createFormData(const CString & boundary)204 PassRefPtr<FormData> HTMLFormElement::createFormData(const CString& boundary)
205 {
206 Vector<char> encodedData;
207 TextEncoding encoding = dataEncoding().encodingForFormSubmission();
208
209 RefPtr<FormData> result = FormData::create();
210
211 for (unsigned i = 0; i < formElements.size(); ++i) {
212 HTMLFormControlElement* control = formElements[i];
213 FormDataList list(encoding);
214
215 if (!control->disabled() && control->appendFormData(list, m_formDataBuilder.isMultiPartForm())) {
216 size_t formDataListSize = list.list().size();
217 ASSERT(formDataListSize % 2 == 0);
218 for (size_t j = 0; j < formDataListSize; j += 2) {
219 const FormDataList::Item& key = list.list()[j];
220 const FormDataList::Item& value = list.list()[j + 1];
221 if (!m_formDataBuilder.isMultiPartForm()) {
222 // Omit the name "isindex" if it's the first form data element.
223 // FIXME: Why is this a good rule? Is this obsolete now?
224 if (encodedData.isEmpty() && key.data() == "isindex")
225 FormDataBuilder::encodeStringAsFormData(encodedData, value.data());
226 else
227 m_formDataBuilder.addKeyValuePairAsFormData(encodedData, key.data(), value.data());
228 } else {
229 Vector<char> header;
230 m_formDataBuilder.beginMultiPartHeader(header, boundary, key.data());
231
232 bool shouldGenerateFile = false;
233 // if the current type is FILE, then we also need to include the filename
234 if (value.file()) {
235 const String& path = value.file()->path();
236 String fileName = value.file()->fileName();
237
238 // Let the application specify a filename if it's going to generate a replacement file for the upload.
239 if (!path.isEmpty()) {
240 if (Page* page = document()->page()) {
241 String generatedFileName;
242 shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName);
243 if (shouldGenerateFile)
244 fileName = generatedFileName;
245 }
246 }
247
248 // We have to include the filename=".." part in the header, even if the filename is empty
249 m_formDataBuilder.addFilenameToMultiPartHeader(header, encoding, fileName);
250
251 if (!fileName.isEmpty()) {
252 // FIXME: The MIMETypeRegistry function's name makes it sound like it takes a path,
253 // not just a basename. But filename is not the path. But note that it's not safe to
254 // just use path instead since in the generated-file case it will not reflect the
255 // MIME type of the generated file.
256 String mimeType = MIMETypeRegistry::getMIMETypeForPath(fileName);
257 if (!mimeType.isEmpty())
258 m_formDataBuilder.addContentTypeToMultiPartHeader(header, mimeType.latin1());
259 }
260 }
261
262 m_formDataBuilder.finishMultiPartHeader(header);
263
264 // Append body
265 result->appendData(header.data(), header.size());
266 if (size_t dataSize = value.data().length())
267 result->appendData(value.data().data(), dataSize);
268 else if (value.file() && !value.file()->path().isEmpty())
269 result->appendFile(value.file()->path(), shouldGenerateFile);
270
271 result->appendData("\r\n", 2);
272 }
273 }
274 }
275 }
276
277 if (m_formDataBuilder.isMultiPartForm())
278 m_formDataBuilder.addBoundaryToMultiPartHeader(encodedData, boundary, true);
279
280 result->appendData(encodedData.data(), encodedData.size());
281
282 result->setIdentifier(generateFormDataIdentifier());
283 return result;
284 }
285
isMailtoForm() const286 bool HTMLFormElement::isMailtoForm() const
287 {
288 return protocolIs(m_url, "mailto");
289 }
290
prepareSubmit(Event * event)291 bool HTMLFormElement::prepareSubmit(Event* event)
292 {
293 Frame* frame = document()->frame();
294 if (m_insubmit || !frame)
295 return m_insubmit;
296
297 m_insubmit = true;
298 m_doingsubmit = false;
299
300 if (dispatchEvent(Event::create(eventNames().submitEvent, true, true)) && !m_doingsubmit)
301 m_doingsubmit = true;
302
303 m_insubmit = false;
304
305 if (m_doingsubmit)
306 submit(event, true, false, NotSubmittedByJavaScript);
307
308 return m_doingsubmit;
309 }
310
transferMailtoPostFormDataToURL(RefPtr<FormData> & data,KURL & url,const String & encodingType)311 static void transferMailtoPostFormDataToURL(RefPtr<FormData>& data, KURL& url, const String& encodingType)
312 {
313 String body = data->flattenToString();
314 data = FormData::create();
315
316 if (equalIgnoringCase(encodingType, "text/plain")) {
317 // Convention seems to be to decode, and s/&/\r\n/. Also, spaces are encoded as %20.
318 body = decodeURLEscapeSequences(body.replace('&', "\r\n").replace('+', ' ') + "\r\n");
319 }
320
321 Vector<char> bodyData;
322 bodyData.append("body=", 5);
323 FormDataBuilder::encodeStringAsFormData(bodyData, body.utf8());
324 body = String(bodyData.data(), bodyData.size()).replace('+', "%20");
325
326 String query = url.query();
327 if (!query.isEmpty())
328 query.append('&');
329 query.append(body);
330 url.setQuery(query);
331 }
332
submit(Frame * javaScriptActiveFrame)333 void HTMLFormElement::submit(Frame* javaScriptActiveFrame)
334 {
335 if (javaScriptActiveFrame)
336 submit(0, false, !javaScriptActiveFrame->script()->anyPageIsProcessingUserGesture(), SubmittedByJavaScript);
337 else
338 submit(0, false, false, NotSubmittedByJavaScript);
339 }
340
submit(Event * event,bool activateSubmitButton,bool lockHistory,FormSubmissionTrigger formSubmissionTrigger)341 void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockHistory, FormSubmissionTrigger formSubmissionTrigger)
342 {
343 FrameView* view = document()->view();
344 Frame* frame = document()->frame();
345 if (!view || !frame)
346 return;
347
348 if (m_insubmit) {
349 m_doingsubmit = true;
350 return;
351 }
352
353 m_insubmit = true;
354
355 HTMLFormControlElement* firstSuccessfulSubmitButton = 0;
356 bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button?
357
358 Vector<pair<String, String> > formValues;
359
360 for (unsigned i = 0; i < formElements.size(); ++i) {
361 HTMLFormControlElement* control = formElements[i];
362 if (control->hasLocalName(inputTag)) {
363 HTMLInputElement* input = static_cast<HTMLInputElement*>(control);
364 if (input->isTextField()) {
365 formValues.append(pair<String, String>(input->name(), input->value()));
366 if (input->isSearchField())
367 input->addSearchResult();
368 }
369 }
370 if (needButtonActivation) {
371 if (control->isActivatedSubmit())
372 needButtonActivation = false;
373 else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton())
374 firstSuccessfulSubmitButton = control;
375 }
376 }
377
378 RefPtr<FormState> formState = FormState::create(this, formValues, frame, formSubmissionTrigger);
379
380 if (needButtonActivation && firstSuccessfulSubmitButton)
381 firstSuccessfulSubmitButton->setActivatedSubmit(true);
382
383 if (m_url.isEmpty())
384 m_url = document()->url().string();
385
386 if (m_formDataBuilder.isPostMethod()) {
387 if (m_formDataBuilder.isMultiPartForm() && isMailtoForm()) {
388 setEnctype("application/x-www-form-urlencoded");
389 ASSERT(!m_formDataBuilder.isMultiPartForm());
390 }
391
392 if (!m_formDataBuilder.isMultiPartForm()) {
393 RefPtr<FormData> data = createFormData(CString());
394
395 if (isMailtoForm()) {
396 // Convert the form data into a string that we put into the URL.
397 KURL url = document()->completeURL(m_url);
398 transferMailtoPostFormDataToURL(data, url, m_formDataBuilder.encodingType());
399 m_url = url.string();
400 }
401
402 frame->loader()->submitForm("POST", m_url, data.release(), m_target, m_formDataBuilder.encodingType(), String(), lockHistory, event, formState.release());
403 } else {
404 Vector<char> boundary = m_formDataBuilder.generateUniqueBoundaryString();
405 frame->loader()->submitForm("POST", m_url, createFormData(boundary.data()), m_target, m_formDataBuilder.encodingType(), boundary.data(), lockHistory, event, formState.release());
406 }
407 } else {
408 m_formDataBuilder.setIsMultiPartForm(false);
409 frame->loader()->submitForm("GET", m_url, createFormData(CString()), m_target, String(), String(), lockHistory, event, formState.release());
410 }
411
412 if (needButtonActivation && firstSuccessfulSubmitButton)
413 firstSuccessfulSubmitButton->setActivatedSubmit(false);
414
415 m_doingsubmit = m_insubmit = false;
416 }
417
reset()418 void HTMLFormElement::reset()
419 {
420 Frame* frame = document()->frame();
421 if (m_inreset || !frame)
422 return;
423
424 m_inreset = true;
425
426 // ### DOM2 labels this event as not cancelable, however
427 // common browsers( sick! ) allow it be cancelled.
428 if (!dispatchEvent(Event::create(eventNames().resetEvent, true, true))) {
429 m_inreset = false;
430 return;
431 }
432
433 for (unsigned i = 0; i < formElements.size(); ++i)
434 formElements[i]->reset();
435
436 m_inreset = false;
437 }
438
parseMappedAttribute(MappedAttribute * attr)439 void HTMLFormElement::parseMappedAttribute(MappedAttribute* attr)
440 {
441 if (attr->name() == actionAttr)
442 m_url = deprecatedParseURL(attr->value());
443 else if (attr->name() == targetAttr)
444 m_target = attr->value();
445 else if (attr->name() == methodAttr)
446 m_formDataBuilder.parseMethodType(attr->value());
447 else if (attr->name() == enctypeAttr)
448 m_formDataBuilder.parseEncodingType(attr->value());
449 else if (attr->name() == accept_charsetAttr)
450 // space separated list of charsets the server
451 // accepts - see rfc2045
452 m_formDataBuilder.setAcceptCharset(attr->value());
453 else if (attr->name() == acceptAttr) {
454 // ignore this one for the moment...
455 } else if (attr->name() == autocompleteAttr) {
456 m_autocomplete = !equalIgnoringCase(attr->value(), "off");
457 if (!m_autocomplete)
458 document()->registerForDocumentActivationCallbacks(this);
459 else
460 document()->unregisterForDocumentActivationCallbacks(this);
461 } else if (attr->name() == onsubmitAttr)
462 setAttributeEventListener(eventNames().submitEvent, createAttributeEventListener(this, attr));
463 else if (attr->name() == onresetAttr)
464 setAttributeEventListener(eventNames().resetEvent, createAttributeEventListener(this, attr));
465 else if (attr->name() == nameAttr) {
466 const AtomicString& newName = attr->value();
467 if (inDocument() && document()->isHTMLDocument()) {
468 HTMLDocument* document = static_cast<HTMLDocument*>(this->document());
469 document->removeNamedItem(m_name);
470 document->addNamedItem(newName);
471 }
472 m_name = newName;
473 } else
474 HTMLElement::parseMappedAttribute(attr);
475 }
476
removeFromVector(Vector<T *,n> & vec,T * item)477 template<class T, size_t n> static void removeFromVector(Vector<T*, n> & vec, T* item)
478 {
479 size_t size = vec.size();
480 for (size_t i = 0; i != size; ++i)
481 if (vec[i] == item) {
482 vec.remove(i);
483 break;
484 }
485 }
486
formElementIndex(HTMLFormControlElement * e)487 unsigned HTMLFormElement::formElementIndex(HTMLFormControlElement* e)
488 {
489 // Check for the special case where this element is the very last thing in
490 // the form's tree of children; we don't want to walk the entire tree in that
491 // common case that occurs during parsing; instead we'll just return a value
492 // that says "add this form element to the end of the array".
493 if (e->traverseNextNode(this)) {
494 unsigned i = 0;
495 for (Node* node = this; node; node = node->traverseNextNode(this)) {
496 if (node == e)
497 return i;
498 if (node->isHTMLElement()
499 && static_cast<Element*>(node)->isFormControlElement()
500 && static_cast<HTMLFormControlElement*>(node)->form() == this)
501 ++i;
502 }
503 }
504 return formElements.size();
505 }
506
registerFormElement(HTMLFormControlElement * e)507 void HTMLFormElement::registerFormElement(HTMLFormControlElement* e)
508 {
509 document()->checkedRadioButtons().removeButton(e);
510 m_checkedRadioButtons.addButton(e);
511 formElements.insert(formElementIndex(e), e);
512 }
513
removeFormElement(HTMLFormControlElement * e)514 void HTMLFormElement::removeFormElement(HTMLFormControlElement* e)
515 {
516 m_checkedRadioButtons.removeButton(e);
517 removeFromVector(formElements, e);
518 }
519
isURLAttribute(Attribute * attr) const520 bool HTMLFormElement::isURLAttribute(Attribute* attr) const
521 {
522 return attr->name() == actionAttr;
523 }
524
registerImgElement(HTMLImageElement * e)525 void HTMLFormElement::registerImgElement(HTMLImageElement* e)
526 {
527 ASSERT(imgElements.find(e) == notFound);
528 imgElements.append(e);
529 }
530
removeImgElement(HTMLImageElement * e)531 void HTMLFormElement::removeImgElement(HTMLImageElement* e)
532 {
533 ASSERT(imgElements.find(e) != notFound);
534 removeFromVector(imgElements, e);
535 }
536
elements()537 PassRefPtr<HTMLCollection> HTMLFormElement::elements()
538 {
539 return HTMLFormCollection::create(this);
540 }
541
name() const542 String HTMLFormElement::name() const
543 {
544 return getAttribute(nameAttr);
545 }
546
setName(const String & value)547 void HTMLFormElement::setName(const String &value)
548 {
549 setAttribute(nameAttr, value);
550 }
551
noValidate() const552 bool HTMLFormElement::noValidate() const
553 {
554 return !getAttribute(novalidateAttr).isNull();
555 }
556
setNoValidate(bool novalidate)557 void HTMLFormElement::setNoValidate(bool novalidate)
558 {
559 setAttribute(novalidateAttr, novalidate ? "" : 0);
560 }
561
setAcceptCharset(const String & value)562 void HTMLFormElement::setAcceptCharset(const String &value)
563 {
564 setAttribute(accept_charsetAttr, value);
565 }
566
action() const567 String HTMLFormElement::action() const
568 {
569 return getAttribute(actionAttr);
570 }
571
setAction(const String & value)572 void HTMLFormElement::setAction(const String &value)
573 {
574 setAttribute(actionAttr, value);
575 }
576
setEnctype(const String & value)577 void HTMLFormElement::setEnctype(const String &value)
578 {
579 setAttribute(enctypeAttr, value);
580 }
581
method() const582 String HTMLFormElement::method() const
583 {
584 return getAttribute(methodAttr);
585 }
586
setMethod(const String & value)587 void HTMLFormElement::setMethod(const String &value)
588 {
589 setAttribute(methodAttr, value);
590 }
591
target() const592 String HTMLFormElement::target() const
593 {
594 return getAttribute(targetAttr);
595 }
596
setTarget(const String & value)597 void HTMLFormElement::setTarget(const String &value)
598 {
599 setAttribute(targetAttr, value);
600 }
601
defaultButton() const602 HTMLFormControlElement* HTMLFormElement::defaultButton() const
603 {
604 for (unsigned i = 0; i < formElements.size(); ++i) {
605 HTMLFormControlElement* control = formElements[i];
606 if (control->isSuccessfulSubmitButton())
607 return control;
608 }
609
610 return 0;
611 }
612
checkValidity()613 bool HTMLFormElement::checkValidity()
614 {
615 // TODO: Check for unhandled invalid controls, see #27452 for tips.
616
617 bool hasOnlyValidControls = true;
618 for (unsigned i = 0; i < formElements.size(); ++i) {
619 HTMLFormControlElement* control = formElements[i];
620 if (!control->checkValidity())
621 hasOnlyValidControls = false;
622 }
623
624 return hasOnlyValidControls;
625 }
626
elementForAlias(const AtomicString & alias)627 PassRefPtr<HTMLFormControlElement> HTMLFormElement::elementForAlias(const AtomicString& alias)
628 {
629 if (alias.isEmpty() || !m_elementAliases)
630 return 0;
631 return m_elementAliases->get(alias.impl());
632 }
633
addElementAlias(HTMLFormControlElement * element,const AtomicString & alias)634 void HTMLFormElement::addElementAlias(HTMLFormControlElement* element, const AtomicString& alias)
635 {
636 if (alias.isEmpty())
637 return;
638 if (!m_elementAliases)
639 m_elementAliases = new AliasMap;
640 m_elementAliases->set(alias.impl(), element);
641 }
642
getNamedElements(const AtomicString & name,Vector<RefPtr<Node>> & namedItems)643 void HTMLFormElement::getNamedElements(const AtomicString& name, Vector<RefPtr<Node> >& namedItems)
644 {
645 elements()->namedItems(name, namedItems);
646
647 // see if we have seen something with this name before
648 RefPtr<HTMLFormControlElement> aliasElem;
649 if (aliasElem = elementForAlias(name)) {
650 bool found = false;
651 for (unsigned n = 0; n < namedItems.size(); n++) {
652 if (namedItems[n] == aliasElem.get()) {
653 found = true;
654 break;
655 }
656 }
657 if (!found)
658 // we have seen it before but it is gone now. still, we need to return it.
659 namedItems.append(aliasElem.get());
660 }
661 // name has been accessed, remember it
662 if (namedItems.size() && aliasElem != namedItems.first())
663 addElementAlias(static_cast<HTMLFormControlElement*>(namedItems.first().get()), name);
664 }
665
documentDidBecomeActive()666 void HTMLFormElement::documentDidBecomeActive()
667 {
668 ASSERT(!m_autocomplete);
669
670 for (unsigned i = 0; i < formElements.size(); ++i)
671 formElements[i]->reset();
672 }
673
willMoveToNewOwnerDocument()674 void HTMLFormElement::willMoveToNewOwnerDocument()
675 {
676 if (!m_autocomplete)
677 document()->unregisterForDocumentActivationCallbacks(this);
678 HTMLElement::willMoveToNewOwnerDocument();
679 }
680
didMoveToNewOwnerDocument()681 void HTMLFormElement::didMoveToNewOwnerDocument()
682 {
683 if (!m_autocomplete)
684 document()->registerForDocumentActivationCallbacks(this);
685 HTMLElement::didMoveToNewOwnerDocument();
686 }
687
688 } // namespace
689