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