diff options
Diffstat (limited to 'WebCore/html/HTMLFormElement.cpp')
-rw-r--r-- | WebCore/html/HTMLFormElement.cpp | 805 |
1 files changed, 0 insertions, 805 deletions
diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp deleted file mode 100644 index 0e4d88e..0000000 --- a/WebCore/html/HTMLFormElement.cpp +++ /dev/null @@ -1,805 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 1999 Antti Koivisto (koivisto@kde.org) - * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * (C) 2006 Alexey Proskuryakov (ap@nypop.com) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" -#include "HTMLFormElement.h" - -#include "CSSHelper.h" -#include "ChromeClient.h" -#include "Document.h" -#include "Event.h" -#include "EventNames.h" -#include "FileList.h" -#include "FileSystem.h" -#include "FormData.h" -#include "FormDataList.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "HTMLDocument.h" -#include "HTMLFormCollection.h" -#include "HTMLImageElement.h" -#include "HTMLInputElement.h" -#include "HTMLNames.h" -#include "MIMETypeRegistry.h" -#include "Page.h" -#include "RenderTextControl.h" - -#if PLATFORM(QT) -#include <QtCore/QFileInfo> -#endif - -#if PLATFORM(WX) -#include <wx/defs.h> -#include <wx/filename.h> -#endif - -#if PLATFORM(WIN_OS) -#include <shlwapi.h> -#endif - -namespace WebCore { - -using namespace HTMLNames; - -static const char hexDigits[17] = "0123456789ABCDEF"; - -HTMLFormElement::HTMLFormElement(Document* doc) - : HTMLElement(formTag, doc) - , m_elementAliases(0) - , collectionInfo(0) - , m_enctype("application/x-www-form-urlencoded") - , m_post(false) - , m_multipart(false) - , m_autocomplete(true) - , m_insubmit(false) - , m_doingsubmit(false) - , m_inreset(false) - , m_malformed(false) -{ -} - -HTMLFormElement::~HTMLFormElement() -{ - if (!m_autocomplete) - document()->unregisterForDocumentActivationCallbacks(this); - - delete m_elementAliases; - delete collectionInfo; - - for (unsigned i = 0; i < formElements.size(); ++i) - formElements[i]->formDestroyed(); - for (unsigned i = 0; i < imgElements.size(); ++i) - imgElements[i]->m_form = 0; -} - -bool HTMLFormElement::formWouldHaveSecureSubmission(const String& url) -{ - return document()->completeURL(url).protocolIs("https"); -} - -void HTMLFormElement::attach() -{ - HTMLElement::attach(); -} - -void HTMLFormElement::insertedIntoDocument() -{ - if (document()->isHTMLDocument()) - static_cast<HTMLDocument*>(document())->addNamedItem(m_name); - - HTMLElement::insertedIntoDocument(); -} - -void HTMLFormElement::removedFromDocument() -{ - if (document()->isHTMLDocument()) - static_cast<HTMLDocument*>(document())->removeNamedItem(m_name); - - HTMLElement::removedFromDocument(); -} - -void HTMLFormElement::handleLocalEvents(Event* event, bool useCapture) -{ - EventTargetNode* targetNode = event->target()->toNode(); - if (!useCapture && targetNode && targetNode != this && (event->type() == eventNames().submitEvent || event->type() == eventNames().resetEvent)) { - event->stopPropagation(); - return; - } - HTMLElement::handleLocalEvents(event, useCapture); -} - -unsigned HTMLFormElement::length() const -{ - int len = 0; - for (unsigned i = 0; i < formElements.size(); ++i) - if (formElements[i]->isEnumeratable()) - ++len; - - return len; -} - -Node* HTMLFormElement::item(unsigned index) -{ - return elements()->item(index); -} - -void HTMLFormElement::submitClick(Event* event) -{ - bool submitFound = false; - for (unsigned i = 0; i < formElements.size(); ++i) { - if (formElements[i]->hasLocalName(inputTag)) { - HTMLInputElement* element = static_cast<HTMLInputElement*>(formElements[i]); - if (element->isSuccessfulSubmitButton() && element->renderer()) { - submitFound = true; - element->dispatchSimulatedClick(event); - break; - } - } - } - if (!submitFound) // submit the form without a submit or image input - prepareSubmit(event); -} - -static void appendString(Vector<char>& buffer, const char* string) -{ - buffer.append(string, strlen(string)); -} - -static void appendString(Vector<char>& buffer, const CString& string) -{ - buffer.append(string.data(), string.length()); -} - -static void appendEncodedString(Vector<char>& buffer, const CString& string) -{ - // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1 - int length = string.length(); - for (int i = 0; i < length; i++) { - unsigned char c = string.data()[i]; - - // Same safe characters as Netscape for compatibility. - static const char safe[] = "-._*"; - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || strchr(safe, c)) - buffer.append(c); - else if (c == ' ') - buffer.append('+'); - else if (c == '\n' || (c == '\r' && (i + 1 >= length || string.data()[i + 1] != '\n'))) - appendString(buffer, "%0D%0A"); - else if (c != '\r') { - buffer.append('%'); - buffer.append(hexDigits[c >> 4]); - buffer.append(hexDigits[c & 0xF]); - } - } -} - -// FIXME: Move to platform directory? -static int randomNumber() -{ - static bool randomSeeded = false; - -#if PLATFORM(DARWIN) - if (!randomSeeded) { - srandomdev(); - randomSeeded = true; - } - return random(); -#else - if (!randomSeeded) { - srand(static_cast<unsigned>(time(0))); - randomSeeded = true; - } - return rand(); -#endif -} - -TextEncoding HTMLFormElement::dataEncoding() const -{ - if (isMailtoForm()) - return UTF8Encoding(); - - TextEncoding encoding; - String str = m_acceptcharset; - str.replace(',', ' '); - Vector<String> charsets; - str.split(' ', charsets); - Vector<String>::const_iterator end = charsets.end(); - for (Vector<String>::const_iterator it = charsets.begin(); it != end; ++it) - if ((encoding = TextEncoding(*it)).isValid()) - return encoding; - if (Frame* frame = document()->frame()) - return frame->loader()->encoding(); - return Latin1Encoding(); -} - -PassRefPtr<FormData> HTMLFormElement::formData(const char* boundary) const -{ - Vector<char> encodedData; - TextEncoding encoding = dataEncoding(); - - RefPtr<FormData> result = FormData::create(); - - for (unsigned i = 0; i < formElements.size(); ++i) { - HTMLFormControlElement* control = formElements[i]; - FormDataList list(encoding); - - if (!control->disabled() && control->appendFormData(list, m_multipart)) { - size_t formDataListSize = list.list().size(); - ASSERT(formDataListSize % 2 == 0); - for (size_t j = 0; j < formDataListSize; j += 2) { - const FormDataList::Item& key = list.list()[j]; - const FormDataList::Item& value = list.list()[j + 1]; - if (!m_multipart) { - // Omit the name "isindex" if it's the first form data element. - // FIXME: Why is this a good rule? Is this obsolete now? - if (encodedData.isEmpty() && key.data() == "isindex") - appendEncodedString(encodedData, value.data()); - else { - if (!encodedData.isEmpty()) - encodedData.append('&'); - appendEncodedString(encodedData, key.data()); - encodedData.append('='); - appendEncodedString(encodedData, value.data()); - } - } else { - Vector<char> header; - appendString(header, "--"); - appendString(header, boundary); - appendString(header, "\r\n"); - appendString(header, "Content-Disposition: form-data; name=\""); - header.append(key.data().data(), key.data().length()); - header.append('"'); - - bool shouldGenerateFile = false; - // if the current type is FILE, then we also need to - // include the filename - if (value.file()) { - const String& path = value.file()->path(); - String filename = value.file()->fileName(); - - // Let the application specify a filename if it's going to generate a replacement file for the upload. - if (!path.isEmpty()) { - if (Page* page = document()->page()) { - String generatedFilename; - shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFilename); - if (shouldGenerateFile) - filename = generatedFilename; - } - } - - // FIXME: This won't work if the filename includes a " mark, - // or control characters like CR or LF. This also does strange - // things if the filename includes characters you can't encode - // in the website's character set. - appendString(header, "; filename=\""); - appendString(header, encoding.encode(filename.characters(), filename.length(), QuestionMarksForUnencodables)); - header.append('"'); - - if (!filename.isEmpty()) { - // FIXME: The MIMETypeRegistry function's name makes it sound like it takes a path, - // not just a basename. But filename is not the path. But note that it's not safe to - // just use path instead since in the generated-file case it will not reflect the - // MIME type of the generated file. - String mimeType = MIMETypeRegistry::getMIMETypeForPath(filename); - if (!mimeType.isEmpty()) { - appendString(header, "\r\nContent-Type: "); - appendString(header, mimeType.latin1()); - } - } - } - - appendString(header, "\r\n\r\n"); - - // append body - result->appendData(header.data(), header.size()); - if (size_t dataSize = value.data().length()) - result->appendData(value.data().data(), dataSize); - else if (value.file() && !value.file()->path().isEmpty()) - result->appendFile(value.file()->path(), shouldGenerateFile); - result->appendData("\r\n", 2); - } - } - } - } - - - if (m_multipart) { - appendString(encodedData, "--"); - appendString(encodedData, boundary); - appendString(encodedData, "--\r\n"); - } - - result->appendData(encodedData.data(), encodedData.size()); - return result; -} - -void HTMLFormElement::parseEnctype(const String& type) -{ - if(type.contains("multipart", false) || type.contains("form-data", false)) { - m_enctype = "multipart/form-data"; - m_multipart = true; - } else if (type.contains("text", false) || type.contains("plain", false)) { - m_enctype = "text/plain"; - m_multipart = false; - } else { - m_enctype = "application/x-www-form-urlencoded"; - m_multipart = false; - } -} - -bool HTMLFormElement::isMailtoForm() const -{ - return protocolIs(m_url, "mailto"); -} - -bool HTMLFormElement::prepareSubmit(Event* event) -{ - Frame* frame = document()->frame(); - if (m_insubmit || !frame) - return m_insubmit; - - m_insubmit = true; - m_doingsubmit = false; - - if (dispatchEventForType(eventNames().submitEvent, true, true) && !m_doingsubmit) - m_doingsubmit = true; - - m_insubmit = false; - - if (m_doingsubmit) - submit(event, true); - - return m_doingsubmit; -} - -void HTMLFormElement::submit() -{ - submit(0, false); -} - -// Returns a 0-terminated C string in the vector. -static void getUniqueBoundaryString(Vector<char>& boundary) -{ - // The RFC 2046 spec says the AlphaNumeric characters plus the following characters - // are legal for boundaries: '()+_,-./:=? - // However the following characters, though legal, cause some sites to fail: - // (),./:= - // http://bugs.webkit.org/show_bug.cgi?id=13352 - static const char AlphaNumericEncMap[64] = - { - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, - 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, - 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, - 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, - 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x41 - // FIXME <rdar://problem/5252577> gmail does not accept legal characters in the form boundary - // As stated above, some legal characters cause, sites to fail. Specifically - // the / character which was the last character in the above array. I have - // replaced the last character with another character already in the array - // (notice the first and last values are both 0x41, A). Instead of picking - // another unique legal character for boundary strings that, because it has - // never been tested, may or may not break other sites, I simply - // replaced / with A. This means A is twice as likely to occur in our boundary - // strings than any other character but I think this is fine for the time being. - // The FIXME here is about restoring the / character once the aforementioned - // radar has been resolved. - }; - - // Start with an informative prefix. - const char boundaryPrefix[] = "----WebKitFormBoundary"; - boundary.append(boundaryPrefix, strlen(boundaryPrefix)); - - // Append 16 random 7bit ascii AlphaNumeric characters. - Vector<char> randomBytes; - - for (int i = 0; i < 4; ++i) { - int randomness = randomNumber(); - randomBytes.append(AlphaNumericEncMap[(randomness >> 24) & 0x3F]); - randomBytes.append(AlphaNumericEncMap[(randomness >> 16) & 0x3F]); - randomBytes.append(AlphaNumericEncMap[(randomness >> 8) & 0x3F]); - randomBytes.append(AlphaNumericEncMap[randomness & 0x3F]); - } - - boundary.append(randomBytes); - boundary.append(0); // Add a 0 at the end so we can use this as a C-style string. -} - -void HTMLFormElement::submit(Event* event, bool activateSubmitButton) -{ - FrameView* view = document()->view(); - Frame* frame = document()->frame(); - if (!view || !frame) - return; - - if (m_insubmit) { - m_doingsubmit = true; - return; - } - - m_insubmit = true; - - HTMLFormControlElement* firstSuccessfulSubmitButton = 0; - bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button? - - frame->loader()->clearRecordedFormValues(); - frame->loader()->setFormAboutToBeSubmitted(this); - for (unsigned i = 0; i < formElements.size(); ++i) { - HTMLFormControlElement* control = formElements[i]; - if (control->hasLocalName(inputTag)) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(control); - if (input->isTextField()) { - frame->loader()->recordFormValue(input->name(), input->value()); - if (input->isSearchField()) - input->addSearchResult(); - } - } - if (needButtonActivation) { - if (control->isActivatedSubmit()) - needButtonActivation = false; - else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton()) - firstSuccessfulSubmitButton = control; - } - } - - if (needButtonActivation && firstSuccessfulSubmitButton) - firstSuccessfulSubmitButton->setActivatedSubmit(true); - - if (m_url.isEmpty()) - m_url = document()->url().string(); - - if (m_post) { - if (m_multipart && isMailtoForm()) { - setEnctype("application/x-www-form-urlencoded"); - m_multipart = false; - } - - if (!m_multipart) { - RefPtr<FormData> data = formData(0); - if (isMailtoForm()) { - String body = data->flattenToString(); - if (equalIgnoringCase(enctype(), "text/plain")) { - // Convention seems to be to decode, and s/&/\r\n/. Also, spaces are encoded as %20. - body = decodeURLEscapeSequences(body.replace('&', "\r\n").replace('+', ' ') + "\r\n"); - } - Vector<char> bodyData; - appendString(bodyData, "body="); - appendEncodedString(bodyData, body.utf8()); - data = FormData::create(String(bodyData.data(), bodyData.size()).replace('+', "%20").latin1()); - } - frame->loader()->submitForm("POST", m_url, data, m_target, enctype(), String(), event); - } else { - Vector<char> boundary; - getUniqueBoundaryString(boundary); - frame->loader()->submitForm("POST", m_url, formData(boundary.data()), m_target, enctype(), boundary.data(), event); - } - } else { - m_multipart = false; - frame->loader()->submitForm("GET", m_url, formData(0), m_target, String(), String(), event); - } - - if (needButtonActivation && firstSuccessfulSubmitButton) - firstSuccessfulSubmitButton->setActivatedSubmit(false); - - m_doingsubmit = m_insubmit = false; -} - -void HTMLFormElement::reset() -{ - Frame* frame = document()->frame(); - if (m_inreset || !frame) - return; - - m_inreset = true; - - // ### DOM2 labels this event as not cancelable, however - // common browsers( sick! ) allow it be cancelled. - if ( !dispatchEventForType(eventNames().resetEvent,true, true) ) { - m_inreset = false; - return; - } - - for (unsigned i = 0; i < formElements.size(); ++i) - formElements[i]->reset(); - - m_inreset = false; -} - -void HTMLFormElement::parseMappedAttribute(MappedAttribute* attr) -{ - if (attr->name() == actionAttr) - m_url = parseURL(attr->value()); - else if (attr->name() == targetAttr) - m_target = attr->value(); - else if (attr->name() == methodAttr) { - if (equalIgnoringCase(attr->value(), "post")) - m_post = true; - else if (equalIgnoringCase(attr->value(), "get")) - m_post = false; - } else if (attr->name() == enctypeAttr) - parseEnctype(attr->value()); - else if (attr->name() == accept_charsetAttr) - // space separated list of charsets the server - // accepts - see rfc2045 - m_acceptcharset = attr->value(); - else if (attr->name() == acceptAttr) { - // ignore this one for the moment... - } else if (attr->name() == autocompleteAttr) { - m_autocomplete = !equalIgnoringCase(attr->value(), "off"); - if (!m_autocomplete) - document()->registerForDocumentActivationCallbacks(this); - else - document()->unregisterForDocumentActivationCallbacks(this); - } else if (attr->name() == onsubmitAttr) - setInlineEventListenerForTypeAndAttribute(eventNames().submitEvent, attr); - else if (attr->name() == onresetAttr) - setInlineEventListenerForTypeAndAttribute(eventNames().resetEvent, attr); - else if (attr->name() == nameAttr) { - const AtomicString& newName = attr->value(); - if (inDocument() && document()->isHTMLDocument()) { - HTMLDocument* document = static_cast<HTMLDocument*>(this->document()); - document->removeNamedItem(m_name); - document->addNamedItem(newName); - } - m_name = newName; - } else - HTMLElement::parseMappedAttribute(attr); -} - -template<class T, size_t n> static void removeFromVector(Vector<T*, n> & vec, T* item) -{ - size_t size = vec.size(); - for (size_t i = 0; i != size; ++i) - if (vec[i] == item) { - vec.remove(i); - break; - } -} - -unsigned HTMLFormElement::formElementIndex(HTMLFormControlElement* e) -{ - // Check for the special case where this element is the very last thing in - // the form's tree of children; we don't want to walk the entire tree in that - // common case that occurs during parsing; instead we'll just return a value - // that says "add this form element to the end of the array". - if (e->traverseNextNode(this)) { - unsigned i = 0; - for (Node* node = this; node; node = node->traverseNextNode(this)) { - if (node == e) - return i; - if (node->isHTMLElement() - && static_cast<HTMLElement*>(node)->isGenericFormElement() - && static_cast<HTMLFormControlElement*>(node)->form() == this) - ++i; - } - } - return formElements.size(); -} - -void HTMLFormElement::registerFormElement(HTMLFormControlElement* e) -{ - document()->checkedRadioButtons().removeButton(e); - m_checkedRadioButtons.addButton(e); - formElements.insert(formElementIndex(e), e); -} - -void HTMLFormElement::removeFormElement(HTMLFormControlElement* e) -{ - m_checkedRadioButtons.removeButton(e); - removeFromVector(formElements, e); -} - -bool HTMLFormElement::isURLAttribute(Attribute* attr) const -{ - return attr->name() == actionAttr; -} - -void HTMLFormElement::registerImgElement(HTMLImageElement* e) -{ - imgElements.append(e); -} - -void HTMLFormElement::removeImgElement(HTMLImageElement* e) -{ - removeFromVector(imgElements, e); -} - -PassRefPtr<HTMLCollection> HTMLFormElement::elements() -{ - return HTMLFormCollection::create(this); -} - -String HTMLFormElement::name() const -{ - return getAttribute(nameAttr); -} - -void HTMLFormElement::setName(const String &value) -{ - setAttribute(nameAttr, value); -} - -String HTMLFormElement::acceptCharset() const -{ - return getAttribute(accept_charsetAttr); -} - -void HTMLFormElement::setAcceptCharset(const String &value) -{ - setAttribute(accept_charsetAttr, value); -} - -String HTMLFormElement::action() const -{ - return getAttribute(actionAttr); -} - -void HTMLFormElement::setAction(const String &value) -{ - setAttribute(actionAttr, value); -} - -void HTMLFormElement::setEnctype(const String &value) -{ - setAttribute(enctypeAttr, value); -} - -String HTMLFormElement::method() const -{ - return getAttribute(methodAttr); -} - -void HTMLFormElement::setMethod(const String &value) -{ - setAttribute(methodAttr, value); -} - -String HTMLFormElement::target() const -{ - return getAttribute(targetAttr); -} - -void HTMLFormElement::setTarget(const String &value) -{ - setAttribute(targetAttr, value); -} - -PassRefPtr<HTMLFormControlElement> HTMLFormElement::elementForAlias(const AtomicString& alias) -{ - if (alias.isEmpty() || !m_elementAliases) - return 0; - return m_elementAliases->get(alias.impl()); -} - -void HTMLFormElement::addElementAlias(HTMLFormControlElement* element, const AtomicString& alias) -{ - if (alias.isEmpty()) - return; - if (!m_elementAliases) - m_elementAliases = new AliasMap; - m_elementAliases->set(alias.impl(), element); -} - -void HTMLFormElement::getNamedElements(const AtomicString& name, Vector<RefPtr<Node> >& namedItems) -{ - elements()->namedItems(name, namedItems); - - // see if we have seen something with this name before - RefPtr<HTMLFormControlElement> aliasElem; - if (aliasElem = elementForAlias(name)) { - bool found = false; - for (unsigned n = 0; n < namedItems.size(); n++) { - if (namedItems[n] == aliasElem.get()) { - found = true; - break; - } - } - if (!found) - // we have seen it before but it is gone now. still, we need to return it. - namedItems.append(aliasElem.get()); - } - // name has been accessed, remember it - if (namedItems.size() && aliasElem != namedItems.first()) - addElementAlias(static_cast<HTMLFormControlElement*>(namedItems.first().get()), name); -} - -void HTMLFormElement::documentDidBecomeActive() -{ - ASSERT(!m_autocomplete); - - for (unsigned i = 0; i < formElements.size(); ++i) - formElements[i]->reset(); -} - -void HTMLFormElement::willMoveToNewOwnerDocument() -{ - if (!m_autocomplete) - document()->unregisterForDocumentActivationCallbacks(this); -} - -void HTMLFormElement::didMoveToNewOwnerDocument() -{ - if(m_autocomplete) - document()->registerForDocumentActivationCallbacks(this); -} - -void HTMLFormElement::CheckedRadioButtons::addButton(HTMLFormControlElement* element) -{ - // We only want to add radio buttons. - if (!element->isRadioButton()) - return; - - // Without a name, there is no group. - if (element->name().isEmpty()) - return; - - HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(element); - - // We only track checked buttons. - if (!inputElement->checked()) - return; - - if (!m_nameToCheckedRadioButtonMap) - m_nameToCheckedRadioButtonMap.set(new NameToInputMap); - - pair<NameToInputMap::iterator, bool> result = m_nameToCheckedRadioButtonMap->add(element->name().impl(), inputElement); - if (result.second) - return; - - HTMLInputElement* oldCheckedButton = result.first->second; - if (oldCheckedButton == inputElement) - return; - - result.first->second = inputElement; - oldCheckedButton->setChecked(false); -} - -HTMLInputElement* HTMLFormElement::CheckedRadioButtons::checkedButtonForGroup(const AtomicString& name) const -{ - if (!m_nameToCheckedRadioButtonMap) - return 0; - - return m_nameToCheckedRadioButtonMap->get(name.impl()); -} - -void HTMLFormElement::CheckedRadioButtons::removeButton(HTMLFormControlElement* element) -{ - if (element->name().isEmpty() || !m_nameToCheckedRadioButtonMap) - return; - - NameToInputMap::iterator it = m_nameToCheckedRadioButtonMap->find(element->name().impl()); - if (it == m_nameToCheckedRadioButtonMap->end() || it->second != element) - return; - - ASSERT(element->isRadioButton()); - ASSERT(element->isChecked()); - - m_nameToCheckedRadioButtonMap->remove(it); - if (m_nameToCheckedRadioButtonMap->isEmpty()) - m_nameToCheckedRadioButtonMap.clear(); -} - -} // namespace |