blob: c3aba9ae1ff85e59869caa238204a44a8e0ecb28 [file] [log] [blame]
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "WebPasswordFormData.h"
#include "HTMLNames.h"
#include "core/dom/Document.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoader.h"
#include "core/page/Frame.h"
#include "weborigin/KURL.h"
#include "DOMUtilitiesPrivate.h"
#include "WebPasswordFormUtils.h"
using namespace WebCore;
namespace WebKit {
namespace {
// Helper to determine which password is the main one, and which is
// an old password (e.g on a "make new password" form), if any.
bool locateSpecificPasswords(PasswordFormFields* fields,
HTMLInputElement** password,
HTMLInputElement** oldPassword)
{
ASSERT(fields);
ASSERT(password);
ASSERT(oldPassword);
switch (fields->passwords.size()) {
case 1:
// Single password, easy.
*password = fields->passwords[0];
break;
case 2:
if (fields->passwords[0]->value() == fields->passwords[1]->value())
// Treat two identical passwords as a single password.
*password = fields->passwords[0];
else {
// Assume first is old password, second is new (no choice but to guess).
*oldPassword = fields->passwords[0];
*password = fields->passwords[1];
}
break;
case 3:
if (fields->passwords[0]->value() == fields->passwords[1]->value()
&& fields->passwords[0]->value() == fields->passwords[2]->value()) {
// All three passwords the same? Just treat as one and hope.
*password = fields->passwords[0];
} else if (fields->passwords[0]->value() == fields->passwords[1]->value()) {
// Two the same and one different -> old password is duplicated one.
*oldPassword = fields->passwords[0];
*password = fields->passwords[2];
} else if (fields->passwords[1]->value() == fields->passwords[2]->value()) {
*oldPassword = fields->passwords[0];
*password = fields->passwords[1];
} else {
// Three different passwords, or first and last match with middle
// different. No idea which is which, so no luck.
return false;
}
break;
default:
return false;
}
return true;
}
// Helped method to clear url of unneeded parts.
KURL stripURL(const KURL& url)
{
KURL strippedURL = url;
strippedURL.setUser(String());
strippedURL.setPass(String());
strippedURL.setQuery(String());
strippedURL.setFragmentIdentifier(String());
return strippedURL;
}
// Helper to gather up the final form data and create a PasswordForm.
void assemblePasswordFormResult(const KURL& fullOrigin,
const KURL& fullAction,
HTMLFormControlElement* submit,
HTMLInputElement* userName,
const Vector<String>& alternateUserNames,
HTMLInputElement* oldPassword,
HTMLInputElement* password,
WebPasswordFormData* result)
{
// We want to keep the path but strip any authentication data, as well as
// query and ref portions of URL, for the form action and form origin.
result->action = stripURL(fullAction);
result->origin = stripURL(fullOrigin);
// Naming is confusing here because we have both the HTML form origin URL
// the page where the form was seen), and the "origin" components of the url
// (scheme, host, and port).
KURL signonRealmURL = stripURL(fullOrigin);
signonRealmURL.setPath("");
result->signonRealm = signonRealmURL;
result->possibleUserNames = alternateUserNames;
if (submit)
result->submitElement = submit->name();
if (userName) {
result->userNameElement = userName->name();
result->userNameValue = userName->value();
}
if (password) {
result->passwordElement = password->name();
result->passwordValue = password->value();
result->passwordShouldAutocomplete = password->shouldAutocomplete();
}
if (oldPassword) {
result->oldPasswordElement = oldPassword->name();
result->oldPasswordValue = oldPassword->value();
}
}
} // namespace
WebPasswordFormData::WebPasswordFormData(const WebFormElement& webForm)
{
RefPtr<HTMLFormElement> form = webForm.operator PassRefPtr<HTMLFormElement>();
PasswordFormFields fields;
findPasswordFormFields(form.get(), &fields);
// Get the document URL
KURL fullOrigin(ParsedURLString, form->document()->documentURI());
// Calculate the canonical action URL
String action = form->action();
if (action.isNull())
action = ""; // missing 'action' attribute implies current URL
KURL fullAction = form->document()->completeURL(action);
if (!fullAction.isValid())
return;
// Determine the types of the password fields
HTMLInputElement* password = 0;
HTMLInputElement* oldPassword = 0;
if (!locateSpecificPasswords(&fields, &password, &oldPassword))
return;
assemblePasswordFormResult(fullOrigin, fullAction,
fields.submit, fields.userName,
fields.alternateUserNames,
oldPassword, password, this);
}
} // namespace WebKit