summaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authordgwallinga@chromium.org <dgwallinga@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-24 10:58:14 +0000
committerdgwallinga@chromium.org <dgwallinga@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-24 10:58:14 +0000
commit80ad3bbbf3ff9a4ffdaf259333b02bc96956ef0a (patch)
tree809da5c355ff2b6072ca9b39406ef2f8013b59a5 /components
parentae5325688d27b2e749f37e5f5ddee92adc20cd63 (diff)
downloadchromium_src-80ad3bbbf3ff9a4ffdaf259333b02bc96956ef0a.zip
chromium_src-80ad3bbbf3ff9a4ffdaf259333b02bc96956ef0a.tar.gz
chromium_src-80ad3bbbf3ff9a4ffdaf259333b02bc96956ef0a.tar.bz2
Display detailed steps for Autocheckout flows.
While proceeding through an Autocheckout flow, display a list of detailed steps which will be provided by the autofill server along with the field mappings for the first page of the flow. These steps will be marked as completed as progress is made. This fix necessarily also involved some minor fixes to CVV challenge handling. BUG=242372, 236047 TEST=unit_tests --gtest_filter=Autofill*:Autocheckout*, browser_tests --gtest_filter=AutofillDialogControllerTest* Review URL: https://chromiumcodereview.appspot.com/15525002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208194 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components')
-rw-r--r--components/autofill/content/browser/autocheckout_manager.cc59
-rw-r--r--components/autofill/content/browser/autocheckout_manager.h6
-rw-r--r--components/autofill/content/browser/autocheckout_manager_unittest.cc153
-rw-r--r--components/autofill/content/browser/autocheckout_page_meta_data.h7
-rw-r--r--components/autofill/content/browser/autocheckout_steps.h32
-rw-r--r--components/autofill/core/browser/autofill_manager_delegate.h10
-rw-r--r--components/autofill/core/browser/autofill_xml_parser.cc37
-rw-r--r--components/autofill/core/browser/autofill_xml_parser.h21
-rw-r--r--components/autofill/core/browser/autofill_xml_parser_unittest.cc13
-rw-r--r--components/autofill/core/browser/test_autofill_manager_delegate.cc7
-rw-r--r--components/autofill/core/browser/test_autofill_manager_delegate.h6
11 files changed, 253 insertions, 98 deletions
diff --git a/components/autofill/content/browser/autocheckout_manager.cc b/components/autofill/content/browser/autocheckout_manager.cc
index bdd7119..438b2a7 100644
--- a/components/autofill/content/browser/autocheckout_manager.cc
+++ b/components/autofill/content/browser/autocheckout_manager.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/content/browser/autocheckout_request_manager.h"
+#include "components/autofill/content/browser/autocheckout_steps.h"
#include "components/autofill/core/browser/autofill_country.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_manager.h"
@@ -204,6 +205,9 @@ void AutocheckoutManager::OnClickFailed(AutocheckoutStatus status) {
DCHECK_NE(MISSING_FIELDMAPPING, status);
SendAutocheckoutStatus(status);
+ SetStepProgressForPage(page_meta_data_->current_page_number,
+ AUTOCHECKOUT_STEP_FAILED);
+
autofill_manager_->delegate()->OnAutocheckoutError();
in_autocheckout_flow_ = false;
}
@@ -248,20 +252,29 @@ void AutocheckoutManager::OnLoadedPageMetaData(
status = CANNOT_PROCEED;
}
- // Encountered an error during the Autocheckout flow.
+ // Encountered an error during the Autocheckout flow, probably to
+ // do with a problem on the previous page.
if (!in_autocheckout_flow_) {
+ if (old_meta_data) {
+ SetStepProgressForPage(old_meta_data->current_page_number,
+ AUTOCHECKOUT_STEP_FAILED);
+ }
SendAutocheckoutStatus(status);
autofill_manager_->delegate()->OnAutocheckoutError();
return;
}
- // Add 1.0 since page numbers are 0-indexed.
- autofill_manager_->delegate()->UpdateProgressBar(
- (1.0 + page_meta_data_->current_page_number) /
- page_meta_data_->total_pages);
+ SetStepProgressForPage(old_meta_data->current_page_number,
+ AUTOCHECKOUT_STEP_COMPLETED);
+ SetStepProgressForPage(page_meta_data_->current_page_number,
+ AUTOCHECKOUT_STEP_STARTED);
+
FillForms();
- // If the current page is the last page in the flow, close the dialog.
+ // If the current page is the last page in the flow, set in-progress
+ // steps to 'completed', and send status.
if (page_meta_data_->IsEndOfAutofillableFlow()) {
+ SetStepProgressForPage(page_meta_data_->current_page_number,
+ AUTOCHECKOUT_STEP_COMPLETED);
SendAutocheckoutStatus(status);
autofill_manager_->delegate()->OnAutocheckoutSuccess();
in_autocheckout_flow_ = false;
@@ -352,14 +365,19 @@ void AutocheckoutManager::ReturnAutocheckoutData(
}
}
- // Add 1.0 since page numbers are 0-indexed.
- autofill_manager_->delegate()->UpdateProgressBar(
- (1.0 + page_meta_data_->current_page_number) /
- page_meta_data_->total_pages);
+ // Page types only available in first-page meta data, so save
+ // them for use later as we navigate.
+ page_types_ = page_meta_data_->page_types;
+ SetStepProgressForPage(page_meta_data_->current_page_number,
+ AUTOCHECKOUT_STEP_STARTED);
+
FillForms();
- // If the current page is the last page in the flow, close the dialog.
+ // If the current page is the last page in the flow, set in-progress
+ // steps to 'completed', and send status.
if (page_meta_data_->IsEndOfAutofillableFlow()) {
+ SetStepProgressForPage(page_meta_data_->current_page_number,
+ AUTOCHECKOUT_STEP_COMPLETED);
SendAutocheckoutStatus(SUCCESS);
autofill_manager_->delegate()->OnAutocheckoutSuccess();
in_autocheckout_flow_ = false;
@@ -387,6 +405,14 @@ void AutocheckoutManager::MaybeShowAutocheckoutDialog(
weak_ptr_factory_.GetWeakPtr());
autofill_manager_->ShowRequestAutocompleteDialog(
form, frame_url, DIALOG_TYPE_AUTOCHECKOUT, callback);
+
+ for (std::map<int, std::vector<AutocheckoutStepType> >::const_iterator
+ it = page_meta_data_->page_types.begin();
+ it != page_meta_data_->page_types.end(); ++it) {
+ for (size_t i = 0; i < it->second.size(); ++i) {
+ autofill_manager_->delegate()->AddAutocheckoutStep(it->second[i]);
+ }
+ }
}
void AutocheckoutManager::ShowAutocheckoutBubble(
@@ -488,4 +514,15 @@ void AutocheckoutManager::SendAutocheckoutStatus(AutocheckoutStatus status) {
google_transaction_id_ = kTransactionIdNotSet;
}
+void AutocheckoutManager::SetStepProgressForPage(
+ int page_number,
+ AutocheckoutStepStatus status) {
+ if (page_types_.count(page_number) == 1) {
+ for (size_t i = 0; i < page_types_[page_number].size(); ++i) {
+ autofill_manager_->delegate()->UpdateAutocheckoutStep(
+ page_types_[page_number][i], status);
+ }
+ }
+}
+
} // namespace autofill
diff --git a/components/autofill/content/browser/autocheckout_manager.h b/components/autofill/content/browser/autocheckout_manager.h
index 18a0c26..a5442b9 100644
--- a/components/autofill/content/browser/autocheckout_manager.h
+++ b/components/autofill/content/browser/autocheckout_manager.h
@@ -120,6 +120,9 @@ class AutocheckoutManager {
// field type specified by |field|.
void SetValue(const AutofillField& field, FormFieldData* field_to_fill);
+ // Sets the progress of all steps for the given page to the provided value.
+ void SetStepProgressForPage(int page_number, AutocheckoutStepStatus status);
+
AutofillManager* autofill_manager_; // WEAK; owns us
// Credit card verification code.
@@ -150,6 +153,9 @@ class AutocheckoutManager {
// Whether or not the user is in an Autocheckout flow.
bool in_autocheckout_flow_;
+ // AutocheckoutStepTypes for the various pages of the flow.
+ std::map<int, std::vector<AutocheckoutStepType> > page_types_;
+
std::string google_transaction_id_;
base::WeakPtrFactory<AutocheckoutManager> weak_ptr_factory_;
diff --git a/components/autofill/content/browser/autocheckout_manager_unittest.cc b/components/autofill/content/browser/autocheckout_manager_unittest.cc
index 9c21872..b4f9b1b 100644
--- a/components/autofill/content/browser/autocheckout_manager_unittest.cc
+++ b/components/autofill/content/browser/autocheckout_manager_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <map>
+
#include "base/strings/utf_string_conversions.h"
#include "base/tuple.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
@@ -145,6 +147,9 @@ scoped_ptr<AutocheckoutPageMetaData> CreateStartOfFlowMetaData() {
new AutocheckoutPageMetaData());
start_of_flow->current_page_number = 0;
start_of_flow->total_pages = 3;
+ start_of_flow->page_types[0].push_back(AUTOCHECKOUT_STEP_SHIPPING);
+ start_of_flow->page_types[1].push_back(AUTOCHECKOUT_STEP_DELIVERY);
+ start_of_flow->page_types[2].push_back(AUTOCHECKOUT_STEP_BILLING);
PopulateClickElement(&start_of_flow->proceed_element_descriptor, "#foo");
return start_of_flow.Pass();
}
@@ -178,6 +183,9 @@ scoped_ptr<AutocheckoutPageMetaData> CreateOnePageFlowMetaData() {
new AutocheckoutPageMetaData());
one_page_flow->current_page_number = 0;
one_page_flow->total_pages = 1;
+ one_page_flow->page_types[0].push_back(AUTOCHECKOUT_STEP_SHIPPING);
+ one_page_flow->page_types[0].push_back(AUTOCHECKOUT_STEP_DELIVERY);
+ one_page_flow->page_types[0].push_back(AUTOCHECKOUT_STEP_BILLING);
PopulateClickElement(&one_page_flow->proceed_element_descriptor, "#foo");
return one_page_flow.Pass();
}
@@ -272,8 +280,6 @@ class MockAutofillManagerDelegate : public TestAutofillManagerDelegate {
callback.Run(true);
}
- virtual void HideAutocheckoutBubble() OVERRIDE {}
-
virtual void ShowRequestAutocompleteDialog(
const FormData& form,
const GURL& source_url,
@@ -284,7 +290,16 @@ class MockAutofillManagerDelegate : public TestAutofillManagerDelegate {
callback.Run(user_supplied_data_.get(), "google_transaction_id");
}
- MOCK_METHOD1(UpdateProgressBar, void(double value));
+ virtual void AddAutocheckoutStep(AutocheckoutStepType step_type) OVERRIDE {
+ if (autocheckout_steps_.count(step_type) == 0)
+ autocheckout_steps_[step_type] = AUTOCHECKOUT_STEP_UNSTARTED;
+ }
+
+ virtual void UpdateAutocheckoutStep(
+ AutocheckoutStepType step_type,
+ AutocheckoutStepStatus step_status) OVERRIDE {
+ autocheckout_steps_[step_type] = step_status;
+ }
void SetUserSuppliedData(scoped_ptr<FormStructure> user_supplied_data) {
user_supplied_data_.reset(user_supplied_data.release());
@@ -302,10 +317,19 @@ class MockAutofillManagerDelegate : public TestAutofillManagerDelegate {
return request_autocomplete_dialog_open_;
}
+ bool AutocheckoutStepExistsWithStatus(
+ AutocheckoutStepType step_type,
+ AutocheckoutStepStatus step_status) const {
+ std::map<AutocheckoutStepType, AutocheckoutStepStatus>::const_iterator it =
+ autocheckout_steps_.find(step_type);
+ return it != autocheckout_steps_.end() && it->second == step_status;
+ }
+
private:
bool request_autocomplete_dialog_open_;
bool autocheckout_bubble_shown_;
scoped_ptr<FormStructure> user_supplied_data_;
+ std::map<AutocheckoutStepType, AutocheckoutStepStatus> autocheckout_steps_;
};
class TestAutofillManager : public AutofillManager {
@@ -416,8 +440,6 @@ class AutocheckoutManagerTest : public ChromeRenderViewHostTestHarness {
FakeUserSubmittedFormStructure());
GURL frame_url;
content::SSLStatus ssl_status;
- EXPECT_CALL(*autofill_manager_delegate_,
- UpdateProgressBar(testing::DoubleEq(1.0/3.0))).Times(1);
EXPECT_CALL(autocheckout_manager_->metric_logger(),
LogAutocheckoutBuyFlowMetric(
AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_STARTED)).Times(1);
@@ -427,6 +449,15 @@ class AutocheckoutManagerTest : public ChromeRenderViewHostTestHarness {
CheckFillFormsAndClickIpc();
EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
EXPECT_TRUE(autofill_manager_delegate_->request_autocomplete_dialog_open());
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_SHIPPING,
+ AUTOCHECKOUT_STEP_STARTED));
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_DELIVERY,
+ AUTOCHECKOUT_STEP_UNSTARTED));
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_BILLING,
+ AUTOCHECKOUT_STEP_UNSTARTED));
}
void HideRequestAutocompleteDialog() {
@@ -539,6 +570,9 @@ TEST_F(AutocheckoutManagerTest, OnClickFailedTestMissingAdvance) {
EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
EXPECT_TRUE(
autofill_manager_delegate_->request_autocomplete_dialog_open());
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_SHIPPING,
+ AUTOCHECKOUT_STEP_FAILED));
}
TEST_F(AutocheckoutManagerTest, OnClickFailedTestMissingClickBeforeFilling) {
@@ -604,67 +638,6 @@ TEST_F(AutocheckoutManagerTest, MaybeShowAutocheckoutBubbleTest) {
EXPECT_FALSE(autofill_manager_delegate_->request_autocomplete_dialog_open());
}
-// Test no proceed element is being passed to the render if a page metadata
-// with no proceed element is loaded.
-TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataMissingProceed) {
- OpenRequestAutocompleteDialog();
-
- // Go the second page with no proceed element.
- EXPECT_CALL(*autofill_manager_delegate_,
- UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
- autocheckout_manager_->OnLoadedPageMetaData(CreateMissingProceedMetaData());
-
- EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
-
- EXPECT_EQ(1U, process()->sink().message_count());
- uint32 kMsgID = AutofillMsg_FillFormsAndClick::ID;
- const IPC::Message* message =
- process()->sink().GetFirstMessageMatching(kMsgID);
- EXPECT_TRUE(message);
- AutofillParam autofill_param;
- AutofillMsg_FillFormsAndClick::Read(message, &autofill_param);
- // Ensure no proceed element is being passed to the render through IPC.
- EXPECT_EQ(WebElementDescriptor::NONE, autofill_param.d.retrieval_method);
- EXPECT_EQ("", autofill_param.d.descriptor);
- ClearIpcSink();
-}
-
-// Test |click_elements_before_form_fill| and |click_elements_after_form_fill|
-// are passed to the render correctly through IPC.
-TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataMultiClick) {
- OpenRequestAutocompleteDialog();
-
- // Go to the second page with multi-click elements.
- EXPECT_CALL(*autofill_manager_delegate_,
- UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
- autocheckout_manager_->OnLoadedPageMetaData(CreateMultiClickMetaData());
-
- EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
-
- EXPECT_EQ(1U, process()->sink().message_count());
- uint32 kMsgID = AutofillMsg_FillFormsAndClick::ID;
- const IPC::Message* message =
- process()->sink().GetFirstMessageMatching(kMsgID);
- EXPECT_TRUE(message);
- AutofillParam autofill_param;
- AutofillMsg_FillFormsAndClick::Read(message, &autofill_param);
- EXPECT_EQ(WebElementDescriptor::ID, autofill_param.d.retrieval_method);
- EXPECT_EQ("#foo", autofill_param.d.descriptor);
-
- // Verify |click_elements_before_form_fill|.
- ASSERT_EQ(2U, autofill_param.b.size());
- EXPECT_EQ(WebElementDescriptor::ID, autofill_param.b[0].retrieval_method);
- EXPECT_EQ("#before_form_fill_1", autofill_param.b[0].descriptor);
- EXPECT_EQ(WebElementDescriptor::ID, autofill_param.b[1].retrieval_method);
- EXPECT_EQ("#before_form_fill_2", autofill_param.b[1].descriptor);
-
- // Verify |click_elements_after_form_fill|.
- ASSERT_EQ(1U, autofill_param.c.size());
- EXPECT_EQ(WebElementDescriptor::ID, autofill_param.c[0].retrieval_method);
- EXPECT_EQ("#after_form_fill", autofill_param.c[0].descriptor);
- ClearIpcSink();
-}
-
TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataMissingMetaData) {
// Gettting no meta data after any autocheckout page is an error.
OpenRequestAutocompleteDialog();
@@ -695,14 +668,15 @@ TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataRepeatedStartPage) {
EXPECT_EQ(0U, process()->sink().message_count());
EXPECT_TRUE(
autofill_manager_delegate_->request_autocomplete_dialog_open());
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_SHIPPING,
+ AUTOCHECKOUT_STEP_FAILED));
}
TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataRepeatedPage) {
// Repeating a page is an error.
OpenRequestAutocompleteDialog();
// Go to second page.
- EXPECT_CALL(*autofill_manager_delegate_,
- UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
autocheckout_manager_->OnLoadedPageMetaData(CreateInFlowMetaData());
EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
CheckFillFormsAndClickIpc();
@@ -716,14 +690,15 @@ TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataRepeatedPage) {
EXPECT_EQ(0U, process()->sink().message_count());
EXPECT_TRUE(
autofill_manager_delegate_->request_autocomplete_dialog_open());
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_DELIVERY,
+ AUTOCHECKOUT_STEP_FAILED));
}
TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataNotInFlow) {
// Repeating a page is an error.
OpenRequestAutocompleteDialog();
// Go to second page.
- EXPECT_CALL(*autofill_manager_delegate_,
- UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
autocheckout_manager_->OnLoadedPageMetaData(CreateInFlowMetaData());
EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
CheckFillFormsAndClickIpc();
@@ -738,6 +713,9 @@ TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataNotInFlow) {
EXPECT_EQ(0U, process()->sink().message_count());
EXPECT_TRUE(
autofill_manager_delegate_->request_autocomplete_dialog_open());
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_DELIVERY,
+ AUTOCHECKOUT_STEP_FAILED));
}
TEST_F(AutocheckoutManagerTest,
@@ -748,8 +726,6 @@ TEST_F(AutocheckoutManagerTest,
AutofillMetrics::BUBBLE_COULD_BE_DISPLAYED)).Times(1);
autocheckout_manager_->OnLoadedPageMetaData(CreateStartOfFlowMetaData());
// Go to second page.
- EXPECT_CALL(*autofill_manager_delegate_,
- UpdateProgressBar(testing::_)).Times(0);
autocheckout_manager_->OnLoadedPageMetaData(CreateInFlowMetaData());
EXPECT_EQ(0U, process()->sink().message_count());
}
@@ -757,30 +733,40 @@ TEST_F(AutocheckoutManagerTest,
TEST_F(AutocheckoutManagerTest, FullAutocheckoutFlow) {
// Test for progression through last page.
OpenRequestAutocompleteDialog();
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_SHIPPING,
+ AUTOCHECKOUT_STEP_STARTED));
// Go to second page.
- EXPECT_CALL(*autofill_manager_delegate_,
- UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
EXPECT_CALL(*autofill_manager_delegate_, OnAutocheckoutSuccess()).Times(1);
autocheckout_manager_->OnLoadedPageMetaData(CreateInFlowMetaData());
EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_SHIPPING,
+ AUTOCHECKOUT_STEP_COMPLETED));
CheckFillFormsAndClickIpc();
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_DELIVERY,
+ AUTOCHECKOUT_STEP_STARTED));
// Go to third page.
- EXPECT_CALL(*autofill_manager_delegate_, UpdateProgressBar(1)).Times(1);
EXPECT_CALL(autocheckout_manager_->metric_logger(),
LogAutocheckoutBuyFlowMetric(
AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_SUCCESS)).Times(1);
autocheckout_manager_->OnLoadedPageMetaData(CreateEndOfFlowMetaData());
CheckFillFormsAndClickIpc();
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_DELIVERY,
+ AUTOCHECKOUT_STEP_COMPLETED));
EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
EXPECT_TRUE(autofill_manager_delegate_->request_autocomplete_dialog_open());
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_BILLING,
+ AUTOCHECKOUT_STEP_COMPLETED));
}
TEST_F(AutocheckoutManagerTest, CancelledAutocheckoutFlow) {
// Test for progression through last page.
OpenRequestAutocompleteDialog();
// Go to second page.
- EXPECT_CALL(*autofill_manager_delegate_,
- UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
autocheckout_manager_->OnLoadedPageMetaData(CreateInFlowMetaData());
EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
CheckFillFormsAndClickIpc();
@@ -790,8 +776,6 @@ TEST_F(AutocheckoutManagerTest, CancelledAutocheckoutFlow) {
EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
// Go to third page.
- EXPECT_CALL(*autofill_manager_delegate_,
- UpdateProgressBar(testing::_)).Times(0);
EXPECT_CALL(autocheckout_manager_->metric_logger(),
LogAutocheckoutBuyFlowMetric(testing::_)).Times(0);
autocheckout_manager_->OnLoadedPageMetaData(CreateEndOfFlowMetaData());
@@ -813,8 +797,6 @@ TEST_F(AutocheckoutManagerTest, SinglePageFlow) {
FakeUserSubmittedFormStructure());
GURL frame_url;
content::SSLStatus ssl_status;
- EXPECT_CALL(*autofill_manager_delegate_,
- UpdateProgressBar(testing::DoubleEq(1))).Times(1);
EXPECT_CALL(autocheckout_manager_->metric_logger(),
LogAutocheckoutBuyFlowMetric(
AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_STARTED)).Times(1);
@@ -827,6 +809,15 @@ TEST_F(AutocheckoutManagerTest, SinglePageFlow) {
CheckFillFormsAndClickIpc();
EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
EXPECT_TRUE(autofill_manager_delegate_->request_autocomplete_dialog_open());
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_SHIPPING,
+ AUTOCHECKOUT_STEP_COMPLETED));
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_DELIVERY,
+ AUTOCHECKOUT_STEP_COMPLETED));
+ EXPECT_TRUE(autofill_manager_delegate_
+ ->AutocheckoutStepExistsWithStatus(AUTOCHECKOUT_STEP_BILLING,
+ AUTOCHECKOUT_STEP_COMPLETED));
}
} // namespace autofill
diff --git a/components/autofill/content/browser/autocheckout_page_meta_data.h b/components/autofill/content/browser/autocheckout_page_meta_data.h
index 8cdf3d3..6839d1b 100644
--- a/components/autofill/content/browser/autocheckout_page_meta_data.h
+++ b/components/autofill/content/browser/autocheckout_page_meta_data.h
@@ -5,9 +5,11 @@
#ifndef COMPONENTS_AUTOFILL_CONTENT_BROWSER_AUTOCHECKOUT_PAGE_META_DATA_H_
#define COMPONENTS_AUTOFILL_CONTENT_BROWSER_AUTOCHECKOUT_PAGE_META_DATA_H_
+#include <map>
#include <vector>
#include "base/basictypes.h"
+#include "components/autofill/content/browser/autocheckout_steps.h"
#include "components/autofill/core/common/web_element_descriptor.h"
namespace autofill {
@@ -61,6 +63,11 @@ struct AutocheckoutPageMetaData {
// |click_elements_after_form_fill|.
WebElementDescriptor proceed_element_descriptor;
+ // Mapping of page numbers to the types of Autocheckout actions that will be
+ // performed on the given page of a multipage Autofill flow.
+ // If this form doesn't belong to such a flow, the map will be empty.
+ std::map<int, std::vector<AutocheckoutStepType> > page_types;
+
private:
DISALLOW_COPY_AND_ASSIGN(AutocheckoutPageMetaData);
};
diff --git a/components/autofill/content/browser/autocheckout_steps.h b/components/autofill/content/browser/autocheckout_steps.h
new file mode 100644
index 0000000..d46abcc
--- /dev/null
+++ b/components/autofill/content/browser/autocheckout_steps.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_BROWSER_AUTOCHECKOUT_STEPS_H_
+#define COMPONENTS_AUTOFILL_BROWSER_AUTOCHECKOUT_STEPS_H_
+
+namespace autofill {
+
+// Stages of a buy flow that may be encountered on an Autocheckout-supported
+// site, used primarily for display purposes.
+// Indexed for easy conversion from int values returned by Autofill server.
+enum AutocheckoutStepType {
+ AUTOCHECKOUT_STEP_MIN_VALUE = 1,
+ AUTOCHECKOUT_STEP_SHIPPING = AUTOCHECKOUT_STEP_MIN_VALUE,
+ AUTOCHECKOUT_STEP_DELIVERY = 2,
+ AUTOCHECKOUT_STEP_BILLING = 3,
+ AUTOCHECKOUT_STEP_PROXY_CARD = 4,
+ AUTOCHECKOUT_STEP_MAX_VALUE = AUTOCHECKOUT_STEP_PROXY_CARD,
+};
+
+// Possible statuses for the above step types, again used primarily for display.
+enum AutocheckoutStepStatus {
+ AUTOCHECKOUT_STEP_UNSTARTED,
+ AUTOCHECKOUT_STEP_STARTED,
+ AUTOCHECKOUT_STEP_COMPLETED,
+ AUTOCHECKOUT_STEP_FAILED,
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_BROWSER_AUTOCHECKOUT_STEPS_H_
diff --git a/components/autofill/core/browser/autofill_manager_delegate.h b/components/autofill/core/browser/autofill_manager_delegate.h
index 42b1f62..0571bd8 100644
--- a/components/autofill/core/browser/autofill_manager_delegate.h
+++ b/components/autofill/core/browser/autofill_manager_delegate.h
@@ -11,6 +11,7 @@
#include "base/i18n/rtl.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
+#include "components/autofill/content/browser/autocheckout_steps.h"
namespace content {
struct PasswordForm;
@@ -127,11 +128,14 @@ class AutofillManagerDelegate {
// Hide the Autofill popup if one is currently showing.
virtual void HideAutofillPopup() = 0;
- // Updates the Autocheckout progress bar. |value| must be in [0.0, 1.0].
- virtual void UpdateProgressBar(double value) = 0;
-
// Whether the Autocomplete feature of Autofill should be enabled.
virtual bool IsAutocompleteEnabled() = 0;
+
+ // Update progress of the Autocheckout flow as displayed to the user.
+ virtual void AddAutocheckoutStep(AutocheckoutStepType step_type) = 0;
+ virtual void UpdateAutocheckoutStep(
+ AutocheckoutStepType step_type,
+ AutocheckoutStepStatus step_status) = 0;
};
} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_xml_parser.cc b/components/autofill/core/browser/autofill_xml_parser.cc
index 40785ab..4b744f6 100644
--- a/components/autofill/core/browser/autofill_xml_parser.cc
+++ b/components/autofill/core/browser/autofill_xml_parser.cc
@@ -8,6 +8,7 @@
#include <string.h>
#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
#include "components/autofill/content/browser/autocheckout_page_meta_data.h"
#include "components/autofill/core/browser/autofill_server_field_info.h"
#include "third_party/libjingle/source/talk/xmllite/qname.h"
@@ -42,7 +43,9 @@ AutofillQueryXmlParser::AutofillQueryXmlParser(
upload_required_(upload_required),
experiment_id_(experiment_id),
page_meta_data_(page_meta_data),
- current_click_element_(NULL) {
+ current_click_element_(NULL),
+ current_page_number_for_page_types_(0),
+ is_in_type_section_(false) {
DCHECK(upload_required_);
DCHECK(experiment_id_);
DCHECK(page_meta_data_);
@@ -140,6 +143,17 @@ void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context,
back();
} else if (element.compare("web_element") == 0) {
ParseElementDescriptor(context, attrs, current_click_element_);
+ } else if (element.compare("flow_page") == 0) {
+ while (*attrs) {
+ buzz::QName attribute_qname = context->ResolveQName(*attrs, true);
+ ++attrs;
+ const std::string& attribute_name = attribute_qname.LocalPart();
+ if (attribute_name.compare("page_no") == 0)
+ current_page_number_for_page_types_ = GetIntValue(context, *attrs);
+ ++attrs;
+ }
+ } else if (element.compare("type") == 0) {
+ is_in_type_section_ = true;
}
}
@@ -171,6 +185,27 @@ void AutofillQueryXmlParser::ParseElementDescriptor(
}
}
+void AutofillQueryXmlParser::EndElement(buzz::XmlParseContext* context,
+ const char* name) {
+ is_in_type_section_ = false;
+}
+
+void AutofillQueryXmlParser::CharacterData(
+ buzz::XmlParseContext* context, const char* text, int len) {
+ if (!is_in_type_section_)
+ return;
+
+ int type = -1;
+ base::StringToInt(text, &type);
+ if (type >= AUTOCHECKOUT_STEP_MIN_VALUE &&
+ type <= AUTOCHECKOUT_STEP_MAX_VALUE) {
+ AutocheckoutStepType step_type =
+ static_cast<AutocheckoutStepType>(type);
+ page_meta_data_->page_types[current_page_number_for_page_types_]
+ .push_back(step_type);
+ }
+}
+
int AutofillQueryXmlParser::GetIntValue(buzz::XmlParseContext* context,
const char* attribute) {
char* attr_end = NULL;
diff --git a/components/autofill/core/browser/autofill_xml_parser.h b/components/autofill/core/browser/autofill_xml_parser.h
index f95f179..c01f137 100644
--- a/components/autofill/core/browser/autofill_xml_parser.h
+++ b/components/autofill/core/browser/autofill_xml_parser.h
@@ -97,6 +97,21 @@ class AutofillQueryXmlParser : public AutofillXmlParser {
const char* const* attrs,
WebElementDescriptor* element_descriptor);
+ // A callback for the end of an </element>, called by Expat.
+ // |context| is a parsing context used to resolve element/attribute names.
+ // |name| is the name of the element.
+ virtual void EndElement(buzz::XmlParseContext* context,
+ const char* name) OVERRIDE;
+
+ // The callback for character data between tags (<element>text...</element>).
+ // |context| is a parsing context used to resolve element/attribute names.
+ // |text| is a pointer to the beginning of character data (not null
+ // terminated).
+ // |len| is the length of the string pointed to by text.
+ virtual void CharacterData(buzz::XmlParseContext* context,
+ const char* text,
+ int len) OVERRIDE;
+
// A helper function to retrieve integer values from strings. Raises an
// XML parse error if it fails.
// |context| is the current parsing context.
@@ -120,6 +135,12 @@ class AutofillQueryXmlParser : public AutofillXmlParser {
// The click element the parser is currently processing.
WebElementDescriptor* current_click_element_;
+ // Number of page whose type is currently being parsed.
+ int current_page_number_for_page_types_;
+
+ // Whether the instance is currently parsing inside 'type' tags.
+ bool is_in_type_section_;
+
DISALLOW_COPY_AND_ASSIGN(AutofillQueryXmlParser);
};
diff --git a/components/autofill/core/browser/autofill_xml_parser_unittest.cc b/components/autofill/core/browser/autofill_xml_parser_unittest.cc
index 35078f0..9f38bbe 100644
--- a/components/autofill/core/browser/autofill_xml_parser_unittest.cc
+++ b/components/autofill/core/browser/autofill_xml_parser_unittest.cc
@@ -171,6 +171,13 @@ TEST_F(AutofillQueryXmlParserTest, ParseAutofillFlow) {
"<field autofilltype=\"55\"/>"
"<autofill_flow page_no=\"1\" total_pages=\"10\">"
"<page_advance_button id=\"foo\"/>"
+ "<flow_page page_no=\"0\">"
+ "<type>1</type>"
+ "<type>2</type>"
+ "</flow_page>"
+ "<flow_page page_no=\"1\">"
+ "<type>3</type>"
+ "</flow_page>"
"</autofill_flow>"
"</autofillqueryresponse>";
@@ -183,6 +190,12 @@ TEST_F(AutofillQueryXmlParserTest, ParseAutofillFlow) {
EXPECT_EQ("foo", page_meta_data_.proceed_element_descriptor.descriptor);
EXPECT_EQ(autofill::WebElementDescriptor::ID,
page_meta_data_.proceed_element_descriptor.retrieval_method);
+ EXPECT_EQ(2U, page_meta_data_.page_types.size());
+ EXPECT_EQ(2U, page_meta_data_.page_types[0].size());
+ EXPECT_EQ(1U, page_meta_data_.page_types[1].size());
+ EXPECT_EQ(AUTOCHECKOUT_STEP_SHIPPING, page_meta_data_.page_types[0][0]);
+ EXPECT_EQ(AUTOCHECKOUT_STEP_DELIVERY, page_meta_data_.page_types[0][1]);
+ EXPECT_EQ(AUTOCHECKOUT_STEP_BILLING, page_meta_data_.page_types[1][0]);
// Clear |field_infos_| for the next test;
field_infos_.clear();
diff --git a/components/autofill/core/browser/test_autofill_manager_delegate.cc b/components/autofill/core/browser/test_autofill_manager_delegate.cc
index 944ab32..665758f 100644
--- a/components/autofill/core/browser/test_autofill_manager_delegate.cc
+++ b/components/autofill/core/browser/test_autofill_manager_delegate.cc
@@ -60,7 +60,12 @@ void TestAutofillManagerDelegate::ShowAutofillPopup(
void TestAutofillManagerDelegate::HideAutofillPopup() {}
-void TestAutofillManagerDelegate::UpdateProgressBar(double value) {}
+void TestAutofillManagerDelegate::AddAutocheckoutStep(
+ AutocheckoutStepType step_type) {}
+
+void TestAutofillManagerDelegate::UpdateAutocheckoutStep(
+ AutocheckoutStepType step_type,
+ AutocheckoutStepStatus step_status) {}
bool TestAutofillManagerDelegate::IsAutocompleteEnabled() {
return true;
diff --git a/components/autofill/core/browser/test_autofill_manager_delegate.h b/components/autofill/core/browser/test_autofill_manager_delegate.h
index 1531770..1368b06 100644
--- a/components/autofill/core/browser/test_autofill_manager_delegate.h
+++ b/components/autofill/core/browser/test_autofill_manager_delegate.h
@@ -51,9 +51,13 @@ class TestAutofillManagerDelegate : public AutofillManagerDelegate {
const std::vector<int>& identifiers,
base::WeakPtr<AutofillPopupDelegate> delegate) OVERRIDE;
virtual void HideAutofillPopup() OVERRIDE;
- virtual void UpdateProgressBar(double value) OVERRIDE;
virtual bool IsAutocompleteEnabled() OVERRIDE;
+ virtual void AddAutocheckoutStep(AutocheckoutStepType step_type) OVERRIDE;
+ virtual void UpdateAutocheckoutStep(
+ AutocheckoutStepType step_type,
+ AutocheckoutStepStatus step_status) OVERRIDE;
+
private:
DISALLOW_COPY_AND_ASSIGN(TestAutofillManagerDelegate);
};