diff options
author | yaar@chromium.org <yaar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-05 17:51:25 +0000 |
---|---|---|
committer | yaar@chromium.org <yaar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-05 17:51:25 +0000 |
commit | 4e6ff9412901d75792f58ad8eb95b37ef8edf4f6 (patch) | |
tree | 992086b591ab153b7770542bfccf1c58ce530cbd /webkit | |
parent | baf652e912759ba285ffa63dbd8a6a68bc7aa4a2 (diff) | |
download | chromium_src-4e6ff9412901d75792f58ad8eb95b37ef8edf4f6.zip chromium_src-4e6ff9412901d75792f58ad8eb95b37ef8edf4f6.tar.gz chromium_src-4e6ff9412901d75792f58ad8eb95b37ef8edf4f6.tar.bz2 |
Move PasswordFormDomManager::CreatePassword into the WebKit API
http://code.google.com/p/chromium/issues/detail?id=24619
Review URL: http://codereview.chromium.org/345056
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31104 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/api/WebKit.gyp | 5 | ||||
-rw-r--r-- | webkit/api/public/WebPasswordFormData.h | 110 | ||||
-rw-r--r-- | webkit/api/public/WebSearchableFormData.h | 7 | ||||
-rw-r--r-- | webkit/api/src/WebPasswordFormData.cpp | 180 | ||||
-rw-r--r-- | webkit/api/src/WebPasswordFormUtils.cpp | 110 | ||||
-rw-r--r-- | webkit/api/src/WebPasswordFormUtils.h | 57 | ||||
-rw-r--r-- | webkit/glue/password_form.h | 18 | ||||
-rw-r--r-- | webkit/glue/password_form_dom_manager.cc | 249 |
8 files changed, 491 insertions, 245 deletions
diff --git a/webkit/api/WebKit.gyp b/webkit/api/WebKit.gyp index 1efd323..dbce149 100644 --- a/webkit/api/WebKit.gyp +++ b/webkit/api/WebKit.gyp @@ -119,6 +119,7 @@ 'public/WebNotification.h', 'public/WebNotificationPresenter.h', 'public/WebNotificationPermissionCallback.h', + 'public/WebPasswordFormData.h', 'public/WebPlugin.h', 'public/WebPluginContainer.h', 'public/WebPluginListBuilder.h', @@ -185,7 +186,6 @@ 'src/EditorClientImpl.h', 'src/FrameLoaderClientImpl.cpp', 'src/FrameLoaderClientImpl.h', - 'src/EmptyWebFrameClientImpl.h', 'src/gtk/WebFontInfo.cpp', 'src/gtk/WebFontInfo.h', 'src/gtk/WebInputEventFactory.cpp', @@ -246,6 +246,9 @@ 'src/WebMediaPlayerClientImpl.h', 'src/WebNode.cpp', 'src/WebNotification.cpp', + 'src/WebPasswordFormData.cpp', + 'src/WebPasswordFormUtils.cpp', + 'src/WebPasswordFormUtils.h', 'src/WebPluginContainerImpl.h', 'src/WebPluginContainerImpl.cpp', 'src/WebPluginListBuilderImpl.cpp', diff --git a/webkit/api/public/WebPasswordFormData.h b/webkit/api/public/WebPasswordFormData.h new file mode 100644 index 0000000..551a48a --- /dev/null +++ b/webkit/api/public/WebPasswordFormData.h @@ -0,0 +1,110 @@ +/* + * 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. + */ + +#ifndef WebPasswordFormData_h +#define WebPasswordFormData_h + +#include "WebForm.h" +#include "WebString.h" +#include "WebURL.h" + +namespace WebKit { + +struct WebPasswordFormData { + // If the provided form is suitable for password completion, isValid() will + // return true; + WebPasswordFormData(const WebForm&); + + // If creation failed, return false. + bool isValid() const { return action.isValid(); } + + // The action target of the form. This is the primary data used by the + // PasswordManager for form autofill; that is, the action of the saved + // credentials must match the action of the form on the page to be autofilled. + // If this is empty / not available, it will result in a "restricted" + // IE-like autofill policy, where we wait for the user to type in his + // username before autofilling the password. In these cases, after successful + // login the action URL will automatically be assigned by the + // PasswordManager. + // + // When parsing an HTML form, this must always be set. + WebURL action; + + // The "Realm" for the sign-on (scheme, host, port for SCHEME_HTML, and + // contains the HTTP realm for dialog-based forms). + // The signon_realm is effectively the primary key used for retrieving + // data from the database, so it must not be empty. + WebString signonRealm; + + // The URL (minus query parameters) containing the form. This is the primary + // data used by the PasswordManager to decide (in longest matching prefix + // fashion) whether or not a given PasswordForm result from the database is a + // good fit for a particular form on a page, so it must not be empty. + WebURL origin; + + // The name of the submit button used. Optional; only used in scoring + // of PasswordForm results from the database to make matches as tight as + // possible. + // + // When parsing an HTML form, this must always be set. + WebString submitElement; + + // The name of the username input element. Optional (improves scoring). + // + // When parsing an HTML form, this must always be set. + WebString userNameElement; + + // The username. Optional. + // + // When parsing an HTML form, this is typically empty unless the site + // has implemented some form of autofill. + WebString userNameValue; + + // The name of the password input element, Optional (improves scoring). + // + // When parsing an HTML form, this must always be set. + WebString passwordElement; + + // The password. Required. + // + // When parsing an HTML form, this is typically empty. + WebString passwordValue; + + // If the form was a change password form, the name of the + // 'old password' input element. Optional. + WebString oldPasswordElement; + + // The old password. Optional. + WebString oldPasswordValue; +}; + +} // namespace WebKit + +#endif diff --git a/webkit/api/public/WebSearchableFormData.h b/webkit/api/public/WebSearchableFormData.h index dcebc0b..d8f3a23 100644 --- a/webkit/api/public/WebSearchableFormData.h +++ b/webkit/api/public/WebSearchableFormData.h @@ -41,11 +41,12 @@ class WebForm; // corresponds to a searchable form request. class WebSearchableFormData { public: - // If the provided form is suitable for automated searching, |m_url| and - // |m_encoding| are set appropriately. Otherwise |m_url| will be left - // invalid. + // If the provided form is suitable for automated searching, isValid() + // will return false. WebSearchableFormData(const WebForm&); + bool isValid() { return m_url.isValid(); } + // URL for the searchable form request. const WebURL& url() const { diff --git a/webkit/api/src/WebPasswordFormData.cpp b/webkit/api/src/WebPasswordFormData.cpp new file mode 100644 index 0000000..7a25be0 --- /dev/null +++ b/webkit/api/src/WebPasswordFormData.cpp @@ -0,0 +1,180 @@ +/* + * 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 "Document.h" +#include "DocumentLoader.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "HTMLFormElement.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "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, + 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; + + 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(); + } + if (oldPassword) { + result->oldPasswordElement = oldPassword->name(); + result->oldPasswordValue = oldPassword->value(); + } +} + +} // namespace + +WebPasswordFormData::WebPasswordFormData(const WebForm& webForm) +{ + RefPtr<HTMLFormElement> form = webForm.operator PassRefPtr<HTMLFormElement>(); + + Frame* frame = form->document()->frame(); + if (!frame) + return; + + PasswordFormFields fields; + findPasswordFormFields(form.get(), &fields); + + // Get the document URL + KURL fullOrigin(ParsedURLString, form->document()->documentURI()); + + // Calculate the canonical action URL + KURL fullAction = frame->loader()->completeURL(form->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, + oldPassword, password, this); +} + +} // namespace WebKit diff --git a/webkit/api/src/WebPasswordFormUtils.cpp b/webkit/api/src/WebPasswordFormUtils.cpp new file mode 100644 index 0000000..766dc63 --- /dev/null +++ b/webkit/api/src/WebPasswordFormUtils.cpp @@ -0,0 +1,110 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License Version +* 1.1 (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +* for the specific language governing rights and limitations under the +* License. +* +* The Original Code is Mozilla Password Manager. +* +* The Initial Developer of the Original Code is +* Brian Ryner. +* Portions created by the Initial Developer are Copyright (C) 2003 +* the Initial Developer. All Rights Reserved. +* +* Contributor(s): +* Brian Ryner <bryner@brianryner.com> +* +* Alternatively, the contents of this file may be used under the terms of +* either the GNU General Public License Version 2 or later (the "GPL"), or +* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +* in which case the provisions of the GPL or the LGPL are applicable instead +* of those above. If you wish to allow use of your version of this file only +* under the terms of either the GPL or the LGPL, and not to allow others to +* use your version of this file under the terms of the MPL, indicate your +* decision by deleting the provisions above and replace them with the notice +* and other provisions required by the GPL or the LGPL. If you do not delete +* the provisions above, a recipient may use your version of this file under +* the terms of any one of the MPL, the GPL or the LGPL. +* +* ***** END LICENSE BLOCK ***** */ + +// Helper to WebPasswordFormData to do the locating of username/password +// fields. +// This method based on Firefox2 code in +// toolkit/components/passwordmgr/base/nsPasswordManager.cpp + +#include "config.h" +#include "WebPasswordFormUtils.h" + +#include "HTMLFormElement.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "KURL.h" + +#include "DOMUtilitiesPrivate.h" + +using namespace WebCore; + +namespace WebKit { + +// Maximum number of password fields we will observe before throwing our +// hands in the air and giving up with a given form. +static const size_t maxPasswords = 3; + +void findPasswordFormFields(HTMLFormElement* form, PasswordFormFields* fields) +{ + ASSERT(form); + ASSERT(fields); + + int firstPasswordIndex = 0; + // First, find the password fields and activated submit button + const Vector<HTMLFormControlElement*>& formElements = form->formElements; + for (size_t i = 0; i < formElements.size(); i++) { + HTMLFormControlElement* formElement = formElements[i]; + if (formElement->isActivatedSubmit()) + fields->submit = formElement; + + if (!formElement->hasLocalName(HTMLNames::inputTag)) + continue; + + HTMLInputElement* inputElement = toHTMLInputElement(formElement); + if (!inputElement->isEnabledFormControl()) + continue; + + if ((fields->passwords.size() < maxPasswords) + && (inputElement->inputType() == HTMLInputElement::PASSWORD) + && (inputElement->autoComplete())) { + if (fields->passwords.isEmpty()) + firstPasswordIndex = i; + fields->passwords.append(inputElement); + } + } + + if (!fields->passwords.isEmpty()) { + // Then, search backwards for the username field + for (int i = firstPasswordIndex - 1; i >= 0; i--) { + HTMLFormControlElement* formElement = formElements[i]; + if (!formElement->hasLocalName(HTMLNames::inputTag)) + continue; + + HTMLInputElement* inputElement = toHTMLInputElement(formElement); + if (!inputElement->isEnabledFormControl()) + continue; + + if ((inputElement->inputType() == HTMLInputElement::TEXT) + && (inputElement->autoComplete())) { + fields->userName = inputElement; + break; + } + } + } +} + +} // namespace WebKit diff --git a/webkit/api/src/WebPasswordFormUtils.h b/webkit/api/src/WebPasswordFormUtils.h new file mode 100644 index 0000000..fd503b4 --- /dev/null +++ b/webkit/api/src/WebPasswordFormUtils.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#ifndef WebPasswordFormUtils_h +#define WebPasswordFormUtils_h + +#include <wtf/Vector.h> + +namespace WebCore { +class HTMLInputElement; +class HTMLFormControlElement; +class HTMLFormElement; +} + +namespace WebKit { + +// Helper structure to locate username, passwords and submit fields. +struct PasswordFormFields { + WebCore::HTMLInputElement* userName; + Vector<WebCore::HTMLInputElement*> passwords; + WebCore::HTMLFormControlElement* submit; + PasswordFormFields() : userName(0), submit(0) { } +}; + +void findPasswordFormFields(WebCore::HTMLFormElement* form, + PasswordFormFields* fields); + +} // namespace WebKit + +#endif diff --git a/webkit/glue/password_form.h b/webkit/glue/password_form.h index b07576d..f392029 100644 --- a/webkit/glue/password_form.h +++ b/webkit/glue/password_form.h @@ -10,6 +10,7 @@ #include "base/time.h" #include "googleurl/src/gurl.h" +#include "webkit/api/public/WebPasswordFormData.h" namespace webkit_glue { @@ -140,6 +141,23 @@ struct PasswordForm { preferred(false), blacklisted_by_user(false) { } + + PasswordForm(const WebKit::WebPasswordFormData& web_password_form) + : scheme(SCHEME_HTML), + signon_realm(web_password_form.signonRealm.utf8()), + origin(web_password_form.origin), + action(web_password_form.action), + submit_element(web_password_form.submitElement), + username_element(web_password_form.userNameElement), + username_value(web_password_form.userNameValue), + password_element(web_password_form.passwordElement), + password_value(web_password_form.passwordValue), + old_password_element(web_password_form.oldPasswordElement), + old_password_value(web_password_form.oldPasswordValue), + ssl_valid(false), + preferred(false), + blacklisted_by_user(false) { + } }; // Map username to PasswordForm* for convenience. See password_form_manager.h. diff --git a/webkit/glue/password_form_dom_manager.cc b/webkit/glue/password_form_dom_manager.cc index 8bd3231..a87e4d4 100644 --- a/webkit/glue/password_form_dom_manager.cc +++ b/webkit/glue/password_form_dom_manager.cc @@ -2,256 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "config.h" - -#include "Document.h" -#include "DocumentLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "HTMLFormElement.h" -#include "HTMLInputElement.h" -#include "HTMLNames.h" -#include "KURL.h" -#undef LOG #include "base/logging.h" +#include "webkit/api/public/WebPasswordFormData.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/password_form_dom_manager.h" using WebKit::WebForm; +using WebKit::WebPasswordFormData; namespace webkit_glue { -namespace { - -// Maximum number of password fields we will observe before throwing our -// hands in the air and giving up with a given form. -const size_t kMaxPasswords = 3; - -// Helper structure to locate username, passwords and submit fields. -struct PasswordFormFields { - WebCore::HTMLInputElement* username; - std::vector<WebCore::HTMLInputElement*> passwords; - WebCore::HTMLFormControlElement* submit; - PasswordFormFields() : username(NULL), submit(NULL) { - } -}; - -// Helper to CreatePasswordForm to do the locating of username/password -// fields. -// This method based on Firefox2 code in -// toolkit/components/passwordmgr/base/nsPasswordManager.cpp -// Its license block is - -/* ***** BEGIN LICENSE BLOCK ***** -* Version: MPL 1.1/GPL 2.0/LGPL 2.1 -* -* The contents of this file are subject to the Mozilla Public License Version -* 1.1 (the "License"); you may not use this file except in compliance with -* the License. You may obtain a copy of the License at -* http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS IS" basis, -* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -* for the specific language governing rights and limitations under the -* License. -* -* The Original Code is Mozilla Password Manager. -* -* The Initial Developer of the Original Code is -* Brian Ryner. -* Portions created by the Initial Developer are Copyright (C) 2003 -* the Initial Developer. All Rights Reserved. -* -* Contributor(s): -* Brian Ryner <bryner@brianryner.com> -* -* Alternatively, the contents of this file may be used under the terms of -* either the GNU General Public License Version 2 or later (the "GPL"), or -* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -* in which case the provisions of the GPL or the LGPL are applicable instead -* of those above. If you wish to allow use of your version of this file only -* under the terms of either the GPL or the LGPL, and not to allow others to -* use your version of this file under the terms of the MPL, indicate your -* decision by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL or the LGPL. If you do not delete -* the provisions above, a recipient may use your version of this file under -* the terms of any one of the MPL, the GPL or the LGPL. -* -* ***** END LICENSE BLOCK ***** */ -void FindPasswordFormFields( - WebCore::HTMLFormElement* form, - PasswordFormFields* fields) { - DCHECK(form && fields); - int first_password_index = 0; - // First, find the password fields and activated submit button - const WTF::Vector<WebCore::HTMLFormControlElement*>& form_elements = - form->formElements; - for (size_t i = 0; i < form_elements.size(); i++) { - WebCore::HTMLFormControlElement* form_element = form_elements[i]; - if (form_element->isActivatedSubmit()) - fields->submit = form_element; - - if (!form_element->hasLocalName(WebCore::HTMLNames::inputTag)) - continue; - - WebCore::HTMLInputElement* input_element = - static_cast<WebCore::HTMLInputElement*>(form_element); - if (!input_element->isEnabledFormControl()) - continue; - - if ((fields->passwords.size() < kMaxPasswords) && - (input_element->inputType() == WebCore::HTMLInputElement::PASSWORD) && - (input_element->autoComplete())) { - if (fields->passwords.empty()) - first_password_index = i; - fields->passwords.push_back(input_element); - } - } - - if (!fields->passwords.empty()) { - // Then, search backwards for the username field - for (int i = first_password_index - 1; i >= 0; i--) { - WebCore::HTMLFormControlElement* form_element = form_elements[i]; - if (!form_element->hasLocalName(WebCore::HTMLNames::inputTag)) - continue; - - WebCore::HTMLInputElement* input_element = - static_cast<WebCore::HTMLInputElement*>(form_element); - if (!input_element->isEnabledFormControl()) - continue; - - if ((input_element->inputType() == WebCore::HTMLInputElement::TEXT) && - (input_element->autoComplete())) { - fields->username = input_element; - break; - } - } - } -} - -// 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, - WebCore::HTMLInputElement** password, - WebCore::HTMLInputElement** old_password) { - DCHECK(fields && password && old_password); - 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). - *old_password = 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. - *old_password = fields->passwords[0]; - *password = fields->passwords[2]; - } else if (fields->passwords[1]->value() == - fields->passwords[2]->value()) { - *old_password = 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; -} - -// Helper to gather up the final form data and create a PasswordForm. -PasswordForm* AssemblePasswordFormResult( - const GURL& full_origin, - const GURL& full_action, - WebCore::HTMLFormControlElement* submit, - WebCore::HTMLInputElement* username, - WebCore::HTMLInputElement* old_password, - WebCore::HTMLInputElement* password) { - string16 empty; - PasswordForm* result = new PasswordForm(); - // Ignore the query and ref components - GURL::Replacements rep; - rep.ClearUsername(); - rep.ClearPassword(); - rep.ClearQuery(); - rep.ClearRef(); - // 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 = full_action.ReplaceComponents(rep); - result->origin = full_origin.ReplaceComponents(rep); - - // 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). - result->signon_realm = full_origin.GetOrigin().spec(); - // Note PasswordManager sets ssl_valid by asking the WebContents' SSLManager. - result->submit_element = - submit == NULL ? empty : StringToString16(submit->name()); - result->username_element = - username == NULL ? empty : StringToString16(username->name()); - result->username_value = - username == NULL ? empty : StringToString16(username->value()); - result->password_element = - password == NULL ? empty : StringToString16(password->name()); - result->password_value = - password == NULL ? empty : StringToString16(password->value()); - result->old_password_element = - old_password == NULL ? empty : StringToString16(old_password->name()); - result->old_password_value = - old_password == NULL ? empty : StringToString16(old_password->value()); - return result; -} - -} // namespace - -PasswordForm* PasswordFormDomManager::CreatePasswordForm( - const WebForm& webform) { - RefPtr<WebCore::HTMLFormElement> form = WebFormToHTMLFormElement(webform); - - WebCore::Frame* frame = form->document()->frame(); - if (!frame) - return NULL; - - PasswordFormFields fields; - FindPasswordFormFields(form.get(), &fields); - - // Get the document URL - WebCore::String origin_string = form->document()->documentURI(); - GURL full_origin(StringToStdString(origin_string)); - - // Calculate the canonical action URL - GURL full_action(KURLToGURL(frame->loader()->completeURL(form->action()))); - if (!full_action.is_valid()) - return NULL; - - // Determine the types of the password fields - WebCore::HTMLInputElement* password = NULL; - WebCore::HTMLInputElement* old_password = NULL; - if (!LocateSpecificPasswords(&fields, &password, &old_password)) - return NULL; - - return AssemblePasswordFormResult(full_origin, full_action, - fields.submit, fields.username, - old_password, password); +PasswordForm* PasswordFormDomManager::CreatePasswordForm(const WebForm& webform) +{ + WebPasswordFormData web_password_form(webform); + if (web_password_form.isValid()) + return new PasswordForm(web_password_form); + return NULL; } // static |