summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-27 17:37:01 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-27 17:37:01 +0000
commit290838a9c769dad3f5d43babdd019cacc198aa81 (patch)
tree04b7ba90ab46b5aa6922b31be41ab41e36f3549c
parentd91ba37d590d050cfbe7a95053b314ebd446c71d (diff)
downloadchromium_src-290838a9c769dad3f5d43babdd019cacc198aa81.zip
chromium_src-290838a9c769dad3f5d43babdd019cacc198aa81.tar.gz
chromium_src-290838a9c769dad3f5d43babdd019cacc198aa81.tar.bz2
AutoFill: Notify the renderer when the page has finished translating. Extract
the forms once translation has occurred. This change also includes another variaton of the Name field, with tests. In addition, this change fixes parsing labels whose text element is not the first child of the label element. BUG=41694 TEST=FormManagerTest.LabelsWithSpans,NameFieldTest.FirstLast Review URL: http://codereview.chromium.org/1801002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45719 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/autofill/name_field.cc20
-rw-r--r--chrome/browser/autofill/name_field_unittest.cc52
-rw-r--r--chrome/renderer/form_manager.cc11
-rw-r--r--chrome/renderer/form_manager_unittest.cc43
-rw-r--r--chrome/renderer/render_view.cc10
-rw-r--r--chrome/renderer/render_view.h4
-rw-r--r--chrome/renderer/translate_helper.cc3
7 files changed, 128 insertions, 15 deletions
diff --git a/chrome/browser/autofill/name_field.cc b/chrome/browser/autofill/name_field.cc
index e04b4c3..7d87030 100644
--- a/chrome/browser/autofill/name_field.cc
+++ b/chrome/browser/autofill/name_field.cc
@@ -74,9 +74,9 @@ FirstLastNameField* FirstLastNameField::Parse2(
// so we match "initials" here (and just fill in a first name there,
// American-style).
// The ".*first$" matches fields ending in "first" (example in sample8.html).
- if (!ParseText(&q,
- ASCIIToUTF16("first name|firstname|initials|fname|.*first$"),
- &v.first_name_))
+ string16 match =
+ ASCIIToUTF16("first name|first_name|firstname|initials|fname|.*first$");
+ if (!ParseText(&q, match, &v.first_name_))
return NULL;
// We check for a middle initial before checking for a middle name
@@ -84,19 +84,17 @@ FirstLastNameField* FirstLastNameField::Parse2(
// as both (the label text is "MI" and the element name is
// "txtmiddlename"); such a field probably actually represents a
// middle initial.
- if (ParseText(&q,
- ASCIIToUTF16("^mi$|middle initial|middleinitial|m.i."),
- &v.middle_name_)) {
+ match = ASCIIToUTF16("^mi$|middle initial|middleinitial|m.i.");
+ if (ParseText(&q, match, &v.middle_name_)) {
v.middle_initial_ = true;
} else {
- ParseText(
- &q, ASCIIToUTF16("middle name|mname|middlename"), &v.middle_name_);
+ match = ASCIIToUTF16("middle name|mname|middlename");
+ ParseText(&q, match, &v.middle_name_);
}
// The ".*last$" matches fields ending in "last" (example in sample8.html).
- if (!ParseText(&q,
- ASCIIToUTF16("last name|lastname|lname|surname|.*last$"),
- &v.last_name_))
+ match = ASCIIToUTF16("last name|last_name|lastname|lname|surname|.*last$");
+ if (!ParseText(&q, match, &v.last_name_))
return NULL;
*iter = q;
diff --git a/chrome/browser/autofill/name_field_unittest.cc b/chrome/browser/autofill/name_field_unittest.cc
index d338c83..f8a3d1c 100644
--- a/chrome/browser/autofill/name_field_unittest.cc
+++ b/chrome/browser/autofill/name_field_unittest.cc
@@ -95,4 +95,56 @@ TEST_F(NameFieldTest, FirstMiddleLast2) {
EXPECT_EQ(NAME_LAST, field_type_map_[ASCIIToUTF16("name3")]);
}
+TEST_F(NameFieldTest, FirstLast) {
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(string16(),
+ ASCIIToUTF16("first_name"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("name1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(string16(),
+ ASCIIToUTF16("last_name"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("name2")));
+ list_.push_back(NULL);
+ iter_ = list_.begin();
+ field_.reset(NameField::Parse(&iter_, false));
+ ASSERT_NE(static_cast<NameField*>(NULL), field_.get());
+ ASSERT_TRUE(field_->GetFieldInfo(&field_type_map_));
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("name1")) != field_type_map_.end());
+ EXPECT_EQ(NAME_FIRST, field_type_map_[ASCIIToUTF16("name1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("name2")) != field_type_map_.end());
+ EXPECT_EQ(NAME_LAST, field_type_map_[ASCIIToUTF16("name2")]);
+}
+
+TEST_F(NameFieldTest, FirstLast2) {
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Name"),
+ ASCIIToUTF16("first_name"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("name1")));
+ list_.push_back(
+ new AutoFillField(webkit_glue::FormField(ASCIIToUTF16("Name"),
+ ASCIIToUTF16("last_name"),
+ string16(),
+ ASCIIToUTF16("text")),
+ ASCIIToUTF16("name2")));
+ list_.push_back(NULL);
+ iter_ = list_.begin();
+ field_.reset(NameField::Parse(&iter_, false));
+ ASSERT_NE(static_cast<NameField*>(NULL), field_.get());
+ ASSERT_TRUE(field_->GetFieldInfo(&field_type_map_));
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("name1")) != field_type_map_.end());
+ EXPECT_EQ(NAME_FIRST, field_type_map_[ASCIIToUTF16("name1")]);
+ ASSERT_TRUE(
+ field_type_map_.find(ASCIIToUTF16("name2")) != field_type_map_.end());
+ EXPECT_EQ(NAME_LAST, field_type_map_[ASCIIToUTF16("name2")]);
+}
+
} // namespace
diff --git a/chrome/renderer/form_manager.cc b/chrome/renderer/form_manager.cc
index 19ae004..59704d1 100644
--- a/chrome/renderer/form_manager.cc
+++ b/chrome/renderer/form_manager.cc
@@ -45,13 +45,16 @@ namespace {
// it's not necessary.
const size_t kRequiredAutoFillFields = 3;
-// Returns the node value of the first child of |element| if the first child
-// is text. This is faster alternative to |innerText()| for performance
-// critical operations when the child structure of element is known.
+// Returns the node value of the first offspring of |element| that is a text
+// node. This is a faster alternative to |innerText()| for performance
+// critical operations when the child structure of |element| is known.
string16 GetChildText(const WebElement& element) {
string16 element_text;
WebNode child = element.firstChild();
- if (!child.isNull() && child.isTextNode()) {
+ // Find the text node.
+ while (!child.isNull() && !child.isTextNode())
+ child = child.firstChild();
+ if (!child.isNull()) {
element_text = child.nodeValue();
TrimWhitespace(element_text, TRIM_ALL, &element_text);
}
diff --git a/chrome/renderer/form_manager_unittest.cc b/chrome/renderer/form_manager_unittest.cc
index 15f548f..2f37362 100644
--- a/chrome/renderer/form_manager_unittest.cc
+++ b/chrome/renderer/form_manager_unittest.cc
@@ -466,6 +466,49 @@ TEST_F(FormManagerTest, Labels) {
fields[2]);
}
+TEST_F(FormManagerTest, LabelsWithSpans) {
+ LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">"
+ " <LABEL for=\"firstname\"><span>First name: </span></LABEL>"
+ " <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+ " <LABEL for=\"lastname\"><span>Last name: </span></LABEL>"
+ " <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+ " <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+ "</FORM>");
+
+ WebFrame* web_frame = GetMainFrame();
+ ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+ FormManager form_manager;
+ form_manager.ExtractForms(web_frame);
+
+ std::vector<FormData> forms;
+ form_manager.GetForms(FormManager::REQUIRE_NONE, &forms);
+ ASSERT_EQ(1U, forms.size());
+
+ const FormData& form = forms[0];
+ EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+ EXPECT_EQ(GURL(web_frame->url()), form.origin);
+ EXPECT_EQ(GURL("http://cnn.com"), form.action);
+
+ const std::vector<FormField>& fields = form.fields;
+ ASSERT_EQ(3U, fields.size());
+ EXPECT_EQ(FormField(ASCIIToUTF16("First name:"),
+ ASCIIToUTF16("firstname"),
+ ASCIIToUTF16("John"),
+ ASCIIToUTF16("text")),
+ fields[0]);
+ EXPECT_EQ(FormField(ASCIIToUTF16("Last name:"),
+ ASCIIToUTF16("lastname"),
+ ASCIIToUTF16("Smith"),
+ ASCIIToUTF16("text")),
+ fields[1]);
+ EXPECT_EQ(FormField(string16(),
+ ASCIIToUTF16("reply-send"),
+ ASCIIToUTF16("Send"),
+ ASCIIToUTF16("submit")),
+ fields[2]);
+}
+
// This test is different from FormManagerTest.Labels in that the label elements
// for= attribute is set to the name of the form control element it is a label
// for instead of the id of the form control element. This is invalid because
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index f744ce1..07eb0e6 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -4945,6 +4945,16 @@ bool RenderView::ScheduleFileChooser(
return true;
}
+void RenderView::OnPageTranslated() {
+ WebFrame* frame = webview()->mainFrame();
+ if (!frame)
+ return;
+
+ // The page is translated, so try to extract the form data again.
+ form_manager_.ExtractForms(frame);
+ SendForms(frame);
+}
+
WebKit::WebGeolocationService* RenderView::geolocationService() {
if (!geolocation_dispatcher_.get())
geolocation_dispatcher_.reset(new GeolocationDispatcher(this));
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index d8bb27a..5d55af9 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -515,6 +515,10 @@ class RenderView : public RenderWidget,
bool ScheduleFileChooser(const ViewHostMsg_RunFileChooser_Params& params,
WebKit::WebFileChooserCompletion* completion);
+ // Called when the translate helper has finished translating the page. We use
+ // this signal to re-scan the page for forms.
+ void OnPageTranslated();
+
// The language code used when the page language is unknown.
static const char* const kUnknownLanguageCode;
diff --git a/chrome/renderer/translate_helper.cc b/chrome/renderer/translate_helper.cc
index d6d8569..1fea5b7 100644
--- a/chrome/renderer/translate_helper.cc
+++ b/chrome/renderer/translate_helper.cc
@@ -196,6 +196,9 @@ void TranslateHelper::CheckTranslateStatus() {
translation_pending_ = false;
+ // Notify the renderer we are done.
+ render_view_->OnPageTranslated();
+
// Notify the browser we are done.
render_view_->Send(new ViewHostMsg_PageTranslated(
render_view_->routing_id(), render_view_->page_id(),