blob: 9eb6782d35c6634c3cf92a0e3a815ba27dcba221 [file] [log] [blame]
// Copyright 2021 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_CORE_BROWSER_AUTOFILL_PROFILE_IMPORT_PROCESS_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_IMPORT_PROCESS_H_
#include <vector>
#include "base/types/id_type.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
// The id of an ongoing profile import process.
using AutofillProfileImportId =
::base::IdTypeU64<class AutofillProfileImportIdMarker>;
// Specifies the type of a profile form import.
enum class AutofillProfileImportType {
// Type is unspecified.
kImportTypeUnspecified,
// The observed profile corresponds to a new profile because there are no
// mergeable or updateable profiles.
kNewProfile,
// The imported profile is a subset of an already existing profile.
kDuplicateImport,
// The imported profile can be integrated into an already existing profile
// without any changes to settings-visible values.
kSilentUpdate,
// The imported profile changes settings-visible values which is only imported
// after explicit user confirmation.
kConfirmableMerge,
// The observed profile corresponds to a new profile because there are no
// mergeable or updateable profiles but imports are suppressed for this
// domain.
kSuppressedNewProfile,
// The observed profile resulted both in a confirmable merge and in a silent
// update.
kConfirmableMergeAndSilentUpdate,
// The observed profile resulted in one or more confirmable merges that are
// all suppressed with no additional silent updates.
kSuppressedConfirmableMerge,
// The observed profile resulted in one or more suppressed confirmable merges
// but with additional silent updates.
kSuppressedConfirmableMergeAndSilentUpdate,
kMaxValue = kSuppressedConfirmableMergeAndSilentUpdate
};
// This class holds the state associated with the import of an AutofillProfile
// observed in a form submission and should be used as the follows:
//
// * An instance is created by supplying the observed profile, all already
// existing profiles and the used locale.
//
// * Now, the import process awaits either a user decision or a
// confirmation that the user wasn't prompted at all. This confirmation is
// supplied by either calling `AcceptWithoutPrompt()`, `AcceptWithoutEdits()`,
// `AcceptWithEdits()`, `Declined()` or `Ignore()`.
//
// * Finally, `GetResultingProfiles()` should be used to get the complete set of
// resulting AutofillProfiles.
//
// The instance of this class should contain all information needed to record
// metrics once an import process is finished.
class ProfileImportProcess {
public:
ProfileImportProcess(const AutofillProfile& observed_profile,
const std::string& app_locale,
const GURL& form_source_url,
const PersonalDataManager* personal_data_manager);
ProfileImportProcess(const ProfileImportProcess&);
ProfileImportProcess& operator=(const ProfileImportProcess& other);
~ProfileImportProcess();
// Returns true if showing the prompt was initiated for this import process.
bool prompt_shown() const;
const absl::optional<AutofillProfile>& import_candidate() const {
return import_candidate_;
}
const absl::optional<AutofillProfile>& merge_candidate() const {
return merge_candidate_;
}
const std::vector<AutofillProfile>& updated_profiles() const {
return updated_profiles_;
}
const AutofillProfileImportId& import_id() const { return import_id_; }
const AutofillProfile& observed_profile() const { return observed_profile_; }
AutofillProfileImportType import_type() const { return import_type_; }
AutofillClient::SaveAddressProfileOfferUserDecision user_decision() const {
return user_decision_;
}
// Returns true if the user actively declined the save of update without
// differentiating between the actual type of decline.
// If no decision is available yet, return false.
bool UserDeclined() const;
// Returns true if the user actively accepted the save of update without
// differentiating if there have been additional edits by the user.
// If no decision is available yet, return false.
bool UserAccepted() const;
const GURL& form_source_url() const { return form_source_url_; }
// Returns a vector containing all unchanged, updated, merged and new
// profiles.
std::vector<AutofillProfile> GetResultingProfiles();
// Returns false if the import does not result in any change to the stored
// profiles. This function can only be evaluated after a decision was
// supplied. Note that this function allows for a false positive if a user
// accepts a merge, but edits the profile back to its initial state.
bool ProfilesChanged() const;
// No prompt is shown to the user.
void AcceptWithoutPrompt();
// The import is accepted by the user without additional edits.
void AcceptWithoutEdits();
// The import is accepted but only with additional edits contained in
// `edited_profile`.
void AcceptWithEdits(AutofillProfile edited_profile);
// The import was declined.
void Declined();
// The prompt was ignored.
void Ignore();
// Set the prompt as being shown.
void set_prompt_was_shown();
// Supply a user |decision| for the import process. The option
// |edited_profile| reflect user edits to the import candidate.
void SetUserDecision(
AutofillClient::SaveAddressProfileOfferUserDecision decision,
absl::optional<AutofillProfile> edited_profile = absl::nullopt);
// Records UMA metrics. Should only be called after a user decision was
// supplied.
void CollectMetrics() const;
private:
// Determines the import type of |observed_profile_| with respect to
// |existing_profiles|. Only the first profile in |existing_profiles| becomes
// a merge candidate in case there is a confirmable merge.
void DetermineProfileImportType();
// An id to identify an import request.
AutofillProfileImportId import_id_;
// Indicates if the user is already prompted.
bool prompt_shown_{false};
// The profile as it has been observed on form submission.
AutofillProfile observed_profile_;
// Profiles that are silently updateable with the observed profile.
std::vector<AutofillProfile> updated_profiles_;
// A profile in its original state that can be merged with the observed
// profile.
absl::optional<AutofillProfile> merge_candidate_;
// The import candidate that is presented to the user.
absl::optional<AutofillProfile> import_candidate_;
// The type of the import indicates if the profile is just a duplicate of an
// existing profile, if an existing profile can be silently updated, or if
// the user must be prompted either because a merge would alter stored values,
// or because the profile is completely new.
AutofillProfileImportType import_type_{
AutofillProfileImportType::kImportTypeUnspecified};
// The profile as it was confirmed by the user or as it should be imported if
// user interactions are disabled.
absl::optional<AutofillProfile> confirmed_import_candidate_;
// The decision the user made when prompted.
AutofillClient::SaveAddressProfileOfferUserDecision user_decision_{
AutofillClient::SaveAddressProfileOfferUserDecision::kUndefined};
// The appplication locale used for this import process.
std::string app_locale_;
// The url of the form.
GURL form_source_url_;
// Indicates if saving a new profile is blocked for the domain the profile
// was observed on.
bool new_profiles_suppressed_for_domain_;
// A pointer to the persona data manager that is used to retrieve additional
// information about existing profiles.
const PersonalDataManager* personal_data_manager_;
// Counts the number of blocked profile updates.
int number_of_blocked_profile_updates_{0};
};
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_IMPORT_PROCESS_H_