Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(665)

Unified Diff: components/autofill/content/renderer/password_form_conversion_utils.cc

Issue 1014683006: [Password manager] Recognise squashed login+sign-up forms (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: LazyInstance + commented regexp Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/autofill/content/renderer/password_form_conversion_utils.cc
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.cc b/components/autofill/content/renderer/password_form_conversion_utils.cc
index dd97e9aaba7621fba147504501066f4e459358d6..be13e1b92b88072f2a0ff4bc9d8d435da006e40f 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -4,6 +4,8 @@
#include "components/autofill/content/renderer/password_form_conversion_utils.h"
+#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/core/common/password_form.h"
@@ -11,6 +13,7 @@
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFormControlElement.h"
#include "third_party/WebKit/public/web/WebInputElement.h"
+#include "third_party/icu/source/i18n/unicode/regex.h"
using blink::WebDocument;
using blink::WebFormControlElement;
@@ -22,6 +25,73 @@ using blink::WebVector;
namespace autofill {
namespace {
+// Layout classification of password forms
+// A layout sequence of a form is the sequence of it's non-password and password
+// input fields, represented by "N" and "P", respectively. A form like this
+// <form>
+// <input type='text' ...>
+// <input type='hidden' ...>
+// <input type='password' ...>
+// <input type='submit' ...>
+// </form>
+// has the layout sequence "NP" -- "N" for the first field, and "P" for the
+// third. The second and fourth fields are ignored, because they are not text
+// fields.
+//
+// The code below classifies the layout (see PasswordForm::Layout) of a form
+// based on its layout sequence. This is done by assigning layouts regular
+// expressions over the alphabet {N, P}. LAYOUT_OTHER is implicitly the type
+// corresponding to all layout sequences not matching any other layout.
+//
+// LAYOUT_LOGIN_AND_SIGNUP is classified by NPN+P.*. This corresponds to a form
+// which starts with a login section (NP) and continues with a sign-up section
+// (N+P.*). The aim is to distinguish such forms from change password-forms
+// (N*PPP?.*) and forms which use password fields to store private but
+// non-password data (could look like, e.g., PN+P.*).
+const char kLoginAndSignupRegex[] =
+ "NP" // Login section.
+ "N+P" // Sign-up section.
+ ".*"; // Anything beyond that.
Ilya Sherman 2015/03/24 00:28:02 Thanks, this is indeed much nicer to read :)
+
+struct LoginAndSignupLazyInstanceTraits
+ : public base::DefaultLazyInstanceTraits<icu::RegexMatcher> {
+ static icu::RegexMatcher* New(void* instance) {
+ const icu::UnicodeString icu_pattern(kLoginAndSignupRegex);
+
+ UErrorCode status = U_ZERO_ERROR;
+ // Use placement new to initialize the instance in the preallocated space.
+ // The "(instance)" is very important to force POD type initialization.
+ scoped_ptr<icu::RegexMatcher> matcher(new (instance) icu::RegexMatcher(
+ icu_pattern, UREGEX_CASE_INSENSITIVE, status));
+ DCHECK(U_SUCCESS(status));
+ return matcher.release();
+ }
+};
+
+base::LazyInstance<icu::RegexMatcher, LoginAndSignupLazyInstanceTraits>
+ login_and_signup_matcher = LAZY_INSTANCE_INITIALIZER;
+
+bool MatchesLoginAndSignupPattern(base::StringPiece layout_sequence) {
+ icu::RegexMatcher* matcher = login_and_signup_matcher.Pointer();
+ icu::UnicodeString icu_input(icu::UnicodeString::fromUTF8(
+ icu::StringPiece(layout_sequence.data(), layout_sequence.length())));
+ matcher->reset(icu_input);
+
+ UErrorCode status = U_ZERO_ERROR;
+ UBool match = matcher->find(0, status);
+ DCHECK(U_SUCCESS(status));
+ return match == TRUE;
+}
+
+// Given the sequence of non-password and password text input fields of a form,
+// represented as a string of Ns (non-password) and Ps (password), computes the
+// layout type of that form.
+PasswordForm::Layout SequenceToLayout(base::StringPiece layout_sequence) {
+ if (MatchesLoginAndSignupPattern(layout_sequence))
+ return PasswordForm::Layout::LAYOUT_LOGIN_AND_SIGNUP;
+ return PasswordForm::Layout::LAYOUT_OTHER;
+}
+
// Checks in a case-insensitive way if the autocomplete attribute for the given
// |element| is present and has the specified |value_in_lowercase|.
bool HasAutocompleteAttributeValue(const WebInputElement& element,
@@ -125,6 +195,8 @@ void GetPasswordForm(
WebVector<WebFormControlElement> control_elements;
form.getFormControlElements(control_elements);
+ std::string layout_sequence;
+ layout_sequence.reserve(control_elements.size());
for (size_t i = 0; i < control_elements.size(); ++i) {
WebFormControlElement control_element = control_elements[i];
if (control_element.isActivatedSubmit())
@@ -134,6 +206,13 @@ void GetPasswordForm(
if (!input_element || !input_element->isEnabled())
continue;
+ if (input_element->isTextField()) {
+ if (input_element->isPasswordField())
+ layout_sequence.push_back('P');
+ else
+ layout_sequence.push_back('N');
+ }
+
if (input_element->isPasswordField()) {
passwords.push_back(*input_element);
// If we have not yet considered any element to be the username so far,
@@ -194,6 +273,7 @@ void GetPasswordForm(
}
}
}
+ password_form->layout = SequenceToLayout(layout_sequence);
if (!username_element.isNull()) {
password_form->username_element = username_element.nameForAutofill();

Powered by Google App Engine
This is Rietveld 408576698