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, 2010 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 "HTMLKeygenElement.h"
27
28#include "Attribute.h"
29#include "Document.h"
30#include "FormDataList.h"
31#include "HTMLNames.h"
32#include "HTMLSelectElement.h"
33#include "HTMLOptionElement.h"
34#include "SSLKeyGenerator.h"
35#include "ShadowRoot.h"
36#include "Text.h"
37#include <wtf/StdLibExtras.h>
38
39using namespace WebCore;
40
41namespace WebCore {
42
43using namespace HTMLNames;
44
45class KeygenSelectElement : public HTMLSelectElement {
46public:
47    static PassRefPtr<KeygenSelectElement> create(Document* document)
48    {
49        return adoptRef(new KeygenSelectElement(document));
50    }
51
52    virtual const AtomicString& shadowPseudoId() const
53    {
54        DEFINE_STATIC_LOCAL(AtomicString, pseudoId, ("-webkit-keygen-select"));
55        return pseudoId;
56    }
57
58protected:
59    KeygenSelectElement(Document* document)
60        : HTMLSelectElement(selectTag, document, 0)
61    {
62    }
63};
64
65inline HTMLKeygenElement::HTMLKeygenElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
66    : HTMLFormControlElementWithState(tagName, document, form)
67{
68    ASSERT(hasTagName(keygenTag));
69
70    // Create a select element with one option element for each key size.
71    Vector<String> keys;
72    getSupportedKeySizes(keys);
73
74    RefPtr<HTMLSelectElement> select = KeygenSelectElement::create(document);
75    ExceptionCode ec = 0;
76    for (size_t i = 0; i < keys.size(); ++i) {
77        RefPtr<HTMLOptionElement> option = HTMLOptionElement::create(document, this->form());
78        select->appendChild(option, ec);
79        option->appendChild(Text::create(document, keys[i]), ec);
80    }
81
82    ensureShadowRoot()->appendChild(select, ec);
83}
84
85PassRefPtr<HTMLKeygenElement> HTMLKeygenElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
86{
87    return adoptRef(new HTMLKeygenElement(tagName, document, form));
88}
89
90void HTMLKeygenElement::parseMappedAttribute(Attribute* attr)
91{
92    // Reflect disabled attribute on the shadow select element
93    if (attr->name() == disabledAttr)
94        shadowSelect()->setAttribute(attr->name(), attr->value());
95
96    if (attr->name() == challengeAttr)
97        m_challenge = attr->value();
98    else if (attr->name() == keytypeAttr)
99        m_keyType = attr->value();
100    else
101        HTMLFormControlElement::parseMappedAttribute(attr);
102}
103
104bool HTMLKeygenElement::appendFormData(FormDataList& encoded_values, bool)
105{
106    // Only RSA is supported at this time.
107    if (!m_keyType.isNull() && !equalIgnoringCase(m_keyType, "rsa"))
108        return false;
109    String value = signedPublicKeyAndChallengeString(shadowSelect()->selectedIndex(), m_challenge, document()->baseURL());
110    if (value.isNull())
111        return false;
112    encoded_values.appendData(name(), value.utf8());
113    return true;
114}
115
116const AtomicString& HTMLKeygenElement::formControlType() const
117{
118    DEFINE_STATIC_LOCAL(const AtomicString, keygen, ("keygen"));
119    return keygen;
120}
121
122void HTMLKeygenElement::reset()
123{
124    static_cast<HTMLFormControlElement*>(shadowSelect())->reset();
125}
126
127HTMLSelectElement* HTMLKeygenElement::shadowSelect() const
128{
129    Node* shadow = shadowRoot();
130    ASSERT(shadow);
131    return shadow ? static_cast<HTMLSelectElement*>(shadow->firstChild()) : 0;
132}
133
134} // namespace
135