summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/autofill/autofill_dialog_gtk.cc184
-rw-r--r--chrome/browser/autofill/autofill_manager.cc8
-rw-r--r--chrome/browser/autofill/autofill_profile.cc2
-rw-r--r--chrome/browser/autofill/autofill_profile.h6
-rw-r--r--chrome/browser/autofill/credit_card.cc90
-rw-r--r--chrome/browser/autofill/credit_card.h42
-rw-r--r--chrome/browser/autofill/personal_data_manager.cc203
-rw-r--r--chrome/browser/autofill/personal_data_manager.h51
-rw-r--r--chrome/browser/autofill/personal_data_manager_unittest.cc103
-rw-r--r--chrome/browser/webdata/web_data_service.cc101
-rw-r--r--chrome/browser/webdata/web_data_service.h51
-rw-r--r--chrome/browser/webdata/web_database.cc176
-rw-r--r--chrome/browser/webdata/web_database.h19
-rw-r--r--chrome/browser/webdata/web_database_unittest.cc75
14 files changed, 963 insertions, 148 deletions
diff --git a/chrome/browser/autofill/autofill_dialog_gtk.cc b/chrome/browser/autofill/autofill_dialog_gtk.cc
index 33a30a5..20f673d 100644
--- a/chrome/browser/autofill/autofill_dialog_gtk.cc
+++ b/chrome/browser/autofill/autofill_dialog_gtk.cc
@@ -57,6 +57,23 @@ typedef struct _AddressWidgets {
GtkWidget* fax3;
} AddressWidgets;
+// All of these widgets are GtkEntrys except for default_profile, which is a
+// GtkCheckButton, and billing/shipping_address are GtkComboBoxes.
+typedef struct _CreditCardWidgets {
+ GtkWidget* label;
+ GtkWidget* default_creditcard;
+ GtkWidget* name_on_card;
+ GtkWidget* card_number;
+ GtkWidget* expiration_month;
+ GtkWidget* expiration_year;
+ GtkWidget* verification_code;
+ GtkWidget* billing_address;
+ GtkWidget* shipping_address;
+ GtkWidget* phone1;
+ GtkWidget* phone2;
+ GtkWidget* phone3;
+} CreditCardWidgets;
+
// Adds an alignment around |widget| which indents the widget by |offset|.
GtkWidget* IndentWidget(GtkWidget* widget, int offset) {
GtkWidget* alignment = gtk_alignment_new(0, 0, 0, 0);
@@ -267,11 +284,14 @@ class AutoFillDialog {
// for either an address or a credit card. The expander will be expanded by
// default if |expand| is true.
GtkWidget* AddNewAddress(bool expand);
- GtkWidget* AddNewCreditCard();
+ GtkWidget* AddNewCreditCard(bool expand);
// Adds a new address filled out with information from |profile|.
void AddAddress(const AutoFillProfile& profile);
+ // Adds a new credit card filled out with information from |credit_card|.
+ void AddCreditCard(const CreditCard& credit_card);
+
// The list of current AutoFill profiles.
std::vector<AutoFillProfile> profiles_;
@@ -281,6 +301,9 @@ class AutoFillDialog {
// The list of address widgets, used to modify the AutoFill profiles.
std::vector<AddressWidgets> address_widgets_;
+ // The list of credit card widgets, used to modify the stored credit cards.
+ std::vector<CreditCardWidgets> credit_card_widgets_;
+
// The AutoFill dialog.
GtkWidget* dialog_;
@@ -306,11 +329,14 @@ AutoFillDialog::AutoFillDialog(AutoFillDialogObserver* observer,
DCHECK(observer);
// Copy the profiles.
- std::vector<AutoFillProfile*>::const_iterator profile;
- for (profile = profiles.begin(); profile != profiles.end(); ++profile)
- profiles_.push_back(**profile);
+ for (std::vector<AutoFillProfile*>::const_iterator iter = profiles.begin();
+ iter != profiles.end(); ++iter)
+ profiles_.push_back(**iter);
- // TODO(jhawkins): Copy the credit cards.
+ // Copy the credit cards.
+ for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin();
+ iter != credit_cards.end(); ++iter)
+ credit_cards_.push_back(**iter);
dialog_ = gtk_dialog_new_with_buttons(
l10n_util::GetStringUTF8(IDS_AUTOFILL_DIALOG_TITLE).c_str(),
@@ -365,8 +391,8 @@ AutoFillDialog::AutoFillDialog(AutoFillDialogObserver* observer,
G_CALLBACK(OnAddAddressClicked));
gtk_box_pack_start_defaults(GTK_BOX(outer_vbox), addresses_vbox_);
- std::vector<AutoFillProfile>::const_iterator iter;
- for (iter = profiles_.begin(); iter != profiles_.end(); ++iter)
+ for (std::vector<AutoFillProfile>::const_iterator iter = profiles_.begin();
+ iter != profiles_.end(); ++iter)
AddAddress(*iter);
creditcards_vbox_ = InitGroup(IDS_AUTOFILL_CREDITCARDS_GROUP_NAME,
@@ -374,7 +400,9 @@ AutoFillDialog::AutoFillDialog(AutoFillDialogObserver* observer,
G_CALLBACK(OnAddCreditCardClicked));
gtk_box_pack_start_defaults(GTK_BOX(outer_vbox), creditcards_vbox_);
- // TODO(jhawkins): Add credit cards from |credit_cards|.
+ for (std::vector<CreditCard>::const_iterator iter = credit_cards_.begin();
+ iter != credit_cards_.end(); ++iter)
+ AddCreditCard(*iter);
gtk_widget_show_all(dialog_);
}
@@ -432,19 +460,47 @@ static AutoFillProfile AutoFillProfileFromWidgetValues(
return profile;
}
+static CreditCard CreditCardFromWidgetValues(
+ const CreditCardWidgets& widgets) {
+ // TODO(jhawkins): unique id?
+ CreditCard credit_card(GetEntryText(widgets.label), 0);
+ credit_card.SetInfo(AutoFillType(CREDIT_CARD_NAME),
+ GetEntryText(widgets.name_on_card));
+ // TODO(jhawkins): Credit card type.
+ credit_card.SetInfo(AutoFillType(CREDIT_CARD_NUMBER),
+ GetEntryText(widgets.card_number));
+ credit_card.SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH),
+ GetEntryText(widgets.expiration_month));
+ credit_card.SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR),
+ GetEntryText(widgets.expiration_year));
+ credit_card.SetInfo(AutoFillType(CREDIT_CARD_VERIFICATION_CODE),
+ GetEntryText(widgets.verification_code));
+ // TODO(jhawkins): Billing/shipping addresses.
+ return credit_card;
+}
+
// static
void AutoFillDialog::OnResponse(GtkDialog* dialog, gint response_id,
AutoFillDialog* autofill_dialog) {
if (response_id == GTK_RESPONSE_APPLY || response_id == GTK_RESPONSE_OK) {
autofill_dialog->profiles_.clear();
- std::vector<AddressWidgets>::const_iterator iter;
- for (iter = autofill_dialog->address_widgets_.begin();
+ for (std::vector<AddressWidgets>::const_iterator iter =
+ autofill_dialog->address_widgets_.begin();
iter != autofill_dialog->address_widgets_.end();
++iter) {
autofill_dialog->profiles_.push_back(
AutoFillProfileFromWidgetValues(*iter));
}
+ autofill_dialog->credit_cards_.clear();
+ for (std::vector<CreditCardWidgets>::const_iterator iter =
+ autofill_dialog->credit_card_widgets_.begin();
+ iter != autofill_dialog->credit_card_widgets_.end();
+ ++iter) {
+ autofill_dialog->credit_cards_.push_back(
+ CreditCardFromWidgetValues(*iter));
+ }
+
autofill_dialog->observer_->OnAutoFillDialogApply(
&autofill_dialog->profiles_,
&autofill_dialog->credit_cards_);
@@ -467,7 +523,7 @@ void AutoFillDialog::OnAddAddressClicked(GtkButton* button,
// static
void AutoFillDialog::OnAddCreditCardClicked(GtkButton* button,
AutoFillDialog* dialog) {
- GtkWidget* new_creditcard = dialog->AddNewCreditCard();
+ GtkWidget* new_creditcard = dialog->AddNewCreditCard(true);
gtk_box_pack_start(GTK_BOX(dialog->creditcards_vbox_), new_creditcard,
FALSE, FALSE, 0);
gtk_widget_show_all(new_creditcard);
@@ -514,7 +570,39 @@ void AutoFillDialog::OnDeleteAddressClicked(GtkButton* button,
// static
void AutoFillDialog::OnDeleteCreditCardClicked(GtkButton* button,
AutoFillDialog* dialog) {
- // TODO(jhawkins): Remove the associated credit card.
+ GtkWidget* entry = GetButtonData(GTK_WIDGET(button));
+ string16 label = GetEntryText(entry);
+
+ // TODO(jhawkins): Base this on ID.
+
+ // Remove the credit card.
+ for (std::vector<CreditCard>::iterator iter = dialog->credit_cards_.begin();
+ iter != dialog->credit_cards_.end();
+ ++iter) {
+ if (iter->Label() == label) {
+ dialog->credit_cards_.erase(iter);
+ break;
+ }
+ }
+
+ // Remove the set of credit widgets.
+ for (std::vector<CreditCardWidgets>::iterator iter =
+ dialog->credit_card_widgets_.begin();
+ iter != dialog->credit_card_widgets_.end();
+ ++iter) {
+ if (iter->label == entry) {
+ dialog->credit_card_widgets_.erase(iter);
+ break;
+ }
+ }
+
+ // Get back to the expander widget.
+ GtkWidget* expander = gtk_widget_get_ancestor(GTK_WIDGET(button),
+ GTK_TYPE_EXPANDER);
+ DCHECK(expander);
+
+ // Destroying the widget will also remove it from the parent container.
+ gtk_widget_destroy(expander);
}
// static
@@ -647,33 +735,38 @@ GtkWidget* AutoFillDialog::AddNewAddress(bool expand) {
return address;
}
-GtkWidget* AutoFillDialog::AddNewCreditCard() {
+GtkWidget* AutoFillDialog::AddNewCreditCard(bool expand) {
+ CreditCardWidgets widgets = {0};
GtkWidget* vbox;
GtkWidget* credit_card = InitGroupContentArea(IDS_AUTOFILL_NEW_CREDITCARD,
&vbox);
+ gtk_expander_set_expanded(GTK_EXPANDER(credit_card), expand);
+
GtkWidget* label_table = InitFormTable(1, 2);
gtk_box_pack_start_defaults(GTK_BOX(vbox), label_table);
- FormTableAddLabelEntry(label_table, 0, 0, 1, IDS_AUTOFILL_DIALOG_LABEL,
- credit_card, G_CALLBACK(OnLabelChanged));
+ widgets.label = FormTableAddLabelEntry(label_table, 0, 0, 1,
+ IDS_AUTOFILL_DIALOG_LABEL, credit_card,
+ G_CALLBACK(OnLabelChanged));
// TODO(jhawkins): If there's not a default profile, automatically check this
// check button.
- GtkWidget* default_check = gtk_check_button_new_with_label(
+ widgets.default_creditcard = gtk_check_button_new_with_label(
l10n_util::GetStringUTF8(IDS_AUTOFILL_DIALOG_MAKE_DEFAULT).c_str());
- FormTableSetWidget(label_table, default_check, 0, 1, 1, true);
+ FormTableSetWidget(label_table, widgets.default_creditcard, 0, 1, 1, true);
GtkWidget* name_cc_table = InitFormTable(2, 6);
gtk_box_pack_start_defaults(GTK_BOX(vbox), name_cc_table);
- FormTableAddExpandedEntry(name_cc_table, 0, 0, 3,
- IDS_AUTOFILL_DIALOG_NAME_ON_CARD);
- FormTableAddExpandedEntry(name_cc_table, 1, 0, 3,
- IDS_AUTOFILL_DIALOG_CREDIT_CARD_NUMBER);
- FormTableAddSizedEntry(name_cc_table, 1, 3, 2, 0);
- FormTableAddSizedEntry(name_cc_table, 1, 4, 4, 0);
- FormTableAddSizedEntry(name_cc_table, 1, 5, 5, IDS_AUTOFILL_DIALOG_CVC);
+ widgets.name_on_card = FormTableAddExpandedEntry(
+ name_cc_table, 0, 0, 3, IDS_AUTOFILL_DIALOG_NAME_ON_CARD);
+ widgets.card_number = FormTableAddExpandedEntry(
+ name_cc_table, 1, 0, 3, IDS_AUTOFILL_DIALOG_CREDIT_CARD_NUMBER);
+ widgets.expiration_month = FormTableAddSizedEntry(name_cc_table, 1, 3, 2, 0);
+ widgets.expiration_year = FormTableAddSizedEntry(name_cc_table, 1, 4, 4, 0);
+ widgets.verification_code = FormTableAddSizedEntry(
+ name_cc_table, 1, 5, 5, IDS_AUTOFILL_DIALOG_CVC);
FormTableSetLabel(name_cc_table, 1, 3, 2,
IDS_AUTOFILL_DIALOG_EXPIRATION_DATE);
@@ -687,6 +780,7 @@ GtkWidget* AutoFillDialog::AddNewCreditCard() {
IDS_AUTOFILL_DIALOG_BILLING_ADDRESS);
GtkWidget* billing = gtk_combo_box_new_text();
+ widgets.billing_address = billing;
std::string combo_text = l10n_util::GetStringUTF8(
IDS_AUTOFILL_DIALOG_CHOOSE_EXISTING_ADDRESS);
gtk_combo_box_append_text(GTK_COMBO_BOX(billing), combo_text.c_str());
@@ -697,6 +791,7 @@ GtkWidget* AutoFillDialog::AddNewCreditCard() {
IDS_AUTOFILL_DIALOG_SHIPPING_ADDRESS);
GtkWidget* shipping = gtk_combo_box_new_text();
+ widgets.shipping_address = shipping;
combo_text = l10n_util::GetStringUTF8(IDS_AUTOFILL_DIALOG_SAME_AS_BILLING);
gtk_combo_box_append_text(GTK_COMBO_BOX(shipping), combo_text.c_str());
gtk_combo_box_set_active(GTK_COMBO_BOX(shipping), 0);
@@ -705,16 +800,21 @@ GtkWidget* AutoFillDialog::AddNewCreditCard() {
GtkWidget* phone_table = InitFormTable(1, 4);
gtk_box_pack_start_defaults(GTK_BOX(vbox), phone_table);
- FormTableAddSizedEntry(phone_table, 0, 0, 4, IDS_AUTOFILL_DIALOG_PHONE);
- FormTableAddSizedEntry(phone_table, 0, 1, 4, 0);
- FormTableAddEntry(phone_table, 0, 2, 2, 0);
+ widgets.phone1 = FormTableAddSizedEntry(
+ phone_table, 0, 0, 4, IDS_AUTOFILL_DIALOG_PHONE);
+ widgets.phone2 = FormTableAddSizedEntry(phone_table, 0, 1, 4, 0);
+ widgets.phone3 = FormTableAddEntry(phone_table, 0, 2, 2, 0);
GtkWidget* button = gtk_button_new_with_label(
l10n_util::GetStringUTF8(IDS_AUTOFILL_DELETE_BUTTON).c_str());
+ g_signal_connect(button, "clicked",
+ G_CALLBACK(OnDeleteCreditCardClicked), this);
+ SetButtonData(button, widgets.label);
GtkWidget* alignment = gtk_alignment_new(0, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(alignment), button);
gtk_box_pack_start_defaults(GTK_BOX(vbox), alignment);
+ credit_card_widgets_.push_back(widgets);
return credit_card;
}
@@ -765,6 +865,36 @@ void AutoFillDialog::AddAddress(const AutoFillProfile& profile) {
gtk_widget_show_all(address);
}
+void AutoFillDialog::AddCreditCard(const CreditCard& credit_card) {
+ GtkWidget* credit_card_widget = AddNewCreditCard(false);
+ gtk_expander_set_label(GTK_EXPANDER(credit_card_widget),
+ UTF16ToUTF8(credit_card.Label()).c_str());
+
+ // We just pushed the widgets to the back of the vector.
+ const CreditCardWidgets& widgets = credit_card_widgets_.back();
+ SetEntryText(widgets.label, credit_card.Label());
+ SetEntryText(widgets.name_on_card,
+ credit_card.GetFieldText(AutoFillType(CREDIT_CARD_NAME)));
+ /*SetEntryText(widgets.type,
+ credit_card.GetFieldText(AutoFillType(CREDIT_CARD_TYPE)));*/
+ SetEntryText(widgets.card_number,
+ credit_card.GetFieldText(AutoFillType(CREDIT_CARD_NUMBER)));
+ SetEntryText(widgets.expiration_month,
+ credit_card.GetFieldText(AutoFillType(CREDIT_CARD_EXP_MONTH)));
+ SetEntryText(
+ widgets.expiration_year,
+ credit_card.GetFieldText(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR)));
+ SetEntryText(
+ widgets.verification_code,
+ credit_card.GetFieldText(AutoFillType(CREDIT_CARD_VERIFICATION_CODE)));
+
+ // TODO(jhawkins): Set the GtkComboBox widgets.
+
+ gtk_box_pack_start(GTK_BOX(creditcards_vbox_), credit_card_widget,
+ FALSE, FALSE, 0);
+ gtk_widget_show_all(credit_card_widget);
+}
+
///////////////////////////////////////////////////////////////////////////////
// Factory/finder method:
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc
index 2e067a9..a9f1f7f 100644
--- a/chrome/browser/autofill/autofill_manager.cc
+++ b/chrome/browser/autofill/autofill_manager.cc
@@ -64,7 +64,7 @@ void AutoFillManager::OnAutoFillDialogApply(
std::vector<CreditCard>* credit_cards) {
// Save the personal data.
personal_data_->SetProfiles(profiles);
- // TODO(jhawkins): Set the credit cards.
+ personal_data_->SetCreditCards(credit_cards);
HandleSubmit();
}
@@ -74,10 +74,8 @@ void AutoFillManager::OnPersonalDataLoaded() {
// remove ourselves as observer.
personal_data_->RemoveObserver(this);
- // TODO(jhawkins): Actually send in the real credit cards from the personal
- // data manager.
- std::vector<CreditCard*> credit_cards;
- ShowAutoFillDialog(this, personal_data_->profiles(), credit_cards);
+ ShowAutoFillDialog(
+ this, personal_data_->profiles(), personal_data_->credit_cards());
}
void AutoFillManager::DeterminePossibleFieldTypes(
diff --git a/chrome/browser/autofill/autofill_profile.cc b/chrome/browser/autofill/autofill_profile.cc
index bfc4fef..cd0438d 100644
--- a/chrome/browser/autofill/autofill_profile.cc
+++ b/chrome/browser/autofill/autofill_profile.cc
@@ -188,7 +188,7 @@ Address* AutoFillProfile::GetHomeAddress() {
// So we can compare AutoFillProfiles with EXPECT_EQ().
std::ostream& operator<<(std::ostream& os, const AutoFillProfile& profile) {
return os
- << UTF16ToASCII(profile.Label())
+ << UTF16ToUTF8(profile.Label())
<< " "
<< profile.unique_id()
<< " "
diff --git a/chrome/browser/autofill/autofill_profile.h b/chrome/browser/autofill/autofill_profile.h
index acc7527..6142721 100644
--- a/chrome/browser/autofill/autofill_profile.h
+++ b/chrome/browser/autofill/autofill_profile.h
@@ -21,7 +21,7 @@ typedef std::map<FieldTypeGroup, FormGroup*> FormGroupMap;
class AutoFillProfile : public FormGroup {
public:
AutoFillProfile(const string16& label, int unique_id);
- // For use in std containers.
+ // For use in STL containers.
AutoFillProfile();
AutoFillProfile(const AutoFillProfile&);
virtual ~AutoFillProfile();
@@ -47,16 +47,16 @@ class AutoFillProfile : public FormGroup {
void set_use_billing_address(bool use);
bool use_billing_address() const { return use_billing_address_; }
+ void set_unique_id(int id) { unique_id_ = id; }
int unique_id() const { return unique_id_; }
- // For use in std containers.
+ // For use in STL containers.
void operator=(const AutoFillProfile&);
// Used by tests.
// TODO(jhawkins): Move these to private and add the test as a friend.
bool operator==(const AutoFillProfile& profile) const;
void set_label(const string16& label) { label_ = label; }
- void set_unique_id(int id) { unique_id_ = id; }
private:
Address* GetBillingAddress();
diff --git a/chrome/browser/autofill/credit_card.cc b/chrome/browser/autofill/credit_card.cc
index fb679a7..882a062 100644
--- a/chrome/browser/autofill/credit_card.cc
+++ b/chrome/browser/autofill/credit_card.cc
@@ -6,6 +6,7 @@
#include "base/basictypes.h"
#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/autofill/autofill_type.h"
#include "chrome/browser/autofill/field_types.h"
@@ -23,23 +24,16 @@ static const AutoFillFieldType kAutoFillCreditCardTypes[] = {
static const int kAutoFillCreditCardLength =
arraysize(kAutoFillCreditCardTypes);
-CreditCard::CreditCard(const string16& label)
+CreditCard::CreditCard(const string16& label, int unique_id)
: expiration_month_(0),
expiration_year_(0),
- label_(label) {
+ label_(label),
+ unique_id_(unique_id) {
}
-CreditCard::CreditCard(const CreditCard& card)
- : number_(card.number_),
- name_on_card_(card.name_on_card_),
- type_(card.type_),
- verification_code_(card.verification_code_),
- last_four_digits_(card.last_four_digits_),
- expiration_month_(card.expiration_month_),
- expiration_year_(card.expiration_year_),
- label_(card.label_) {
+CreditCard::CreditCard(const CreditCard& card) {
+ operator=(card);
}
-
FormGroup* CreditCard::Clone() const {
return new CreditCard(*this);
}
@@ -190,7 +184,8 @@ void CreditCard::SetInfo(const AutoFillType& type, const string16& value) {
break;
default:
- DLOG(ERROR) << "Attempting to set unknown info-type";
+ DLOG(ERROR) << "Attempting to set unknown info-type "
+ << type.field_type();
break;
}
}
@@ -254,6 +249,48 @@ void CreditCard::set_expiration_year(int expiration_year) {
expiration_year_ = expiration_year;
}
+
+void CreditCard::operator=(const CreditCard& source) {
+ number_ = source.number_;
+ name_on_card_ = source.name_on_card_;
+ type_ = source.type_;
+ verification_code_ = source.verification_code_;
+ last_four_digits_ = source.last_four_digits_;
+ expiration_month_ = source.expiration_month_;
+ expiration_year_ = source.expiration_year_;
+ label_ = source.label_;
+ billing_address_ = source.billing_address_;
+ shipping_address_ = source.shipping_address_;
+ unique_id_ = source.unique_id_;
+}
+
+bool CreditCard::operator==(const CreditCard& creditcard) const {
+ // The following CreditCard field types are the only types we store in the
+ // WebDB so far, so we're only concerned with matching these types in the
+ // profile.
+ const AutoFillFieldType types[] = { CREDIT_CARD_NAME,
+ CREDIT_CARD_TYPE,
+ CREDIT_CARD_NUMBER,
+ CREDIT_CARD_VERIFICATION_CODE,
+ CREDIT_CARD_EXP_MONTH,
+ CREDIT_CARD_EXP_4_DIGIT_YEAR };
+
+ if (label_ != creditcard.label_ ||
+ unique_id_ != creditcard.unique_id_ ||
+ billing_address_ != creditcard.billing_address_ ||
+ shipping_address_ != creditcard.shipping_address_) {
+ return false;
+ }
+
+ for (size_t index = 0; index < arraysize(types); ++index) {
+ if (GetFieldText(AutoFillType(types[index])) !=
+ creditcard.GetFieldText(AutoFillType(types[index])))
+ return false;
+ }
+
+ return true;
+}
+
bool CreditCard::FindInfoMatchesHelper(const AutoFillFieldType& field_type,
const string16& info,
string16* match) const {
@@ -395,3 +432,30 @@ bool CreditCard::ConvertDate(const string16& date, int* num) const {
return true;
}
+
+// So we can compare CreditCards with EXPECT_EQ().
+std::ostream& operator<<(std::ostream& os, const CreditCard& creditcard) {
+ return os
+ << UTF16ToUTF8(creditcard.Label())
+ << " "
+ << creditcard.unique_id()
+ << " "
+ << UTF16ToUTF8(creditcard.billing_address())
+ << " "
+ << UTF16ToUTF8(creditcard.shipping_address())
+ << " "
+ << UTF16ToUTF8(creditcard.GetFieldText(AutoFillType(CREDIT_CARD_NAME)))
+ << " "
+ << UTF16ToUTF8(creditcard.GetFieldText(AutoFillType(CREDIT_CARD_TYPE)))
+ << " "
+ << UTF16ToUTF8(creditcard.GetFieldText(AutoFillType(CREDIT_CARD_NUMBER)))
+ << " "
+ << UTF16ToUTF8(creditcard.GetFieldText(
+ AutoFillType(CREDIT_CARD_VERIFICATION_CODE)))
+ << " "
+ << UTF16ToUTF8(creditcard.GetFieldText(
+ AutoFillType(CREDIT_CARD_EXP_MONTH)))
+ << " "
+ << UTF16ToUTF8(creditcard.GetFieldText(
+ AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR)));
+}
diff --git a/chrome/browser/autofill/credit_card.h b/chrome/browser/autofill/credit_card.h
index 7d3cbe9..3962c40 100644
--- a/chrome/browser/autofill/credit_card.h
+++ b/chrome/browser/autofill/credit_card.h
@@ -13,9 +13,9 @@
// A form group that stores credit card information.
class CreditCard : public FormGroup {
public:
- explicit CreditCard(const string16& label);
- // Used for STL.
- explicit CreditCard(const CreditCard& card);
+ CreditCard(const string16& label, int unique_id);
+ // For use in STL containers.
+ CreditCard(const CreditCard& card);
// FormGroup implementation:
FormGroup* Clone() const;
@@ -49,6 +49,9 @@ class CreditCard : public FormGroup {
string16 last_four_digits() const { return last_four_digits_; }
int expiration_month() const { return expiration_month_; }
int expiration_year() const { return expiration_year_; }
+ string16 billing_address() const { return billing_address_; }
+ string16 shipping_address() const { return shipping_address_; }
+ int unique_id() const { return unique_id_; }
void set_number(const string16& number) { number_ = number; }
void set_name_on_card(const string16& name_on_card) {
@@ -61,15 +64,31 @@ class CreditCard : public FormGroup {
void set_last_four_digits(const string16& last_four_digits) {
last_four_digits_ = last_four_digits;
}
+ void set_unique_id(int id) { unique_id_ = id; }
+
+ // The caller should verify that the corresponding AutoFillProfile exists. If
+ // the shipping address should be the same as the billing address, send in an
+ // empty string to set_shipping_address.
+ void set_billing_address(const string16& address) {
+ billing_address_ = address;
+ }
+ void set_shipping_address(const string16& address) {
+ shipping_address_ = address;
+ }
// These setters verify that the month and year are within appropriate
// ranges.
void set_expiration_month(int expiration_month);
void set_expiration_year(int expiration_year);
- private:
- void operator=(const CreditCard& card);
+ // For use in STL containers.
+ void operator=(const CreditCard&);
+
+ // Used by tests.
+ bool operator==(const CreditCard& creditcard) const;
+ void set_label(const string16& label) { label_ = label; }
+ private:
// A helper function for FindInfoMatches that only handles matching the info
// with the requested field type.
bool FindInfoMatchesHelper(const AutoFillFieldType& field_type,
@@ -121,6 +140,19 @@ class CreditCard : public FormGroup {
// This is the display name of the card set by the user, e.g., Amazon Visa.
string16 label_;
+
+ // The billing and shipping addresses. The are the labels of
+ // AutoFillProfiles that contain the corresponding address. If
+ // |shipping_address_| is empty, the billing address is used for the shipping
+ // address.
+ string16 billing_address_;
+ string16 shipping_address_;
+
+ // The unique ID of this profile.
+ int unique_id_;
};
+// So we can compare CreditCards with EXPECT_EQ().
+std::ostream& operator<<(std::ostream& os, const CreditCard& creditcard);
+
#endif // CHROME_BROWSER_AUTOFILL_CREDIT_CARD_H_
diff --git a/chrome/browser/autofill/personal_data_manager.cc b/chrome/browser/autofill/personal_data_manager.cc
index e2b2150..0ed0cce 100644
--- a/chrome/browser/autofill/personal_data_manager.cc
+++ b/chrome/browser/autofill/personal_data_manager.cc
@@ -25,7 +25,8 @@ static const int kPhoneNumberLength = 7;
static const int kPhoneCityCodeLength = 3;
PersonalDataManager::~PersonalDataManager() {
- CancelPendingQuery();
+ CancelPendingQuery(&pending_profiles_query_);
+ CancelPendingQuery(&pending_creditcards_query_);
}
void PersonalDataManager::OnWebDataServiceRequestDone(
@@ -35,24 +36,27 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
if (!result)
return;
- DCHECK(pending_query_handle_);
- DCHECK(result->GetType() == AUTOFILL_PROFILES_RESULT);
- pending_query_handle_ = 0;
-
- unique_ids_.clear();
- profiles_.reset();
- const WDResult<std::vector<AutoFillProfile*> >* r =
- static_cast<const WDResult<std::vector<AutoFillProfile*> >*>(result);
- std::vector<AutoFillProfile*> profiles = r->GetValue();
- for (std::vector<AutoFillProfile*>::iterator iter = profiles.begin();
- iter != profiles.end(); ++iter) {
- unique_ids_.insert((*iter)->unique_id());
- profiles_.push_back(*iter);
+ DCHECK(pending_profiles_query_ || pending_creditcards_query_);
+ DCHECK(result->GetType() == AUTOFILL_PROFILES_RESULT ||
+ result->GetType() == AUTOFILL_CREDITCARDS_RESULT);
+
+ switch (result->GetType()) {
+ case AUTOFILL_PROFILES_RESULT:
+ ReceiveLoadedProfiles(h, result);
+ break;
+ case AUTOFILL_CREDITCARDS_RESULT:
+ ReceiveLoadedCreditCards(h, result);
+ break;
+ default:
+ NOTREACHED();
}
- is_data_loaded_ = true;
- if (observer_)
- observer_->OnPersonalDataLoaded();
+ // If both requests have responded, then all personal data is loaded.
+ if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0) {
+ is_data_loaded_ = true;
+ if (observer_)
+ observer_->OnPersonalDataLoaded();
+ }
}
void PersonalDataManager::SetObserver(PersonalDataManager::Observer* observer) {
@@ -75,9 +79,10 @@ bool PersonalDataManager::ImportFormData(
// possible to import.
int importable_fields = 0;
int importable_credit_card_fields = 0;
- imported_profile_.reset(new AutoFillProfile(string16(),
- CreateNextUniqueID()));
- imported_credit_card_.reset(new CreditCard(string16()));
+ imported_profile_.reset(new AutoFillProfile(
+ string16(), CreateNextUniqueID(&unique_profile_ids_)));
+ // TODO(jhawkins): Use a hash of the CC# instead of a list of unique IDs?
+ imported_credit_card_.reset(new CreditCard(string16(), 0));
bool billing_address_info = false;
std::vector<FormStructure*>::const_iterator iter;
@@ -161,28 +166,28 @@ void PersonalDataManager::SetProfiles(std::vector<AutoFillProfile>* profiles) {
for (std::vector<AutoFillProfile>::iterator iter = profiles->begin();
iter != profiles->end(); ++iter) {
if (iter->unique_id() != 0)
- unique_ids_.erase(iter->unique_id());
+ unique_profile_ids_.erase(iter->unique_id());
}
// Any remaining IDs are not in the new profile list and should be removed
// from the web database.
- for (std::set<int>::iterator iter = unique_ids_.begin();
- iter != unique_ids_.end(); ++iter) {
+ for (std::set<int>::iterator iter = unique_profile_ids_.begin();
+ iter != unique_profile_ids_.end(); ++iter) {
wds->RemoveAutoFillProfile(*iter);
}
// Clear the unique IDs. The set of unique IDs is updated for each profile
- // added to |profile_| below.
- unique_ids_.clear();
+ // added to |profiles_| below.
+ unique_profile_ids_.clear();
// Update the web database with the existing profiles. We need to handle
- // these first so that |unique_ids_| is reset with the IDs of the existing
- // profiles; otherwise, new profiles added before older profiles can take
- // their unique ID.
+ // these first so that |unique_profile_ids_| is reset with the IDs of the
+ // existing profiles; otherwise, new profiles added before older profiles can
+ // take their unique ID.
for (std::vector<AutoFillProfile>::iterator iter = profiles->begin();
iter != profiles->end(); ++iter) {
if (iter->unique_id() != 0) {
- unique_ids_.insert(iter->unique_id());
+ unique_profile_ids_.insert(iter->unique_id());
wds->UpdateAutoFillProfile(*iter);
}
}
@@ -190,10 +195,11 @@ void PersonalDataManager::SetProfiles(std::vector<AutoFillProfile>* profiles) {
// Add the new profiles to the web database.
for (std::vector<AutoFillProfile>::iterator iter = profiles->begin();
iter != profiles->end(); ++iter) {
- // Profile was added by the AutoFill dialog, so we need to set the unique
- // ID. This also means we need to add this profile to the web DB.
+ // The profile was added by the AutoFill dialog, so we need to set the
+ // unique ID. This also means we need to add this profile to the web
+ // database.
if (iter->unique_id() == 0) {
- iter->set_unique_id(CreateNextUniqueID());
+ iter->set_unique_id(CreateNextUniqueID(&unique_profile_ids_));
wds->AddAutoFillProfile(*iter);
}
}
@@ -205,6 +211,64 @@ void PersonalDataManager::SetProfiles(std::vector<AutoFillProfile>* profiles) {
}
}
+void PersonalDataManager::SetCreditCards(
+ std::vector<CreditCard>* credit_cards) {
+ if (profile_->IsOffTheRecord())
+ return;
+
+ WebDataService* wds = profile_->GetWebDataService(Profile::EXPLICIT_ACCESS);
+ if (!wds)
+ return;
+
+ // Remove the unique IDs of the new set of credit cards from the unique ID
+ // set.
+ for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
+ iter != credit_cards->end(); ++iter) {
+ if (iter->unique_id() != 0)
+ unique_creditcard_ids_.erase(iter->unique_id());
+ }
+
+ // Any remaining IDs are not in the new credit card list and should be removed
+ // from the web database.
+ for (std::set<int>::iterator iter = unique_creditcard_ids_.begin();
+ iter != unique_creditcard_ids_.end(); ++iter) {
+ wds->RemoveCreditCard(*iter);
+ }
+
+ // Clear the unique IDs. The set of unique IDs is updated for each credit
+ // card added to |credit_cards_| below.
+ unique_creditcard_ids_.clear();
+
+ // Update the web database with the existing credit cards. We need to handle
+ // these first so that |unique_creditcard_ids_| is reset with the IDs of the
+ // existing credit cards; otherwise, new credit cards added before older
+ // credit cards can take their unique ID.
+ for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
+ iter != credit_cards->end(); ++iter) {
+ if (iter->unique_id() != 0) {
+ unique_creditcard_ids_.insert(iter->unique_id());
+ wds->UpdateCreditCard(*iter);
+ }
+ }
+
+ // Add the new credit cards to the web database.
+ for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
+ iter != credit_cards->end(); ++iter) {
+ // The credit card was added by the AutoFill dialog, so we need to set the
+ // unique ID. This also means we need to add this credit card to the web
+ // database.
+ if (iter->unique_id() == 0) {
+ iter->set_unique_id(CreateNextUniqueID(&unique_creditcard_ids_));
+ wds->AddCreditCard(*iter);
+ }
+ }
+
+ credit_cards_.reset();
+ for (std::vector<CreditCard>::iterator iter = credit_cards->begin();
+ iter != credit_cards->end(); ++iter) {
+ credit_cards_.push_back(new CreditCard(*iter));
+ }
+}
void PersonalDataManager::GetPossibleFieldTypes(const string16& text,
FieldTypeSet* possible_types) {
@@ -227,7 +291,7 @@ void PersonalDataManager::GetPossibleFieldTypes(const string16& text,
profile->GetPossibleFieldTypes(clean_info, possible_types);
}
- for (ScopedVector<FormGroup>::iterator iter = credit_cards_.begin();
+ for (ScopedVector<CreditCard>::iterator iter = credit_cards_.begin();
iter != credit_cards_.end(); ++iter) {
const FormGroup* credit_card = *iter;
if (!credit_card) {
@@ -250,9 +314,11 @@ PersonalDataManager::PersonalDataManager(Profile* profile)
: profile_(profile),
is_initialized_(false),
is_data_loaded_(false),
- pending_query_handle_(0),
+ pending_profiles_query_(0),
+ pending_creditcards_query_(0),
observer_(NULL) {
LoadProfiles();
+ LoadCreditCards();
}
void PersonalDataManager::InitializeIfNeeded() {
@@ -263,13 +329,13 @@ void PersonalDataManager::InitializeIfNeeded() {
// TODO(jhawkins): Load data.
}
-int PersonalDataManager::CreateNextUniqueID() {
+int PersonalDataManager::CreateNextUniqueID(std::set<int>* unique_ids) {
// Profile IDs MUST start at 1 to allow 0 as an error value when reading
// the ID from the WebDB (see LoadData()).
int id = 1;
- while (unique_ids_.count(id) != 0)
+ while (unique_ids->count(id) != 0)
++id;
- unique_ids_.insert(id);
+ unique_ids->insert(id);
return id;
}
@@ -307,20 +373,71 @@ void PersonalDataManager::LoadProfiles() {
return;
}
- CancelPendingQuery();
+ CancelPendingQuery(&pending_profiles_query_);
+
+ pending_profiles_query_ = web_data_service->GetAutoFillProfiles(this);
+}
+
+void PersonalDataManager::LoadCreditCards() {
+ WebDataService* web_data_service =
+ profile_->GetWebDataService(Profile::EXPLICIT_ACCESS);
+ if (!web_data_service) {
+ NOTREACHED();
+ return;
+ }
+
+ CancelPendingQuery(&pending_creditcards_query_);
- pending_query_handle_ = web_data_service->GetAutoFillProfiles(this);
+ pending_creditcards_query_ = web_data_service->GetCreditCards(this);
+}
+
+void PersonalDataManager::ReceiveLoadedProfiles(WebDataService::Handle h,
+ const WDTypedResult* result) {
+ DCHECK_EQ(pending_profiles_query_, h);
+ pending_profiles_query_ = 0;
+
+ unique_profile_ids_.clear();
+ profiles_.reset();
+
+ const WDResult<std::vector<AutoFillProfile*> >* r =
+ static_cast<const WDResult<std::vector<AutoFillProfile*> >*>(result);
+
+ std::vector<AutoFillProfile*> profiles = r->GetValue();
+ for (std::vector<AutoFillProfile*>::iterator iter = profiles.begin();
+ iter != profiles.end(); ++iter) {
+ unique_profile_ids_.insert((*iter)->unique_id());
+ profiles_.push_back(*iter);
+ }
+}
+
+void PersonalDataManager::ReceiveLoadedCreditCards(
+ WebDataService::Handle h, const WDTypedResult* result) {
+ DCHECK_EQ(pending_creditcards_query_, h);
+ pending_creditcards_query_ = 0;
+
+ unique_creditcard_ids_.clear();
+ credit_cards_.reset();
+
+ const WDResult<std::vector<CreditCard*> >* r =
+ static_cast<const WDResult<std::vector<CreditCard*> >*>(result);
+
+ std::vector<CreditCard*> credit_cards = r->GetValue();
+ for (std::vector<CreditCard*>::iterator iter = credit_cards.begin();
+ iter != credit_cards.end(); ++iter) {
+ unique_creditcard_ids_.insert((*iter)->unique_id());
+ credit_cards_.push_back(*iter);
+ }
}
-void PersonalDataManager::CancelPendingQuery() {
- if (pending_query_handle_) {
+void PersonalDataManager::CancelPendingQuery(WebDataService::Handle* handle) {
+ if (*handle) {
WebDataService* web_data_service =
profile_->GetWebDataService(Profile::EXPLICIT_ACCESS);
if (!web_data_service) {
NOTREACHED();
return;
}
- web_data_service->CancelRequest(pending_query_handle_);
+ web_data_service->CancelRequest(*handle);
}
- pending_query_handle_ = 0;
+ *handle = 0;
}
diff --git a/chrome/browser/autofill/personal_data_manager.h b/chrome/browser/autofill/personal_data_manager.h
index 5821a2a..4f6ed7b 100644
--- a/chrome/browser/autofill/personal_data_manager.h
+++ b/chrome/browser/autofill/personal_data_manager.h
@@ -58,9 +58,15 @@ class PersonalDataManager : public WebDataServiceConsumer {
AutoFillManager* autofill_manager);
// Sets |profiles_| to the contents of |profiles| and updates the web database
- // by adding, updating and removing profiles.
+ // by adding, updating and removing profiles. Sets the unique ID of
+ // newly-added profiles.
void SetProfiles(std::vector<AutoFillProfile>* profiles);
+ // Sets |credit_cards_| to the contents of |credit_cards| and updates the web
+ // database by adding, updating and removing credit cards. Sets the unique
+ // ID of newly-added profiles.
+ void SetCreditCards(std::vector<CreditCard>* credit_cards);
+
// Gets the possible field types for the given text, determined by matching
// the text with all known personal information and returning matching types.
void GetPossibleFieldTypes(const string16& text,
@@ -72,9 +78,11 @@ class PersonalDataManager : public WebDataServiceConsumer {
// Returns whether the personal data has been loaded from the web database.
bool IsDataLoaded() const { return is_data_loaded_; }
- // This PersonalDataManager owns these profiles. Their lifetime is until the
- // web database is updated with new profile information.
+ // This PersonalDataManager owns these profiles and credit cards. Their
+ // lifetime is until the web database is updated with new profile and credit
+ // card information, respectively.
const std::vector<AutoFillProfile*>& profiles() { return profiles_.get(); }
+ const std::vector<CreditCard*>& credit_cards() { return credit_cards_.get(); }
private:
// Make sure that only Profile and the PersonalDataManager tests can create an
@@ -93,7 +101,7 @@ class PersonalDataManager : public WebDataServiceConsumer {
void InitializeIfNeeded();
// This will create and reserve a new unique ID for a profile.
- int CreateNextUniqueID();
+ int CreateNextUniqueID(std::set<int>* unique_ids);
// Parses value to extract the components of a phone number and adds them to
// profile.
@@ -108,8 +116,22 @@ class PersonalDataManager : public WebDataServiceConsumer {
// Loads the saved profiles from the web database.
void LoadProfiles();
- // Cancels a pending query to the web database.
- void CancelPendingQuery();
+ // Loads the saved credit cards from the web database.
+ void LoadCreditCards();
+
+ // Receives the loaded profiles from the web data service and stores them in
+ // |credit_cards_|.
+ void ReceiveLoadedProfiles(WebDataService::Handle h,
+ const WDTypedResult* result);
+
+ // Receives the loaded credit cards from the web data service and stores them
+ // in |credit_cards_|.
+ void ReceiveLoadedCreditCards(WebDataService::Handle h,
+ const WDTypedResult* result);
+
+ // Cancels a pending query to the web database. |handle| is a pointer to the
+ // query handle.
+ void CancelPendingQuery(WebDataService::Handle* handle);
// The profile hosting this PersonalDataManager.
Profile* profile_;
@@ -120,14 +142,19 @@ class PersonalDataManager : public WebDataServiceConsumer {
// True if personal data has been loaded from the web database.
bool is_data_loaded_;
- // The set of already created unique IDs, used to create a new unique ID.
- std::set<int> unique_ids_;
+ // The set of already created unique profile IDs, used to create a new unique
+ // profile ID.
+ std::set<int> unique_profile_ids_;
+
+ // The set of already created unique credit card IDs, used to create a new
+ // unique credit card ID.
+ std::set<int> unique_creditcard_ids_;
// The loaded profiles.
ScopedVector<AutoFillProfile> profiles_;
// The loaded credit cards.
- ScopedVector<FormGroup> credit_cards_;
+ ScopedVector<CreditCard> credit_cards_;
// The profile that is imported from a web form by ImportFormData.
scoped_ptr<AutoFillProfile> imported_profile_;
@@ -141,8 +168,10 @@ class PersonalDataManager : public WebDataServiceConsumer {
// When the manager makes a request from WebDataService, the database
// is queried on another thread, we record the query handle until we
- // get called back.
- WebDataService::Handle pending_query_handle_;
+ // get called back. We store handles for both profile and credit card queries
+ // so they can be loaded at the same time.
+ WebDataService::Handle pending_profiles_query_;
+ WebDataService::Handle pending_creditcards_query_;
// The observer. This can be NULL.
Observer* observer_;
diff --git a/chrome/browser/autofill/personal_data_manager_unittest.cc b/chrome/browser/autofill/personal_data_manager_unittest.cc
index 5bcbb08..db7e070 100644
--- a/chrome/browser/autofill/personal_data_manager_unittest.cc
+++ b/chrome/browser/autofill/personal_data_manager_unittest.cc
@@ -82,6 +82,27 @@ class PersonalDataManagerTest : public testing::Test {
profile->SetInfo(AutoFillType(PHONE_FAX_NUMBER), ASCIIToUTF16(fax));
}
+ static void SetCreditCardInfo(CreditCard* credit_card,
+ const char* label, const char* name_on_card, const char* type,
+ const char* card_number, const char* expiration_month,
+ const char* expiration_year, const char* verification_code,
+ const char* billing_address, const char* shipping_address) {
+ credit_card->set_label(ASCIIToUTF16(label));
+ credit_card->SetInfo(AutoFillType(CREDIT_CARD_NAME),
+ ASCIIToUTF16(name_on_card));
+ credit_card->SetInfo(AutoFillType(CREDIT_CARD_TYPE), ASCIIToUTF16(type));
+ credit_card->SetInfo(AutoFillType(CREDIT_CARD_NUMBER),
+ ASCIIToUTF16(card_number));
+ credit_card->SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH),
+ ASCIIToUTF16(expiration_month));
+ credit_card->SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR),
+ ASCIIToUTF16(expiration_year));
+ credit_card->SetInfo(AutoFillType(CREDIT_CARD_VERIFICATION_CODE),
+ ASCIIToUTF16(verification_code));
+ credit_card->set_billing_address(ASCIIToUTF16(billing_address));
+ credit_card->set_shipping_address(ASCIIToUTF16(shipping_address));
+ }
+
MessageLoopForUI message_loop_;
ChromeThread ui_thread_;
ChromeThread db_thread_;
@@ -92,7 +113,7 @@ class PersonalDataManagerTest : public testing::Test {
PersonalDataLoadedObserverMock personal_data_observer_;
};
-// TODO(jhawkins): Test SaveProfiles w/out a WebDataService in the profile.
+// TODO(jhawkins): Test SetProfiles w/out a WebDataService in the profile.
TEST_F(PersonalDataManagerTest, SetProfiles) {
AutoFillProfile profile0(string16(), 0);
SetProfileInfo(&profile0, "Billing", "Marion", "Mitchell", "Morrison",
@@ -174,3 +195,83 @@ TEST_F(PersonalDataManagerTest, SetProfiles) {
EXPECT_EQ(profile0, *results3.at(0));
EXPECT_EQ(profile2, *results3.at(1));
}
+
+// TODO(jhawkins): Test SetCreditCards w/out a WebDataService in the profile.
+TEST_F(PersonalDataManagerTest, SetCreditCards) {
+ CreditCard creditcard0(string16(), 0);
+ SetCreditCardInfo(&creditcard0, "Corporate", "John Dillinger", "Visa",
+ "123456789012", "01", "2010", "123", "Chicago", "Indianapolis");
+
+ CreditCard creditcard1(string16(), 0);
+ SetCreditCardInfo(&creditcard1, "Personal", "Bonnie Parker", "Mastercard",
+ "098765432109", "12", "2012", "987", "Dallas", "");
+
+ CreditCard creditcard2(string16(), 0);
+ SetCreditCardInfo(&creditcard2, "Savings", "Clyde Barrow", "American Express",
+ "777666888555", "04", "2015", "445", "Home", "Farm");
+
+ // This will verify that the web database has been loaded and the notification
+ // sent out.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ // The message loop will exit when the mock observer is notified.
+ MessageLoop::current()->Run();
+
+ // Add the three test credit cards to the database.
+ std::vector<CreditCard> update;
+ update.push_back(creditcard0);
+ update.push_back(creditcard1);
+ personal_data_->SetCreditCards(&update);
+
+ // The PersonalDataManager will update the unique IDs when saving the
+ // credit cards, so we have to update the expectations.
+ creditcard0.set_unique_id(update[0].unique_id());
+ creditcard1.set_unique_id(update[1].unique_id());
+
+ const std::vector<CreditCard*>& results1 = personal_data_->credit_cards();
+ ASSERT_EQ(2U, results1.size());
+ EXPECT_EQ(creditcard0, *results1.at(0));
+ EXPECT_EQ(creditcard1, *results1.at(1));
+
+ // Three operations in one:
+ // - Update creditcard0
+ // - Remove creditcard1
+ // - Add creditcard2
+ creditcard0.SetInfo(AutoFillType(CREDIT_CARD_NAME), ASCIIToUTF16("Joe"));
+ update.clear();
+ update.push_back(creditcard0);
+ update.push_back(creditcard2);
+ personal_data_->SetCreditCards(&update);
+
+ // Set the expected unique ID for creditcard2.
+ creditcard2.set_unique_id(update[1].unique_id());
+
+ // CreditCard IDs are re-used, so the third credit card to be added will have
+ // a unique ID that matches the old unique ID of the removed creditcard1, even
+ // though that ID has already been used.
+ const std::vector<CreditCard*>& results2 = personal_data_->credit_cards();
+ ASSERT_EQ(2U, results2.size());
+ EXPECT_EQ(creditcard0, *results2.at(0));
+ EXPECT_EQ(creditcard2, *results2.at(1));
+ EXPECT_EQ(creditcard2.unique_id(), creditcard1.unique_id());
+
+ // Reset the PersonalDataManager. This tests that the personal data was saved
+ // to the web database, and that we can load the credit cards from the web
+ // database.
+ ResetPersonalDataManager();
+
+ // This will verify that the web database has been loaded and the notification
+ // sent out.
+ EXPECT_CALL(personal_data_observer_,
+ OnPersonalDataLoaded()).WillOnce(QuitUIMessageLoop());
+
+ // The message loop will exit when the PersonalDataLoadedObserver is notified.
+ MessageLoop::current()->Run();
+
+ // Verify that we've loaded the credit cards from the web database.
+ const std::vector<CreditCard*>& results3 = personal_data_->credit_cards();
+ ASSERT_EQ(2U, results3.size());
+ EXPECT_EQ(creditcard0, *results3.at(0));
+ EXPECT_EQ(creditcard2, *results3.at(1));
+}
diff --git a/chrome/browser/webdata/web_data_service.cc b/chrome/browser/webdata/web_data_service.cc
index b630a91..197b859 100644
--- a/chrome/browser/webdata/web_data_service.cc
+++ b/chrome/browser/webdata/web_data_service.cc
@@ -8,6 +8,7 @@
#include "base/task.h"
#include "base/thread.h"
#include "chrome/browser/autofill/autofill_profile.h"
+#include "chrome/browser/autofill/credit_card.h"
#include "chrome/browser/webdata/autofill_change.h"
#include "chrome/browser/webdata/autofill_entry.h"
#include "chrome/browser/webdata/web_database.h"
@@ -170,27 +171,56 @@ void WebDataService::RemoveAutoFillProfile(int profile_id) {
request));
}
-WebDataService::Handle WebDataService::GetAutoFillProfileForLabel(
- const string16& label, WebDataServiceConsumer* consumer) {
+WebDataService::Handle WebDataService::GetAutoFillProfiles(
+ WebDataServiceConsumer* consumer) {
WebDataRequest* request =
new WebDataRequest(this, GetNextRequestHandle(), consumer);
RegisterRequest(request);
ScheduleTask(
NewRunnableMethod(this,
- &WebDataService::GetAutoFillProfileForLabelImpl,
- request,
- label));
+ &WebDataService::GetAutoFillProfilesImpl,
+ request));
return request->GetHandle();
}
-WebDataService::Handle WebDataService::GetAutoFillProfiles(
+void WebDataService::AddCreditCard(const CreditCard& creditcard) {
+ GenericRequest<CreditCard>* request =
+ new GenericRequest<CreditCard>(
+ this, GetNextRequestHandle(), NULL, creditcard);
+ RegisterRequest(request);
+ ScheduleTask(NewRunnableMethod(this,
+ &WebDataService::AddCreditCardImpl,
+ request));
+}
+
+void WebDataService::UpdateCreditCard(const CreditCard& creditcard) {
+ GenericRequest<CreditCard>* request =
+ new GenericRequest<CreditCard>(
+ this, GetNextRequestHandle(), NULL, creditcard);
+ RegisterRequest(request);
+ ScheduleTask(NewRunnableMethod(this,
+ &WebDataService::UpdateCreditCardImpl,
+ request));
+}
+
+void WebDataService::RemoveCreditCard(int creditcard_id) {
+ GenericRequest<int>* request =
+ new GenericRequest<int>(
+ this, GetNextRequestHandle(), NULL, creditcard_id);
+ RegisterRequest(request);
+ ScheduleTask(NewRunnableMethod(this,
+ &WebDataService::RemoveCreditCardImpl,
+ request));
+}
+
+WebDataService::Handle WebDataService::GetCreditCards(
WebDataServiceConsumer* consumer) {
WebDataRequest* request =
new WebDataRequest(this, GetNextRequestHandle(), consumer);
RegisterRequest(request);
ScheduleTask(
NewRunnableMethod(this,
- &WebDataService::GetAutoFillProfilesImpl,
+ &WebDataService::GetCreditCardsImpl,
request));
return request->GetHandle();
}
@@ -768,27 +798,62 @@ void WebDataService::RemoveAutoFillProfileImpl(
request->RequestComplete();
}
-void WebDataService::GetAutoFillProfileForLabelImpl(WebDataRequest* request,
- const string16& label) {
+void WebDataService::GetAutoFillProfilesImpl(WebDataRequest* request) {
InitializeDatabaseIfNecessary();
if (db_ && !request->IsCancelled()) {
- AutoFillProfile* profile;
- db_->GetAutoFillProfileForLabel(label, &profile);
+ std::vector<AutoFillProfile*> profiles;
+ db_->GetAutoFillProfiles(&profiles);
request->SetResult(
- new WDResult<AutoFillProfile>(AUTOFILL_PROFILE_RESULT, *profile));
- delete profile;
+ new WDResult<std::vector<AutoFillProfile*> >(AUTOFILL_PROFILES_RESULT,
+ profiles));
}
request->RequestComplete();
}
-void WebDataService::GetAutoFillProfilesImpl(WebDataRequest* request) {
+void WebDataService::AddCreditCardImpl(
+ GenericRequest<CreditCard>* request) {
InitializeDatabaseIfNecessary();
if (db_ && !request->IsCancelled()) {
- std::vector<AutoFillProfile*> profiles;
- db_->GetAutoFillProfiles(&profiles);
+ const CreditCard& creditcard = request->GetArgument();
+ if (!db_->AddCreditCard(creditcard))
+ NOTREACHED();
+ ScheduleCommit();
+ }
+ request->RequestComplete();
+}
+
+void WebDataService::UpdateCreditCardImpl(
+ GenericRequest<CreditCard>* request) {
+ InitializeDatabaseIfNecessary();
+ if (db_ && !request->IsCancelled()) {
+ const CreditCard& creditcard = request->GetArgument();
+ if (!db_->UpdateCreditCard(creditcard))
+ NOTREACHED();
+ ScheduleCommit();
+ }
+ request->RequestComplete();
+}
+
+void WebDataService::RemoveCreditCardImpl(
+ GenericRequest<int>* request) {
+ InitializeDatabaseIfNecessary();
+ if (db_ && !request->IsCancelled()) {
+ int creditcard_id = request->GetArgument();
+ if (!db_->RemoveCreditCard(creditcard_id))
+ NOTREACHED();
+ ScheduleCommit();
+ }
+ request->RequestComplete();
+}
+
+void WebDataService::GetCreditCardsImpl(WebDataRequest* request) {
+ InitializeDatabaseIfNecessary();
+ if (db_ && !request->IsCancelled()) {
+ std::vector<CreditCard*> creditcards;
+ db_->GetCreditCards(&creditcards);
request->SetResult(
- new WDResult<std::vector<AutoFillProfile*> >(AUTOFILL_PROFILES_RESULT,
- profiles));
+ new WDResult<std::vector<CreditCard*> >(AUTOFILL_CREDITCARDS_RESULT,
+ creditcards));
}
request->RequestComplete();
}
diff --git a/chrome/browser/webdata/web_data_service.h b/chrome/browser/webdata/web_data_service.h
index ff356e0..c81061d 100644
--- a/chrome/browser/webdata/web_data_service.h
+++ b/chrome/browser/webdata/web_data_service.h
@@ -19,6 +19,7 @@
class AutofillChange;
class AutoFillProfile;
+class CreditCard;
#if defined(OS_WIN)
struct IE7PasswordInfo;
#endif
@@ -54,18 +55,20 @@ struct PasswordForm;
// Result types
//
typedef enum {
- BOOL_RESULT = 1, // WDResult<bool>
- KEYWORDS_RESULT, // WDResult<WDKeywordsResult>
- INT64_RESULT, // WDResult<int64>
- PASSWORD_RESULT, // WDResult<std::vector<PasswordForm*>>
+ BOOL_RESULT = 1, // WDResult<bool>
+ KEYWORDS_RESULT, // WDResult<WDKeywordsResult>
+ INT64_RESULT, // WDResult<int64>
+ PASSWORD_RESULT, // WDResult<std::vector<PasswordForm*>>
#if defined(OS_WIN)
- PASSWORD_IE7_RESULT, // WDResult<IE7PasswordInfo>
+ PASSWORD_IE7_RESULT, // WDResult<IE7PasswordInfo>
#endif
- WEB_APP_IMAGES, // WDResult<WDAppImagesResult>
- AUTOFILL_VALUE_RESULT, // WDResult<std::vector<string16>>
- AUTOFILL_CHANGES, // WDResult<std::vector<AutofillChange>>
- AUTOFILL_PROFILE_RESULT, // WDResult<AutoFillProfile>
- AUTOFILL_PROFILES_RESULT // WDResult<std::vector<AutoFillProfile*>>
+ WEB_APP_IMAGES, // WDResult<WDAppImagesResult>
+ AUTOFILL_VALUE_RESULT, // WDResult<std::vector<string16>>
+ AUTOFILL_CHANGES, // WDResult<std::vector<AutofillChange>>
+ AUTOFILL_PROFILE_RESULT, // WDResult<AutoFillProfile>
+ AUTOFILL_PROFILES_RESULT, // WDResult<std::vector<AutoFillProfile*>>
+ AUTOFILL_CREDITCARD_RESULT, // WDResult<CreditCard>
+ AUTOFILL_CREDITCARDS_RESULT // WDResult<std::vector<CreditCard*>>
} WDResultType;
typedef std::vector<AutofillChange> AutofillChangeList;
@@ -418,18 +421,28 @@ class WebDataService
// |profile_id| is the unique ID of the profile to remove.
void RemoveAutoFillProfile(int profile_id);
- // Initiates the request for an AutoFill profile with label |label|. The
- // method OnWebDataServiceRequestDone of |consumer| gets called back when the
- // request is finished, with the profile included in the argument |result|.
- Handle GetAutoFillProfileForLabel(const string16& label,
- WebDataServiceConsumer* consumer);
-
// Initiates the request for all AutoFill profiles. The method
// OnWebDataServiceRequestDone of |consumer| gets called when the request is
// finished, with the profiles included in the argument |result|. The
// consumer owns the profiles.
Handle GetAutoFillProfiles(WebDataServiceConsumer* consumer);
+ // Schedules a task to add credit card to the web database.
+ void AddCreditCard(const CreditCard& creditcard);
+
+ // Schedules a task to update credit card in the web database.
+ void UpdateCreditCard(const CreditCard& creditcard);
+
+ // Schedules a task to remove a credit card from the web database.
+ // |creditcard_id| is the unique ID of the credit card to remove.
+ void RemoveCreditCard(int creditcard_id);
+
+ // Initiates the request for all credit cards. The method
+ // OnWebDataServiceRequestDone of |consumer| gets called when the request is
+ // finished, with the credit cards included in the argument |result|. The
+ // consumer owns the credit cards.
+ Handle GetCreditCards(WebDataServiceConsumer* consumer);
+
// Testing
#ifdef UNIT_TEST
void set_failed_init(bool value) { failed_init_ = value; }
@@ -531,6 +544,12 @@ class WebDataService
void GetAutoFillProfileForLabelImpl(WebDataRequest* request,
const string16& label);
void GetAutoFillProfilesImpl(WebDataRequest* request);
+ void AddCreditCardImpl(GenericRequest<CreditCard>* request);
+ void UpdateCreditCardImpl(GenericRequest<CreditCard>* request);
+ void RemoveCreditCardImpl(GenericRequest<int>* request);
+ void GetCreditCardForLabelImpl(WebDataRequest* request,
+ const string16& label);
+ void GetCreditCardsImpl(WebDataRequest* request);
//////////////////////////////////////////////////////////////////////////////
//
diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc
index 019c7d3..3bc0438 100644
--- a/chrome/browser/webdata/web_database.cc
+++ b/chrome/browser/webdata/web_database.cc
@@ -17,6 +17,7 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/autofill/autofill_profile.h"
#include "chrome/browser/autofill/autofill_type.h"
+#include "chrome/browser/autofill/credit_card.h"
#include "chrome/browser/diagnostics/sqlite_diagnostics.h"
#include "chrome/browser/history/history_database.h"
#include "chrome/browser/webdata/autofill_change.h"
@@ -111,6 +112,22 @@ using webkit_glue::PasswordForm;
// phone
// fax
//
+// credit_cards This table contains credit card data added by the user
+// with the AutoFill dialog. Most of the columns are
+// standard entries in a credit card form.
+//
+// label The label of the credit card. Presented to the user
+// when selecting credit cards.
+// unique_id The unique ID of this credit card.
+// name_on_card
+// type
+// card_number
+// expiration_month
+// expiration_year
+// verification_code The CVC/CVV/CVV2 card security code.
+// billing_address A foreign key into the autofill_profiles table.
+// shipping_address A foreign key into the autofill_profiles table.
+//
// web_app_icons
// url URL of the web app.
// width Width of the image.
@@ -198,7 +215,8 @@ sql::InitStatus WebDatabase::Init(const FilePath& db_name) {
// Initialize the tables.
if (!InitKeywordsTable() || !InitLoginsTable() || !InitWebAppIconsTable() ||
!InitWebAppsTable() || !InitAutofillTable() ||
- !InitAutofillDatesTable() || !InitAutoFillProfilesTable()) {
+ !InitAutofillDatesTable() || !InitAutoFillProfilesTable() ||
+ !InitCreditCardsTable()) {
LOG(WARNING) << "Unable to initialize the web database.";
return sql::INIT_FAILURE;
}
@@ -445,6 +463,31 @@ bool WebDatabase::InitAutoFillProfilesTable() {
return true;
}
+bool WebDatabase::InitCreditCardsTable() {
+ if (!db_.DoesTableExist("credit_cards")) {
+ if (!db_.Execute("CREATE TABLE credit_cards ( "
+ "label VARCHAR, "
+ "unique_id INTEGER PRIMARY KEY, "
+ "name_on_card VARCHAR, "
+ "type VARCHAR, "
+ "card_number VARCHAR, "
+ "expiration_month INTEGER, "
+ "expiration_year INTEGER, "
+ "verification_code VARCHAR, "
+ "billing_address VARCHAR, "
+ "shipping_address VARCHAR)")) {
+ NOTREACHED();
+ return false;
+ }
+ if (!db_.Execute("CREATE INDEX credit_cards_label_index "
+ "ON credit_cards (label)")) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
bool WebDatabase::InitWebAppIconsTable() {
if (!db_.DoesTableExist("web_app_icons")) {
if (!db_.Execute("CREATE TABLE web_app_icons ("
@@ -1331,6 +1374,137 @@ bool WebDatabase::RemoveAutoFillProfile(int profile_id) {
return s.Run();
}
+static void BindCreditCardToStatement(const CreditCard& creditcard,
+ sql::Statement* s) {
+ s->BindString(0, UTF16ToUTF8(creditcard.Label()));
+ s->BindInt(1, creditcard.unique_id());
+
+ string16 text = creditcard.GetFieldText(AutoFillType(CREDIT_CARD_NAME));
+ s->BindString(2, UTF16ToUTF8(text));
+ text = creditcard.GetFieldText(AutoFillType(CREDIT_CARD_TYPE));
+ s->BindString(3, UTF16ToUTF8(text));
+ text = creditcard.GetFieldText(AutoFillType(CREDIT_CARD_NUMBER));
+ s->BindString(4, UTF16ToUTF8(text));
+ text = creditcard.GetFieldText(AutoFillType(CREDIT_CARD_EXP_MONTH));
+ s->BindString(5, UTF16ToUTF8(text));
+ text = creditcard.GetFieldText(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR));
+ s->BindString(6, UTF16ToUTF8(text));
+ text = creditcard.GetFieldText(AutoFillType(CREDIT_CARD_VERIFICATION_CODE));
+ s->BindString(7, UTF16ToUTF8(text));
+ s->BindString(8, UTF16ToUTF8(creditcard.billing_address()));
+ s->BindString(9, UTF16ToUTF8(creditcard.shipping_address()));
+}
+
+bool WebDatabase::AddCreditCard(const CreditCard& creditcard) {
+ sql::Statement s(db_.GetUniqueStatement(
+ "INSERT INTO credit_cards"
+ "(label, unique_id, name_on_card, type, card_number, expiration_month,"
+ " expiration_year, verification_code, billing_address, shipping_address)"
+ "VALUES (?,?,?,?,?,?,?,?,?,?)"));
+ if (!s) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+
+ BindCreditCardToStatement(creditcard, &s);
+
+ if (!s.Run()) {
+ NOTREACHED();
+ return false;
+ }
+
+ return s.Succeeded();
+}
+
+static CreditCard* CreditCardFromStatement(const sql::Statement& s) {
+ CreditCard* creditcard = new CreditCard(
+ ASCIIToUTF16(s.ColumnString(0)), s.ColumnInt(1));
+ creditcard->SetInfo(AutoFillType(CREDIT_CARD_NAME),
+ ASCIIToUTF16(s.ColumnString(2)));
+ creditcard->SetInfo(AutoFillType(CREDIT_CARD_TYPE),
+ ASCIIToUTF16(s.ColumnString(3)));
+ creditcard->SetInfo(AutoFillType(CREDIT_CARD_NUMBER),
+ ASCIIToUTF16(s.ColumnString(4)));
+ creditcard->SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH),
+ ASCIIToUTF16(s.ColumnString(5)));
+ creditcard->SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR),
+ ASCIIToUTF16(s.ColumnString(6)));
+ creditcard->SetInfo(AutoFillType(CREDIT_CARD_VERIFICATION_CODE),
+ ASCIIToUTF16(s.ColumnString(7)));
+ creditcard->set_billing_address(ASCIIToUTF16(s.ColumnString(8)));
+ creditcard->set_shipping_address(ASCIIToUTF16(s.ColumnString(9)));
+
+ return creditcard;
+}
+
+bool WebDatabase::GetCreditCardForLabel(const string16& label,
+ CreditCard** creditcard) {
+ DCHECK(creditcard);
+ sql::Statement s(db_.GetUniqueStatement(
+ "SELECT * FROM credit_cards "
+ "WHERE label = ?"));
+ if (!s) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+
+ s.BindString(0, UTF16ToUTF8(label));
+ if (!s.Step())
+ return false;
+
+ *creditcard = CreditCardFromStatement(s);
+
+ return s.Succeeded();
+}
+
+bool WebDatabase::GetCreditCards(
+ std::vector<CreditCard*>* creditcards) {
+ DCHECK(creditcards);
+ creditcards->clear();
+
+ sql::Statement s(db_.GetUniqueStatement("SELECT * FROM credit_cards"));
+ if (!s) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+
+ while (s.Step())
+ creditcards->push_back(CreditCardFromStatement(s));
+
+ return s.Succeeded();
+}
+
+bool WebDatabase::UpdateCreditCard(const CreditCard& creditcard) {
+ DCHECK(creditcard.unique_id());
+ sql::Statement s(db_.GetUniqueStatement(
+ "UPDATE credit_cards "
+ "SET label=?, unique_id=?, name_on_card=?, type=?, card_number=?, "
+ " expiration_month=?, expiration_year=?, verification_code=?, "
+ " billing_address=?, shipping_address=? "
+ "WHERE unique_id=?"));
+ if (!s) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+
+ BindCreditCardToStatement(creditcard, &s);
+ s.BindInt(10, creditcard.unique_id());
+ return s.Run();
+}
+
+bool WebDatabase::RemoveCreditCard(int creditcard_id) {
+ DCHECK_NE(0, creditcard_id);
+ sql::Statement s(db_.GetUniqueStatement(
+ "DELETE FROM credit_cards WHERE unique_id = ?"));
+ if (!s) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+
+ s.BindInt(0, creditcard_id);
+ return s.Run();
+}
+
bool WebDatabase::AddToCountOfFormElement(int64 pair_id,
int delta,
bool* was_removed) {
diff --git a/chrome/browser/webdata/web_database.h b/chrome/browser/webdata/web_database.h
index 2820beb1..d8179b1 100644
--- a/chrome/browser/webdata/web_database.h
+++ b/chrome/browser/webdata/web_database.h
@@ -17,6 +17,7 @@
class AutofillChange;
class AutoFillProfile;
+class CreditCard;
class FilePath;
namespace base {
@@ -215,6 +216,23 @@ class WebDatabase {
// Retrieves all profiles in the database. Caller owns the returned profiles.
bool GetAutoFillProfiles(std::vector<AutoFillProfile*>* profiles);
+ // Records a single credit card in the credit_cards table.
+ bool AddCreditCard(const CreditCard& creditcard);
+
+ // Updates the database values for the specified profile.
+ bool UpdateCreditCard(const CreditCard& profile);
+
+ // Removes a row from the autofill_profiles table. |profile_id| is the
+ // unique ID of the profile to remove.
+ bool RemoveCreditCard(int profile_id);
+
+ // Retrieves a profile with label |label|. The caller owns |profile|.
+ bool GetCreditCardForLabel(const string16& label,
+ CreditCard** profile);
+
+ // Retrieves all profiles in the database. Caller owns the returned profiles.
+ bool GetCreditCards(std::vector<CreditCard*>* profiles);
+
//////////////////////////////////////////////////////////////////////////////
//
// Web Apps
@@ -255,6 +273,7 @@ class WebDatabase {
bool InitAutofillTable();
bool InitAutofillDatesTable();
bool InitAutoFillProfilesTable();
+ bool InitCreditCardsTable();
bool InitWebAppIconsTable();
bool InitWebAppsTable();
diff --git a/chrome/browser/webdata/web_database_unittest.cc b/chrome/browser/webdata/web_database_unittest.cc
index c0f340d..1b950c8 100644
--- a/chrome/browser/webdata/web_database_unittest.cc
+++ b/chrome/browser/webdata/web_database_unittest.cc
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "chrome/browser/autofill/autofill_profile.h"
#include "chrome/browser/autofill/autofill_type.h"
+#include "chrome/browser/autofill/credit_card.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/webdata/autofill_change.h"
#include "chrome/browser/webdata/autofill_entry.h"
@@ -900,8 +901,7 @@ TEST_F(WebDatabaseTest, AutoFillProfile) {
// Get the 'Home' profile.
AutoFillProfile* db_profile;
- EXPECT_TRUE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Home"),
- &db_profile));
+ ASSERT_TRUE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Home"), &db_profile));
EXPECT_EQ(home_profile, *db_profile);
delete db_profile;
@@ -915,7 +915,7 @@ TEST_F(WebDatabaseTest, AutoFillProfile) {
ASCIIToUTF16("suite 3"));
EXPECT_TRUE(db.AddAutoFillProfile(billing_profile));
- EXPECT_TRUE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Billing"),
+ ASSERT_TRUE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Billing"),
&db_profile));
EXPECT_EQ(billing_profile, *db_profile);
delete db_profile;
@@ -923,7 +923,7 @@ TEST_F(WebDatabaseTest, AutoFillProfile) {
// Update the 'Billing' profile.
billing_profile.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("Jane"));
EXPECT_TRUE(db.UpdateAutoFillProfile(billing_profile));
- EXPECT_TRUE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Billing"),
+ ASSERT_TRUE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Billing"),
&db_profile));
EXPECT_EQ(billing_profile, *db_profile);
delete db_profile;
@@ -933,3 +933,70 @@ TEST_F(WebDatabaseTest, AutoFillProfile) {
EXPECT_FALSE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Billing"),
&db_profile));
}
+
+TEST_F(WebDatabaseTest, CreditCard) {
+ WebDatabase db;
+
+ ASSERT_EQ(sql::INIT_OK, db.Init(file_));
+
+ // Add a 'Work' credit card.
+ CreditCard work_creditcard(ASCIIToUTF16("Work"), 13);
+ work_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NAME),
+ ASCIIToUTF16("Jack Torrance"));
+ work_creditcard.SetInfo(AutoFillType(CREDIT_CARD_TYPE),
+ ASCIIToUTF16("Visa"));
+ work_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NUMBER),
+ ASCIIToUTF16("1234567890123456"));
+ work_creditcard.SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH),
+ ASCIIToUTF16("04"));
+ work_creditcard.SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR),
+ ASCIIToUTF16("2013"));
+ work_creditcard.SetInfo(AutoFillType(CREDIT_CARD_VERIFICATION_CODE),
+ ASCIIToUTF16("987"));
+ work_creditcard.set_billing_address(ASCIIToUTF16("Overlook Hotel"));
+ work_creditcard.set_shipping_address(ASCIIToUTF16("Timberline Lodge"));
+
+ EXPECT_TRUE(db.AddCreditCard(work_creditcard));
+
+ // Get the 'Work' credit card.
+ CreditCard* db_creditcard;
+ ASSERT_TRUE(db.GetCreditCardForLabel(ASCIIToUTF16("Work"), &db_creditcard));
+ EXPECT_EQ(work_creditcard, *db_creditcard);
+ delete db_creditcard;
+
+ // Add a 'Target' profile.
+ CreditCard target_creditcard(ASCIIToUTF16("Target"), 7);
+ target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NAME),
+ ASCIIToUTF16("Jack Torrance"));
+ target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_TYPE),
+ ASCIIToUTF16("Mastercard"));
+ target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NUMBER),
+ ASCIIToUTF16("1111222233334444"));
+ target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH),
+ ASCIIToUTF16("06"));
+ target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR),
+ ASCIIToUTF16("2012"));
+ target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_VERIFICATION_CODE),
+ ASCIIToUTF16("123"));
+ target_creditcard.set_billing_address(ASCIIToUTF16("Overlook Hotel"));
+ target_creditcard.set_shipping_address(string16());
+
+ EXPECT_TRUE(db.AddCreditCard(target_creditcard));
+ ASSERT_TRUE(db.GetCreditCardForLabel(ASCIIToUTF16("Target"),
+ &db_creditcard));
+ EXPECT_EQ(target_creditcard, *db_creditcard);
+ delete db_creditcard;
+
+ // Update the 'Target' profile.
+ target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NAME),
+ ASCIIToUTF16("Charles Grady"));
+ EXPECT_TRUE(db.UpdateCreditCard(target_creditcard));
+ ASSERT_TRUE(db.GetCreditCardForLabel(ASCIIToUTF16("Target"), &db_creditcard));
+ EXPECT_EQ(target_creditcard, *db_creditcard);
+ delete db_creditcard;
+
+ // Remove the 'Billing' profile.
+ EXPECT_TRUE(db.RemoveCreditCard(target_creditcard.unique_id()));
+ EXPECT_FALSE(db.GetCreditCardForLabel(ASCIIToUTF16("Target"),
+ &db_creditcard));
+}