// https://w3c.github.io/webappsec-credential-management/#passwordcredential-form-constructor PasswordCredential* PasswordCredential::create(HTMLFormElement* form, ExceptionState& exceptionState) { // Extract data from the form, then use the extracted |formData| object's // value to populate |data|. FormData* formData = FormData::create(form); PasswordCredentialData data; AtomicString idName; AtomicString passwordName; for (FormAssociatedElement* element : form->associatedElements()) { // If |element| isn't a "submittable element" with string data, then it // won't have a matching value in |formData|, and we can safely skip it. FileOrUSVString result; formData->get(element->name(), result); if (!result.isUSVString()) continue; AtomicString autocomplete = toHTMLElement(element)->fastGetAttribute(HTMLNames::autocompleteAttr); if (equalIgnoringCase(autocomplete, "current-password") || equalIgnoringCase(autocomplete, "new-password")) { data.setPassword(result.getAsUSVString()); passwordName = element->name(); } else if (equalIgnoringCase(autocomplete, "photo")) { data.setIconURL(result.getAsUSVString()); } else if (equalIgnoringCase(autocomplete, "name") || equalIgnoringCase(autocomplete, "nickname")) { data.setName(result.getAsUSVString()); } else if (equalIgnoringCase(autocomplete, "username")) { data.setId(result.getAsUSVString()); idName = element->name(); } } // Create a PasswordCredential using the data gathered above. PasswordCredential* credential = PasswordCredential::create(data, exceptionState); if (exceptionState.hadException()) return nullptr; ASSERT(credential); // After creating the Credential, populate its 'additionalData', 'idName', and 'passwordName' attributes. // If the form's 'enctype' is anything other than multipart, generate a URLSearchParams using the // data in |formData|. credential->setIdName(idName); credential->setPasswordName(passwordName); FormDataOrURLSearchParams additionalData; if (form->enctype() == "multipart/form-data") { additionalData.setFormData(formData); } else { URLSearchParams* params = URLSearchParams::create(URLSearchParamsInit()); for (const FormData::Entry* entry : formData->entries()) { if (entry->isString()) params->append(entry->name().data(), entry->value().data()); } additionalData.setURLSearchParams(params); } credential->setAdditionalData(additionalData); return credential; }
TEST(FormDataTest, get) { FormData* fd = FormData::create(UTF8Encoding()); fd->append("name1", "value1"); FileOrUSVString result; fd->get("name1", result); EXPECT_TRUE(result.isUSVString()); EXPECT_EQ("value1", result.getAsUSVString()); const FormData::Entry& entry = *fd->entries()[0]; EXPECT_STREQ("name1", entry.name().data()); EXPECT_STREQ("value1", entry.value().data()); }
PassRefPtr<EncodedFormData> PasswordCredential::encodeFormData( String& contentType) const { if (m_additionalData.isURLSearchParams()) { // If |additionalData| is a 'URLSearchParams' object, build a urlencoded // response. URLSearchParams* params = URLSearchParams::create(URLSearchParamsInit()); URLSearchParams* additionalData = m_additionalData.getAsURLSearchParams(); for (const auto& param : additionalData->params()) { const String& name = param.first; if (name != idName() && name != passwordName()) params->append(name, param.second); } params->append(idName(), id()); params->append(passwordName(), password()); contentType = AtomicString("application/x-www-form-urlencoded;charset=UTF-8"); return params->toEncodedFormData(); } // Otherwise, we'll build a multipart response. FormData* formData = FormData::create(nullptr); if (m_additionalData.isFormData()) { FormData* additionalData = m_additionalData.getAsFormData(); for (const FormData::Entry* entry : additionalData->entries()) { const String& name = formData->decode(entry->name()); if (name == idName() || name == passwordName()) continue; if (entry->blob()) formData->append(name, entry->blob(), entry->filename()); else formData->append(name, formData->decode(entry->value())); } } formData->append(idName(), id()); formData->append(passwordName(), password()); RefPtr<EncodedFormData> encodedData = formData->encodeMultiPartFormData(); contentType = AtomicString("multipart/form-data; boundary=") + encodedData->boundary().data(); return encodedData.release(); }