blob: 1b348caabc04a378170cc70b7eed103d3d67726f [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.
#include "components/autofill_assistant/browser/script_parameters.h"
#include <array>
#include <sstream>
#include "base/logging.h"
namespace {
// Converts a value to a target type. Returns nullopt for invalid or
// non-existent values. Expects bool parameters as 'false' and 'true'.
template <typename T>
absl::optional<T> GetTypedParameter(
const std::map<std::string, std::string> parameters,
const std::string& key) {
auto iter = parameters.find(key);
if (iter == parameters.end())
return absl::nullopt;
std::stringstream ss;
ss << iter->second;
T out;
if (!(ss >> std::boolalpha >> out)) {
LOG(ERROR) << "Error trying to convert parameter '" << key
<< "' with value '" << iter->second << "' to target type";
return absl::nullopt;
}
return out;
}
} // namespace
namespace autofill_assistant {
// Parameter that allows setting the color of the overlay.
const char kOverlayColorParameterName[] = "OVERLAY_COLORS";
// Parameter that contains the current session username. Should be synced with
// |SESSION_USERNAME_PARAMETER| from
// .../password_manager/PasswordChangeLauncher.java
// TODO(b/151401974): Eliminate duplicate parameter definitions.
const char kPasswordChangeUsernameParameterName[] = "PASSWORD_CHANGE_USERNAME";
// Parameter that contains a base64-encoded GetTriggerScriptsResponseProto
// message. Instructs the client to decode and run this trigger script prior to
// starting the regular flow. Takes precedence over REQUEST_TRIGGER_SCRIPT if
// both are specified.
const char kBase64TriggerScriptsResponseProtoParameterName[] =
"TRIGGER_SCRIPTS_BASE64";
// Special parameter for instructing the client to request and run a trigger
// script from a remote RPC prior to starting the regular flow.
const char kRequestTriggerScriptParameterName[] = "REQUEST_TRIGGER_SCRIPT";
// Special bool parameter that MUST be present in all intents. It allows the
// caller to either request immediate start of autofill assistant (if set to
// true), or a delayed start using trigger scripts (if set to false). If this is
// set to false, REQUEST_TRIGGER_SCRIPT or TRIGGER_SCRIPTS_BASE_64 must be set.
const char kStartImmediatelyParameterName[] = "START_IMMEDIATELY";
// Mandatory parameter that MUST be present and set to true in all intents.
// Note: this parameter is automatically removed from |ToProto|.
const char kEnabledParameterName[] = "ENABLED";
// The parameter key for the user's email, as indicated by the caller.
const char kCallerEmailParameterName[] = "USER_EMAIL";
// The original deeplink as indicated by the caller. Use this parameter instead
// of the initial URL when available to avoid issues where the initial URL
// points to a redirect rather than the actual deeplink.
const char kOriginalDeeplinkParameterName[] = "ORIGINAL_DEEPLINK";
// Special parameter for declaring a user to be in a trigger script experiment.
const char kTriggerScriptExperimentParameterName[] =
"TRIGGER_SCRIPT_EXPERIMENT";
// The intent parameter.
const char kIntent[] = "INTENT";
// The list of script parameters that trigger scripts are allowed to send to
// the backend.
constexpr std::array<const char*, 6> kAllowlistedTriggerScriptParameters = {
"DEBUG_BUNDLE_ID", "DEBUG_BUNDLE_VERSION", "DEBUG_SOCKET_ID",
"FALLBACK_BUNDLE_ID", "FALLBACK_BUNDLE_VERSION", kIntent};
// Parameters to specify details before the first backend roundtrip.
const char kDetailsShowInitialParameterName[] = "DETAILS_SHOW_INITIAL";
const char kDetailsTitleParameterName[] = "DETAILS_TITLE";
const char kDetailsDescriptionLine1ParameterName[] =
"DETAILS_DESCRIPTION_LINE_1";
const char kDetailsDescriptionLine2ParameterName[] =
"DETAILS_DESCRIPTION_LINE_2";
const char kDetailsDescriptionLine3ParameterName[] =
"DETAILS_DESCRIPTION_LINE_3";
const char kDetailsImageUrl[] = "DETAILS_IMAGE_URL";
const char kDetailsImageAccessibilityHint[] =
"DETAILS_IMAGE_ACCESSIBILITY_HINT";
const char kDetailsImageClickthroughUrl[] = "DETAILS_IMAGE_CLICKTHROUGH_URL";
const char kDetailsTotalPriceLabel[] = "DETAILS_TOTAL_PRICE_LABEL";
const char kDetailsTotalPrice[] = "DETAILS_TOTAL_PRICE";
ScriptParameters::ScriptParameters(
const std::map<std::string, std::string>& parameters)
: parameters_(parameters) {}
ScriptParameters::ScriptParameters() = default;
ScriptParameters::~ScriptParameters() = default;
void ScriptParameters::MergeWith(const ScriptParameters& another) {
for (const auto& param : another.parameters_) {
parameters_.insert(param);
}
}
bool ScriptParameters::Matches(const ScriptParameterMatchProto& proto) const {
auto opt_value = GetParameter(proto.name());
if (!proto.exists()) {
return !opt_value;
}
if (!proto.has_value_equals()) {
return opt_value.has_value();
}
return opt_value && proto.value_equals() == opt_value.value();
}
google::protobuf::RepeatedPtrField<ScriptParameterProto>
ScriptParameters::ToProto(bool only_trigger_script_allowlisted) const {
google::protobuf::RepeatedPtrField<ScriptParameterProto> out;
if (only_trigger_script_allowlisted) {
for (const char* key : kAllowlistedTriggerScriptParameters) {
auto iter = parameters_.find(key);
if (iter == parameters_.end()) {
continue;
}
auto* out_param = out.Add();
out_param->set_name(key);
out_param->set_value(iter->second);
}
return out;
}
// TODO(arbesser): Send properly typed parameters to backend.
for (const auto& parameter : parameters_) {
if (parameter.first == kEnabledParameterName) {
continue;
}
auto* out_param = out.Add();
out_param->set_name(parameter.first);
out_param->set_value(parameter.second);
}
return out;
}
absl::optional<std::string> ScriptParameters::GetParameter(
const std::string& name) const {
auto iter = parameters_.find(name);
if (iter == parameters_.end())
return absl::nullopt;
return iter->second;
}
absl::optional<std::string> ScriptParameters::GetOverlayColors() const {
return GetParameter(kOverlayColorParameterName);
}
absl::optional<std::string> ScriptParameters::GetPasswordChangeUsername()
const {
return GetParameter(kPasswordChangeUsernameParameterName);
}
absl::optional<std::string>
ScriptParameters::GetBase64TriggerScriptsResponseProto() const {
return GetParameter(kBase64TriggerScriptsResponseProtoParameterName);
}
absl::optional<bool> ScriptParameters::GetRequestsTriggerScript() const {
return GetTypedParameter<bool>(parameters_,
kRequestTriggerScriptParameterName);
}
absl::optional<bool> ScriptParameters::GetStartImmediately() const {
return GetTypedParameter<bool>(parameters_, kStartImmediatelyParameterName);
}
absl::optional<bool> ScriptParameters::GetEnabled() const {
return GetTypedParameter<bool>(parameters_, kEnabledParameterName);
}
absl::optional<std::string> ScriptParameters::GetOriginalDeeplink() const {
return GetParameter(kOriginalDeeplinkParameterName);
}
absl::optional<bool> ScriptParameters::GetTriggerScriptExperiment() const {
return GetTypedParameter<bool>(parameters_,
kTriggerScriptExperimentParameterName);
}
absl::optional<std::string> ScriptParameters::GetIntent() const {
return GetParameter(kIntent);
}
absl::optional<std::string> ScriptParameters::GetCallerEmail() const {
return GetParameter(kCallerEmailParameterName);
}
absl::optional<bool> ScriptParameters::GetDetailsShowInitial() const {
return GetTypedParameter<bool>(parameters_, kDetailsShowInitialParameterName);
}
absl::optional<std::string> ScriptParameters::GetDetailsTitle() const {
return GetParameter(kDetailsTitleParameterName);
}
absl::optional<std::string> ScriptParameters::GetDetailsDescriptionLine1()
const {
return GetParameter(kDetailsDescriptionLine1ParameterName);
}
absl::optional<std::string> ScriptParameters::GetDetailsDescriptionLine2()
const {
return GetParameter(kDetailsDescriptionLine2ParameterName);
}
absl::optional<std::string> ScriptParameters::GetDetailsDescriptionLine3()
const {
return GetParameter(kDetailsDescriptionLine3ParameterName);
}
absl::optional<std::string> ScriptParameters::GetDetailsImageUrl() const {
return GetParameter(kDetailsImageUrl);
}
absl::optional<std::string> ScriptParameters::GetDetailsImageAccessibilityHint()
const {
return GetParameter(kDetailsImageAccessibilityHint);
}
absl::optional<std::string> ScriptParameters::GetDetailsImageClickthroughUrl()
const {
return GetParameter(kDetailsImageClickthroughUrl);
}
absl::optional<std::string> ScriptParameters::GetDetailsTotalPriceLabel()
const {
return GetParameter(kDetailsTotalPriceLabel);
}
absl::optional<std::string> ScriptParameters::GetDetailsTotalPrice() const {
return GetParameter(kDetailsTotalPrice);
}
} // namespace autofill_assistant