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