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