Home | History | Annotate | Download | only in forms
      1 /*
      2  * Copyright (C) 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
      3  * Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved.
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #include "config.h"
     22 #include "core/html/forms/FormController.h"
     23 
     24 #include "core/html/HTMLFormControlElementWithState.h"
     25 #include "core/html/HTMLFormElement.h"
     26 #include "core/html/HTMLInputElement.h"
     27 #include "platform/FileChooser.h"
     28 #include "wtf/Deque.h"
     29 #include "wtf/HashTableDeletedValueType.h"
     30 #include "wtf/text/StringBuilder.h"
     31 
     32 namespace blink {
     33 
     34 using namespace HTMLNames;
     35 
     36 static inline HTMLFormElement* ownerFormForState(const HTMLFormControlElementWithState& control)
     37 {
     38     // Assume controls with form attribute have no owners because we restore
     39     // state during parsing and form owners of such controls might be
     40     // indeterminate.
     41     return control.fastHasAttribute(formAttr) ? 0 : control.form();
     42 }
     43 
     44 // ----------------------------------------------------------------------------
     45 
     46 // Serilized form of FormControlState:
     47 //  (',' means strings around it are separated in stateVector.)
     48 //
     49 // SerializedControlState ::= SkipState | RestoreState
     50 // SkipState ::= '0'
     51 // RestoreState ::= UnsignedNumber, ControlValue+
     52 // UnsignedNumber ::= [0-9]+
     53 // ControlValue ::= arbitrary string
     54 //
     55 // RestoreState has a sequence of ControlValues. The length of the
     56 // sequence is represented by UnsignedNumber.
     57 
     58 void FormControlState::serializeTo(Vector<String>& stateVector) const
     59 {
     60     ASSERT(!isFailure());
     61     stateVector.append(String::number(m_values.size()));
     62     for (size_t i = 0; i < m_values.size(); ++i)
     63         stateVector.append(m_values[i].isNull() ? emptyString() : m_values[i]);
     64 }
     65 
     66 FormControlState FormControlState::deserialize(const Vector<String>& stateVector, size_t& index)
     67 {
     68     if (index >= stateVector.size())
     69         return FormControlState(TypeFailure);
     70     size_t valueSize = stateVector[index++].toUInt();
     71     if (!valueSize)
     72         return FormControlState();
     73     if (index + valueSize > stateVector.size())
     74         return FormControlState(TypeFailure);
     75     FormControlState state;
     76     state.m_values.reserveCapacity(valueSize);
     77     for (size_t i = 0; i < valueSize; ++i)
     78         state.append(stateVector[index++]);
     79     return state;
     80 }
     81 
     82 // ----------------------------------------------------------------------------
     83 
     84 class FormElementKey {
     85 public:
     86     FormElementKey(StringImpl* = 0, StringImpl* = 0);
     87     ~FormElementKey();
     88     FormElementKey(const FormElementKey&);
     89     FormElementKey& operator=(const FormElementKey&);
     90 
     91     StringImpl* name() const { return m_name; }
     92     StringImpl* type() const { return m_type; }
     93 
     94     // Hash table deleted values, which are only constructed and never copied or destroyed.
     95     FormElementKey(WTF::HashTableDeletedValueType) : m_name(hashTableDeletedValue()) { }
     96     bool isHashTableDeletedValue() const { return m_name == hashTableDeletedValue(); }
     97 
     98 private:
     99     void ref() const;
    100     void deref() const;
    101 
    102     static StringImpl* hashTableDeletedValue() { return reinterpret_cast<StringImpl*>(-1); }
    103 
    104     StringImpl* m_name;
    105     StringImpl* m_type;
    106 };
    107 
    108 FormElementKey::FormElementKey(StringImpl* name, StringImpl* type)
    109     : m_name(name)
    110     , m_type(type)
    111 {
    112     ref();
    113 }
    114 
    115 FormElementKey::~FormElementKey()
    116 {
    117     deref();
    118 }
    119 
    120 FormElementKey::FormElementKey(const FormElementKey& other)
    121     : m_name(other.name())
    122     , m_type(other.type())
    123 {
    124     ref();
    125 }
    126 
    127 FormElementKey& FormElementKey::operator=(const FormElementKey& other)
    128 {
    129     other.ref();
    130     deref();
    131     m_name = other.name();
    132     m_type = other.type();
    133     return *this;
    134 }
    135 
    136 void FormElementKey::ref() const
    137 {
    138     if (name())
    139         name()->ref();
    140     if (type())
    141         type()->ref();
    142 }
    143 
    144 void FormElementKey::deref() const
    145 {
    146     if (name())
    147         name()->deref();
    148     if (type())
    149         type()->deref();
    150 }
    151 
    152 inline bool operator==(const FormElementKey& a, const FormElementKey& b)
    153 {
    154     return a.name() == b.name() && a.type() == b.type();
    155 }
    156 
    157 struct FormElementKeyHash {
    158     static unsigned hash(const FormElementKey&);
    159     static bool equal(const FormElementKey& a, const FormElementKey& b) { return a == b; }
    160     static const bool safeToCompareToEmptyOrDeleted = true;
    161 };
    162 
    163 unsigned FormElementKeyHash::hash(const FormElementKey& key)
    164 {
    165     return StringHasher::hashMemory<sizeof(FormElementKey)>(&key);
    166 }
    167 
    168 struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
    169     static void constructDeletedValue(FormElementKey& slot, bool) { new (NotNull, &slot) FormElementKey(WTF::HashTableDeletedValue); }
    170     static bool isDeletedValue(const FormElementKey& value) { return value.isHashTableDeletedValue(); }
    171 };
    172 
    173 // ----------------------------------------------------------------------------
    174 
    175 class SavedFormState {
    176     WTF_MAKE_NONCOPYABLE(SavedFormState);
    177     WTF_MAKE_FAST_ALLOCATED;
    178 
    179 public:
    180     static PassOwnPtr<SavedFormState> create();
    181     static PassOwnPtr<SavedFormState> deserialize(const Vector<String>&, size_t& index);
    182     void serializeTo(Vector<String>&) const;
    183     bool isEmpty() const { return m_stateForNewFormElements.isEmpty(); }
    184     void appendControlState(const AtomicString& name, const AtomicString& type, const FormControlState&);
    185     FormControlState takeControlState(const AtomicString& name, const AtomicString& type);
    186 
    187     Vector<String> getReferencedFilePaths() const;
    188 
    189 private:
    190     SavedFormState() : m_controlStateCount(0) { }
    191 
    192     typedef HashMap<FormElementKey, Deque<FormControlState>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
    193     FormElementStateMap m_stateForNewFormElements;
    194     size_t m_controlStateCount;
    195 };
    196 
    197 PassOwnPtr<SavedFormState> SavedFormState::create()
    198 {
    199     return adoptPtr(new SavedFormState);
    200 }
    201 
    202 static bool isNotFormControlTypeCharacter(UChar ch)
    203 {
    204     return ch != '-' && (ch > 'z' || ch < 'a');
    205 }
    206 
    207 PassOwnPtr<SavedFormState> SavedFormState::deserialize(const Vector<String>& stateVector, size_t& index)
    208 {
    209     if (index >= stateVector.size())
    210         return nullptr;
    211     // FIXME: We need String::toSizeT().
    212     size_t itemCount = stateVector[index++].toUInt();
    213     if (!itemCount)
    214         return nullptr;
    215     OwnPtr<SavedFormState> savedFormState = adoptPtr(new SavedFormState);
    216     while (itemCount--) {
    217         if (index + 1 >= stateVector.size())
    218             return nullptr;
    219         String name = stateVector[index++];
    220         String type = stateVector[index++];
    221         FormControlState state = FormControlState::deserialize(stateVector, index);
    222         if (type.isEmpty() || type.find(isNotFormControlTypeCharacter) != kNotFound || state.isFailure())
    223             return nullptr;
    224         savedFormState->appendControlState(AtomicString(name), AtomicString(type), state);
    225     }
    226     return savedFormState.release();
    227 }
    228 
    229 void SavedFormState::serializeTo(Vector<String>& stateVector) const
    230 {
    231     stateVector.append(String::number(m_controlStateCount));
    232     for (FormElementStateMap::const_iterator it = m_stateForNewFormElements.begin(); it != m_stateForNewFormElements.end(); ++it) {
    233         const FormElementKey& key = it->key;
    234         const Deque<FormControlState>& queue = it->value;
    235         for (Deque<FormControlState>::const_iterator queIterator = queue.begin(); queIterator != queue.end(); ++queIterator) {
    236             stateVector.append(key.name());
    237             stateVector.append(key.type());
    238             queIterator->serializeTo(stateVector);
    239         }
    240     }
    241 }
    242 
    243 void SavedFormState::appendControlState(const AtomicString& name, const AtomicString& type, const FormControlState& state)
    244 {
    245     FormElementKey key(name.impl(), type.impl());
    246     FormElementStateMap::iterator it = m_stateForNewFormElements.find(key);
    247     if (it != m_stateForNewFormElements.end()) {
    248         it->value.append(state);
    249     } else {
    250         Deque<FormControlState> stateList;
    251         stateList.append(state);
    252         m_stateForNewFormElements.set(key, stateList);
    253     }
    254     m_controlStateCount++;
    255 }
    256 
    257 FormControlState SavedFormState::takeControlState(const AtomicString& name, const AtomicString& type)
    258 {
    259     if (m_stateForNewFormElements.isEmpty())
    260         return FormControlState();
    261     FormElementStateMap::iterator it = m_stateForNewFormElements.find(FormElementKey(name.impl(), type.impl()));
    262     if (it == m_stateForNewFormElements.end())
    263         return FormControlState();
    264     ASSERT(it->value.size());
    265     FormControlState state = it->value.takeFirst();
    266     m_controlStateCount--;
    267     if (!it->value.size())
    268         m_stateForNewFormElements.remove(it);
    269     return state;
    270 }
    271 
    272 Vector<String> SavedFormState::getReferencedFilePaths() const
    273 {
    274     Vector<String> toReturn;
    275     for (FormElementStateMap::const_iterator it = m_stateForNewFormElements.begin(); it != m_stateForNewFormElements.end(); ++it) {
    276         const FormElementKey& key = it->key;
    277         if (!equal(key.type(), "file", 4))
    278             continue;
    279         const Deque<FormControlState>& queue = it->value;
    280         for (Deque<FormControlState>::const_iterator queIterator = queue.begin(); queIterator != queue.end(); ++queIterator) {
    281             const Vector<FileChooserFileInfo>& selectedFiles = HTMLInputElement::filesFromFileInputFormControlState(*queIterator);
    282             for (size_t i = 0; i < selectedFiles.size(); ++i)
    283                 toReturn.append(selectedFiles[i].path);
    284         }
    285     }
    286     return toReturn;
    287 }
    288 
    289 // ----------------------------------------------------------------------------
    290 
    291 class FormKeyGenerator FINAL : public NoBaseWillBeGarbageCollectedFinalized<FormKeyGenerator> {
    292     WTF_MAKE_NONCOPYABLE(FormKeyGenerator);
    293     WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
    294 
    295 public:
    296     static PassOwnPtrWillBeRawPtr<FormKeyGenerator> create() { return adoptPtrWillBeNoop(new FormKeyGenerator); }
    297     void trace(Visitor* visitor)
    298     {
    299 #if ENABLE(OILPAN)
    300         visitor->trace(m_formToKeyMap);
    301 #endif
    302     }
    303     const AtomicString& formKey(const HTMLFormControlElementWithState&);
    304     void willDeleteForm(HTMLFormElement*);
    305 
    306 private:
    307     FormKeyGenerator() { }
    308 
    309     typedef WillBeHeapHashMap<RawPtrWillBeMember<HTMLFormElement>, AtomicString> FormToKeyMap;
    310     typedef HashMap<String, unsigned> FormSignatureToNextIndexMap;
    311     FormToKeyMap m_formToKeyMap;
    312     FormSignatureToNextIndexMap m_formSignatureToNextIndexMap;
    313 };
    314 
    315 static inline void recordFormStructure(const HTMLFormElement& form, StringBuilder& builder)
    316 {
    317     // 2 is enough to distinguish forms in webkit.org/b/91209#c0
    318     const size_t namedControlsToBeRecorded = 2;
    319     const FormAssociatedElement::List& controls = form.associatedElements();
    320     builder.appendLiteral(" [");
    321     for (size_t i = 0, namedControls = 0; i < controls.size() && namedControls < namedControlsToBeRecorded; ++i) {
    322         if (!controls[i]->isFormControlElementWithState())
    323             continue;
    324         HTMLFormControlElementWithState* control = toHTMLFormControlElementWithState(controls[i]);
    325         if (!ownerFormForState(*control))
    326             continue;
    327         AtomicString name = control->name();
    328         if (name.isEmpty())
    329             continue;
    330         namedControls++;
    331         builder.append(name);
    332         builder.append(' ');
    333     }
    334     builder.append(']');
    335 }
    336 
    337 static inline String formSignature(const HTMLFormElement& form)
    338 {
    339     KURL actionURL = form.getURLAttribute(actionAttr);
    340     // Remove the query part because it might contain volatile parameters such
    341     // as a session key.
    342     if (!actionURL.isEmpty())
    343         actionURL.setQuery(String());
    344 
    345     StringBuilder builder;
    346     if (!actionURL.isEmpty())
    347         builder.append(actionURL.string());
    348 
    349     recordFormStructure(form, builder);
    350     return builder.toString();
    351 }
    352 
    353 const AtomicString& FormKeyGenerator::formKey(const HTMLFormControlElementWithState& control)
    354 {
    355     HTMLFormElement* form = ownerFormForState(control);
    356     if (!form) {
    357         DEFINE_STATIC_LOCAL(const AtomicString, formKeyForNoOwner, ("No owner", AtomicString::ConstructFromLiteral));
    358         return formKeyForNoOwner;
    359     }
    360     FormToKeyMap::const_iterator it = m_formToKeyMap.find(form);
    361     if (it != m_formToKeyMap.end())
    362         return it->value;
    363 
    364     String signature = formSignature(*form);
    365     ASSERT(!signature.isNull());
    366     FormSignatureToNextIndexMap::AddResult result = m_formSignatureToNextIndexMap.add(signature, 0);
    367     unsigned nextIndex = result.storedValue->value++;
    368 
    369     StringBuilder formKeyBuilder;
    370     formKeyBuilder.append(signature);
    371     formKeyBuilder.appendLiteral(" #");
    372     formKeyBuilder.appendNumber(nextIndex);
    373     FormToKeyMap::AddResult addFormKeyresult = m_formToKeyMap.add(form, formKeyBuilder.toAtomicString());
    374     return addFormKeyresult.storedValue->value;
    375 }
    376 
    377 void FormKeyGenerator::willDeleteForm(HTMLFormElement* form)
    378 {
    379     ASSERT(form);
    380     m_formToKeyMap.remove(form);
    381 }
    382 
    383 // ----------------------------------------------------------------------------
    384 
    385 PassRefPtrWillBeRawPtr<DocumentState> DocumentState::create()
    386 {
    387     return adoptRefWillBeNoop(new DocumentState);
    388 }
    389 
    390 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(DocumentState)
    391 
    392 void DocumentState::trace(Visitor* visitor)
    393 {
    394 #if ENABLE(OILPAN)
    395     visitor->trace(m_formControls);
    396 #endif
    397 }
    398 
    399 void DocumentState::addControl(HTMLFormControlElementWithState* control)
    400 {
    401     ASSERT(!m_formControls.contains(control));
    402     m_formControls.add(control);
    403 }
    404 
    405 void DocumentState::removeControl(HTMLFormControlElementWithState* control)
    406 {
    407     RELEASE_ASSERT(m_formControls.contains(control));
    408     m_formControls.remove(control);
    409 }
    410 
    411 static String formStateSignature()
    412 {
    413     // In the legacy version of serialized state, the first item was a name
    414     // attribute value of a form control. The following string literal should
    415     // contain some characters which are rarely used for name attribute values.
    416     DEFINE_STATIC_LOCAL(String, signature, ("\n\r?% Blink serialized form state version 9 \n\r=&"));
    417     return signature;
    418 }
    419 
    420 Vector<String> DocumentState::toStateVector()
    421 {
    422     OwnPtrWillBeRawPtr<FormKeyGenerator> keyGenerator = FormKeyGenerator::create();
    423     OwnPtr<SavedFormStateMap> stateMap = adoptPtr(new SavedFormStateMap);
    424     for (FormElementListHashSet::const_iterator it = m_formControls.begin(); it != m_formControls.end(); ++it) {
    425         HTMLFormControlElementWithState* control = it->get();
    426         ASSERT(control->inDocument());
    427         if (!control->shouldSaveAndRestoreFormControlState())
    428             continue;
    429         SavedFormStateMap::AddResult result = stateMap->add(keyGenerator->formKey(*control), nullptr);
    430         if (result.isNewEntry)
    431             result.storedValue->value = SavedFormState::create();
    432         result.storedValue->value->appendControlState(control->name(), control->type(), control->saveFormControlState());
    433     }
    434 
    435     Vector<String> stateVector;
    436     stateVector.reserveInitialCapacity(m_formControls.size() * 4);
    437     stateVector.append(formStateSignature());
    438     for (SavedFormStateMap::const_iterator it = stateMap->begin(); it != stateMap->end(); ++it) {
    439         stateVector.append(it->key);
    440         it->value->serializeTo(stateVector);
    441     }
    442     bool hasOnlySignature = stateVector.size() == 1;
    443     if (hasOnlySignature)
    444         stateVector.clear();
    445     return stateVector;
    446 }
    447 
    448 // ----------------------------------------------------------------------------
    449 
    450 FormController::FormController()
    451     : m_documentState(DocumentState::create())
    452 {
    453 }
    454 
    455 FormController::~FormController()
    456 {
    457 }
    458 
    459 void FormController::trace(Visitor* visitor)
    460 {
    461     visitor->trace(m_radioButtonGroupScope);
    462     visitor->trace(m_documentState);
    463     visitor->trace(m_formKeyGenerator);
    464 }
    465 
    466 DocumentState* FormController::formElementsState() const
    467 {
    468     return m_documentState.get();
    469 }
    470 
    471 void FormController::setStateForNewFormElements(const Vector<String>& stateVector)
    472 {
    473     formStatesFromStateVector(stateVector, m_savedFormStateMap);
    474 }
    475 
    476 FormControlState FormController::takeStateForFormElement(const HTMLFormControlElementWithState& control)
    477 {
    478     if (m_savedFormStateMap.isEmpty())
    479         return FormControlState();
    480     if (!m_formKeyGenerator)
    481         m_formKeyGenerator = FormKeyGenerator::create();
    482     SavedFormStateMap::iterator it = m_savedFormStateMap.find(m_formKeyGenerator->formKey(control));
    483     if (it == m_savedFormStateMap.end())
    484         return FormControlState();
    485     FormControlState state = it->value->takeControlState(control.name(), control.type());
    486     if (it->value->isEmpty())
    487         m_savedFormStateMap.remove(it);
    488     return state;
    489 }
    490 
    491 void FormController::formStatesFromStateVector(const Vector<String>& stateVector, SavedFormStateMap& map)
    492 {
    493     map.clear();
    494 
    495     size_t i = 0;
    496     if (stateVector.size() < 1 || stateVector[i++] != formStateSignature())
    497         return;
    498 
    499     while (i + 1 < stateVector.size()) {
    500         AtomicString formKey = AtomicString(stateVector[i++]);
    501         OwnPtr<SavedFormState> state = SavedFormState::deserialize(stateVector, i);
    502         if (!state) {
    503             i = 0;
    504             break;
    505         }
    506         map.add(formKey, state.release());
    507     }
    508     if (i != stateVector.size())
    509         map.clear();
    510 }
    511 
    512 void FormController::willDeleteForm(HTMLFormElement* form)
    513 {
    514     if (m_formKeyGenerator)
    515         m_formKeyGenerator->willDeleteForm(form);
    516 }
    517 
    518 void FormController::restoreControlStateFor(HTMLFormControlElementWithState& control)
    519 {
    520     // We don't save state of a control with shouldSaveAndRestoreFormControlState()
    521     // == false. But we need to skip restoring process too because a control in
    522     // another form might have the same pair of name and type and saved its state.
    523     if (!control.shouldSaveAndRestoreFormControlState())
    524         return;
    525     if (ownerFormForState(control))
    526         return;
    527     FormControlState state = takeStateForFormElement(control);
    528     if (state.valueSize() > 0)
    529         control.restoreFormControlState(state);
    530 }
    531 
    532 void FormController::restoreControlStateIn(HTMLFormElement& form)
    533 {
    534     const FormAssociatedElement::List& elements = form.associatedElements();
    535     for (size_t i = 0; i < elements.size(); ++i) {
    536         if (!elements[i]->isFormControlElementWithState())
    537             continue;
    538         HTMLFormControlElementWithState* control = toHTMLFormControlElementWithState(elements[i]);
    539         if (!control->shouldSaveAndRestoreFormControlState())
    540             continue;
    541         if (ownerFormForState(*control) != &form)
    542             continue;
    543         FormControlState state = takeStateForFormElement(*control);
    544         if (state.valueSize() > 0)
    545             control->restoreFormControlState(state);
    546     }
    547 }
    548 
    549 Vector<String> FormController::getReferencedFilePaths(const Vector<String>& stateVector)
    550 {
    551     Vector<String> toReturn;
    552     SavedFormStateMap map;
    553     formStatesFromStateVector(stateVector, map);
    554     for (SavedFormStateMap::const_iterator it = map.begin(); it != map.end(); ++it)
    555         toReturn.appendVector(it->value->getReferencedFilePaths());
    556     return toReturn;
    557 }
    558 
    559 void FormController::registerStatefulFormControl(HTMLFormControlElementWithState& control)
    560 {
    561     m_documentState->addControl(&control);
    562 }
    563 
    564 void FormController::unregisterStatefulFormControl(HTMLFormControlElementWithState& control)
    565 {
    566     m_documentState->removeControl(&control);
    567 }
    568 
    569 } // namespace blink
    570