blob: e7e6fdb3a615f4df028c61328422a120a23f677d [file] [log] [blame]
// Copyright 2017 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.
#include "components/autofill/core/browser/address_combobox_model.h"
#include <memory>
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/combobox_model_observer.h"
#include "ui/gfx/text_elider.h"
namespace autofill {
namespace {
// There's one header entry to prompt the user to select an address, and a
// separator.
int kNbHeaderEntries = 2;
} // namespace
AddressComboboxModel::AddressComboboxModel(
const PersonalDataManager& personal_data_manager,
const std::string& app_locale,
const std::string& default_selected_guid)
: app_locale_(app_locale), default_selected_guid_(default_selected_guid) {
for (const auto* profile : personal_data_manager.GetProfilesToSuggest()) {
profiles_cache_.push_back(std::make_unique<AutofillProfile>(*profile));
}
UpdateAddresses();
}
AddressComboboxModel::~AddressComboboxModel() {}
int AddressComboboxModel::GetItemCount() const {
// When there are not addresses, a special entry is shown to prompt the user
// to add addresses, but nothing else is shown, since there are no address to
// select from, and no need for a separator.
if (addresses_.size() == 0)
return 1;
// If there are addresses to choose from, but none is selected, add extra
// items for the "Select" entry and a separator.
return addresses_.size() + kNbHeaderEntries;
}
base::string16 AddressComboboxModel::GetItemAt(int index) {
DCHECK_GE(index, 0);
// A special entry is always added at index 0 and a separator at index 1.
DCHECK_LT(static_cast<size_t>(index), addresses_.size() + kNbHeaderEntries);
// Special entry when no profiles have been created yet.
if (addresses_.empty())
return l10n_util::GetStringUTF16(IDS_AUTOFILL_NO_SAVED_ADDRESS);
// Always show the "Select" entry at the top, default selection position.
if (index == 0)
return l10n_util::GetStringUTF16(IDS_AUTOFILL_SELECT);
// Always show the "Select" entry at the top, default selection position.
if (index == 1)
return base::ASCIIToUTF16("---");
return addresses_[index - kNbHeaderEntries].second;
}
bool AddressComboboxModel::IsItemSeparatorAt(int index) {
// The only separator is between the "Select" entry at 0 and the first address
// at index 2. So there must be at least one address for a separator to be
// shown.
DCHECK(index <= kNbHeaderEntries || !addresses_.empty());
return index == 1;
}
int AddressComboboxModel::GetDefaultIndex() const {
if (!default_selected_guid_.empty()) {
int address_index = GetIndexOfIdentifier(default_selected_guid_);
if (address_index != -1)
return address_index;
}
return ui::ComboboxModel::GetDefaultIndex();
}
void AddressComboboxModel::AddObserver(ui::ComboboxModelObserver* observer) {
observers_.AddObserver(observer);
}
void AddressComboboxModel::RemoveObserver(ui::ComboboxModelObserver* observer) {
observers_.RemoveObserver(observer);
}
int AddressComboboxModel::AddNewProfile(const AutofillProfile& profile) {
profiles_cache_.push_back(std::make_unique<AutofillProfile>(profile));
UpdateAddresses();
DCHECK_GT(addresses_.size(), 0UL);
return addresses_.size() + kNbHeaderEntries - 1;
}
std::string AddressComboboxModel::GetItemIdentifierAt(int index) {
// The first two indices are special entries, with no addresses.
if (index < kNbHeaderEntries)
return std::string();
DCHECK_LT(static_cast<size_t>(index), addresses_.size() + kNbHeaderEntries);
return addresses_[index - kNbHeaderEntries].first;
}
int AddressComboboxModel::GetIndexOfIdentifier(
const std::string& identifier) const {
for (size_t i = 0; i < addresses_.size(); ++i) {
if (addresses_[i].first == identifier)
return i + kNbHeaderEntries;
}
return -1;
}
void AddressComboboxModel::UpdateAddresses() {
addresses_.clear();
std::vector<base::string16> labels;
// CreateDifferentiatingLabels is expecting a pointer vector and we keep
// profiles as unique_ptr.
std::vector<AutofillProfile*> profiles;
for (const auto& profile : profiles_cache_) {
profiles.push_back(profile.get());
}
AutofillProfile::CreateDifferentiatingLabels(profiles, app_locale_, &labels);
DCHECK_EQ(labels.size(), profiles_cache_.size());
for (size_t i = 0; i < profiles_cache_.size(); ++i)
addresses_.emplace_back(profiles_cache_[i]->guid(), labels[i]);
for (auto& observer : observers_) {
observer.OnComboboxModelChanged(this);
}
}
} // namespace autofill