Ignore ajax on specified pages.

BUG=247522

Review URL: https://chromiumcodereview.appspot.com/16611003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207923 0039d316-1c4b-4281-b951-d872f2087c98
parent ddf75903
......@@ -272,6 +272,10 @@ void AutocheckoutManager::OnFormsSeen() {
autocheckout_offered_ = false;
}
bool AutocheckoutManager::ShouldIgnoreAjax() {
return in_autocheckout_flow_ && page_meta_data_->ignore_ajax;
}
void AutocheckoutManager::MaybeShowAutocheckoutBubble(
const GURL& frame_url,
const content::SSLStatus& ssl_status,
......
......@@ -61,6 +61,10 @@ class AutocheckoutManager {
// Called when a page containing forms is loaded.
void OnFormsSeen();
// Whether ajax on the current page should be ignored during
// an Autocheckout flow.
bool ShouldIgnoreAjax();
// Causes the Autocheckout bubble to be displayed if the user hasn't seen it
// yet for the current page. |frame_url| is the page where Autocheckout is
// being initiated. |ssl_status| is the SSL status of the page. |bounding_box|
......
......@@ -8,7 +8,8 @@ namespace autofill {
AutocheckoutPageMetaData::AutocheckoutPageMetaData()
: current_page_number(-1),
total_pages(-1) {}
total_pages(-1),
ignore_ajax(false) {}
AutocheckoutPageMetaData::~AutocheckoutPageMetaData() {}
......
......@@ -38,6 +38,10 @@ struct AutocheckoutPageMetaData {
// belong to any autofill flow, it is set to -1.
int total_pages;
// Whether ajaxy form changes that occur on this page during an Autocheckout
// flow should be ignored.
bool ignore_ajax;
// A list of elements to click before filling form fields. Elements have to be
// clicked in order.
std::vector<WebElementDescriptor> click_elements_before_form_fill;
......
......@@ -332,9 +332,14 @@ void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms,
autofill::FormsSeenState state) {
bool is_post_document_load = state == autofill::DYNAMIC_FORMS_SEEN;
bool has_more_forms = state == autofill::PARTIAL_FORMS_SEEN;
// If new forms were added via AJAX or DHML, treat as new page.
if (is_post_document_load)
// If new forms were added dynamically, and the autocheckout manager
// doesn't tell us to ignore ajax on this page, treat as a new page.
if (is_post_document_load) {
if (autocheckout_manager_.ShouldIgnoreAjax())
return;
Reset();
}
RenderViewHost* host = driver_->GetWebContents()->GetRenderViewHost();
if (!host)
......
......@@ -628,6 +628,21 @@ class TestAutofillManager : public AutofillManager {
autocheckout_manager()->OnLoadedPageMetaData(start_of_flow.Pass());
}
// Set autocheckout manager's page meta data to first page on Autocheckout
// flow.
void MarkAsFirstPageInAutocheckoutFlowIgnoringAjax() {
scoped_ptr<AutocheckoutPageMetaData> start_of_flow(
new AutocheckoutPageMetaData());
start_of_flow->current_page_number = 0;
start_of_flow->total_pages = 3;
start_of_flow->ignore_ajax = true;
WebElementDescriptor* proceed_element =
&start_of_flow->proceed_element_descriptor;
proceed_element->descriptor = "#foo";
proceed_element->retrieval_method = WebElementDescriptor::ID;
autocheckout_manager()->OnLoadedPageMetaData(start_of_flow.Pass());
}
private:
// Weak reference.
TestPersonalDataManager* personal_data_;
......@@ -3183,18 +3198,43 @@ TEST_F(AutofillManagerTest, DisabledAutofillDispatchesError) {
namespace {
class MockAutofillManagerDelegate
: public autofill::TestAutofillManagerDelegate {
class MockAutofillManagerDelegate : public TestAutofillManagerDelegate {
public:
MockAutofillManagerDelegate() {}
MockAutofillManagerDelegate()
: autocheckout_bubble_shown_(false) {}
virtual ~MockAutofillManagerDelegate() {}
MOCK_METHOD3(ShowAutocheckoutBubble,
void(const gfx::RectF& bounds,
bool is_google_user,
const base::Callback<void(bool)>& callback));
virtual void ShowAutocheckoutBubble(
const gfx::RectF& bounds,
bool is_google_user,
const base::Callback<void(bool)>& callback) OVERRIDE {
autocheckout_bubble_shown_ = true;
callback.Run(true);
}
virtual void ShowRequestAutocompleteDialog(
const FormData& form,
const GURL& source_url,
DialogType dialog_type,
const base::Callback<void(const FormStructure*,
const std::string&)>& callback) OVERRIDE {
callback.Run(user_supplied_data_.get(), "google_transaction_id");
}
void SetUserSuppliedData(scoped_ptr<FormStructure> user_supplied_data) {
user_supplied_data_.reset(user_supplied_data.release());
}
bool autocheckout_bubble_shown() const {
return autocheckout_bubble_shown_;
}
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillManagerDelegate);
bool autocheckout_bubble_shown_;
scoped_ptr<FormStructure> user_supplied_data_;
DISALLOW_COPY_AND_ASSIGN(MockAutofillManagerDelegate);
};
class MockAutofillExternalDelegate : public AutofillExternalDelegate {
......@@ -3224,8 +3264,6 @@ TEST_F(AutofillManagerTest, TestBubbleShown) {
autofill_manager_->set_autofill_enabled(true);
autofill_manager_->MarkAsFirstPageInAutocheckoutFlow();
EXPECT_CALL(delegate, ShowAutocheckoutBubble(_, _, _));
FormData form;
CreateTestAddressFormData(&form);
......@@ -3243,6 +3281,8 @@ TEST_F(AutofillManagerTest, TestBubbleShown) {
autofill_manager_->AddSeenForm(form_structure);
autofill_manager_->OnMaybeShowAutocheckoutBubble(form, gfx::RectF());
EXPECT_TRUE(delegate.autocheckout_bubble_shown());
}
// Test that Autocheckout bubble is not offered when server doesn't have data
......@@ -3271,6 +3311,8 @@ TEST_F(AutofillManagerTest, TestAutocheckoutBubbleNotShown) {
autofill_manager_->AddSeenForm(form_structure);
autofill_manager_->OnMaybeShowAutocheckoutBubble(form, gfx::RectF());
EXPECT_FALSE(delegate.autocheckout_bubble_shown());
}
// Test our external delegate is called at the right time.
......@@ -3290,4 +3332,53 @@ TEST_F(AutofillManagerTest, TestExternalDelegate) {
autofill_manager_->SetExternalDelegate(NULL);
}
// Test that in the case of Autocheckout, forms seen are in order supplied.
TEST_F(AutofillManagerTest, DynamicFormsSeenAndIgnored) {
MockAutofillManagerDelegate delegate;
autofill_manager_.reset(new TestAutofillManager(
autofill_driver_.get(), &delegate, &personal_data_));
FormData shipping_options;
CreateTestShippingOptionsFormData(&shipping_options);
FormData user_supplied;
CreateTestFormWithAutocompleteAttribute(&user_supplied);
FormData address;
CreateTestAddressFormData(&address);
autofill_manager_->set_autocheckout_url_prefix("test-prefix");
// Push address only
std::vector<FormData> forms;
forms.push_back(address);
// Build and add form structure with server data.
scoped_ptr<TestFormStructure> form_structure(new TestFormStructure(address));
std::vector<AutofillFieldType> heuristic_types, server_types;
for (size_t i = 0; i < address.fields.size(); ++i) {
heuristic_types.push_back(UNKNOWN_TYPE);
server_types.push_back(form_structure->field(i)->type());
}
form_structure->SetFieldTypes(heuristic_types, server_types);
autofill_manager_->AddSeenForm(form_structure.release());
// Make sure normal form is handled correctly.
autofill_manager_->MarkAsFirstPageInAutocheckoutFlowIgnoringAjax();
std::vector<FormStructure*> form_structures;
form_structures = autofill_manager_->GetFormStructures();
ASSERT_EQ(1U, form_structures.size());
EXPECT_EQ("/form.html", form_structures[0]->source_url().path());
scoped_ptr<FormStructure> filled_form(new TestFormStructure(address));
delegate.SetUserSuppliedData(filled_form.Pass());
autofill_manager_->OnMaybeShowAutocheckoutBubble(address, gfx::RectF());
// Push other forms
forms.push_back(shipping_options);
forms.push_back(user_supplied);
// FormStructure should contain the same forms as before.
DynamicFormsSeen(forms);
form_structures = autofill_manager_->GetFormStructures();
ASSERT_EQ(1U, form_structures.size());
EXPECT_EQ("/form.html", form_structures[0]->source_url().path());
}
} // namespace autofill
......@@ -119,6 +119,8 @@ void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context,
page_meta_data_->current_page_number = GetIntValue(context, *attrs);
else if (attribute_name.compare("total_pages") == 0)
page_meta_data_->total_pages = GetIntValue(context, *attrs);
else if (attribute_name.compare("ignore_ajax") == 0)
page_meta_data_->ignore_ajax = strcmp(*attrs, "true") == 0;
++attrs;
}
} else if (element.compare("page_advance_button") == 0) {
......
......@@ -179,6 +179,7 @@ TEST_F(AutofillQueryXmlParserTest, ParseAutofillFlow) {
EXPECT_EQ(1U, field_infos_.size());
EXPECT_EQ(1, page_meta_data_.current_page_number);
EXPECT_EQ(10, page_meta_data_.total_pages);
EXPECT_FALSE(page_meta_data_.ignore_ajax);
EXPECT_EQ("foo", page_meta_data_.proceed_element_descriptor.descriptor);
EXPECT_EQ(autofill::WebElementDescriptor::ID,
page_meta_data_.proceed_element_descriptor.retrieval_method);
......@@ -277,6 +278,52 @@ TEST_F(AutofillQueryXmlParserTest, ParseAutofillFlow) {
click_elment = page_meta_data_.click_elements_after_form_fill[0];
EXPECT_EQ("btn1", click_elment.descriptor);
EXPECT_EQ(autofill::WebElementDescriptor::ID, click_elment.retrieval_method);
// Clear |field_infos_| for the next test.
field_infos_.clear();
// Test setting of ignore_ajax attribute.
xml = "<autofillqueryresponse>"
"<field autofilltype=\"55\"/>"
"<autofill_flow page_no=\"1\" total_pages=\"10\" ignore_ajax=\"true\">"
"<page_advance_button css_selector=\"[name=&quot;foo&quot;]\""
" id=\"foo\"/>"
"</autofill_flow>"
"</autofillqueryresponse>";
ParseQueryXML(xml, true);
EXPECT_EQ(1U, field_infos_.size());
EXPECT_EQ(1, page_meta_data_.current_page_number);
EXPECT_EQ(10, page_meta_data_.total_pages);
EXPECT_TRUE(page_meta_data_.ignore_ajax);
EXPECT_EQ("[name=\"foo\"]",
page_meta_data_.proceed_element_descriptor.descriptor);
EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR,
page_meta_data_.proceed_element_descriptor.retrieval_method);
// Clear |field_infos_| for the next test.
field_infos_.clear();
// Test redundant setting to false of ignore_ajax attribute.
xml = "<autofillqueryresponse>"
"<field autofilltype=\"55\"/>"
"<autofill_flow page_no=\"1\" total_pages=\"10\" ignore_ajax=\"false\">"
"<page_advance_button css_selector=\"[name=&quot;foo&quot;]\""
" id=\"foo\"/>"
"</autofill_flow>"
"</autofillqueryresponse>";
ParseQueryXML(xml, true);
EXPECT_EQ(1U, field_infos_.size());
EXPECT_EQ(1, page_meta_data_.current_page_number);
EXPECT_EQ(10, page_meta_data_.total_pages);
EXPECT_FALSE(page_meta_data_.ignore_ajax);
EXPECT_EQ("[name=\"foo\"]",
page_meta_data_.proceed_element_descriptor.descriptor);
EXPECT_EQ(autofill::WebElementDescriptor::CSS_SELECTOR,
page_meta_data_.proceed_element_descriptor.retrieval_method);
}
// Test badly formed XML queries.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment