1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/autofill_assistant/browser/trigger_context.h"
6 #include "base/strings/string_split.h"
7 
8 namespace autofill_assistant {
9 
10 // Parameter that allows setting the color of the overlay.
11 const char kOverlayColorParameterName[] = "OVERLAY_COLORS";
12 
13 // Parameter that contains the current session username. Should be synced with
14 // |SESSION_USERNAME_PARAMETER| from
15 // .../password_manager/PasswordChangeLauncher.java
16 // TODO(b/151401974): Eliminate duplicate parameter definitions.
17 const char kPasswordChangeUsernameParameterName[] = "PASSWORD_CHANGE_USERNAME";
18 
19 // Legacy, remove as soon as possible.
20 // Parameter that contains the path of the lite script that was used to trigger
21 // this flow (may be empty).
22 const char kLiteScriptPathParamaterName[] = "TRIGGER_SCRIPT_USED";
23 
24 // Parameter that contains a base64-encoded GetTriggerScriptsResponseProto
25 // message. This allows callers to directly inject trigger scripts, rather than
26 // fetching them from a remote backend.
27 const char kBase64TriggerScriptsResponseProtoParameterName[] =
28     "TRIGGER_SCRIPTS_BASE64";
29 
30 // static
CreateEmpty()31 std::unique_ptr<TriggerContext> TriggerContext::CreateEmpty() {
32   return std::make_unique<TriggerContextImpl>();
33 }
34 
35 // static
Create(std::map<std::string,std::string> params,const std::string & exp)36 std::unique_ptr<TriggerContext> TriggerContext::Create(
37     std::map<std::string, std::string> params,
38     const std::string& exp) {
39   return std::make_unique<TriggerContextImpl>(params, exp);
40 }
41 
42 // static
Merge(std::vector<const TriggerContext * > contexts)43 std::unique_ptr<TriggerContext> TriggerContext::Merge(
44     std::vector<const TriggerContext*> contexts) {
45   return std::make_unique<MergedTriggerContext>(contexts);
46 }
47 
TriggerContext()48 TriggerContext::TriggerContext() {}
~TriggerContext()49 TriggerContext::~TriggerContext() {}
50 
GetOverlayColors() const51 base::Optional<std::string> TriggerContext::GetOverlayColors() const {
52   return GetParameter(kOverlayColorParameterName);
53 }
54 
GetPasswordChangeUsername() const55 base::Optional<std::string> TriggerContext::GetPasswordChangeUsername() const {
56   return GetParameter(kPasswordChangeUsernameParameterName);
57 }
58 
WasStartedByLegacyTriggerScript() const59 bool TriggerContext::WasStartedByLegacyTriggerScript() const {
60   return GetParameter(kLiteScriptPathParamaterName).has_value();
61 }
62 
63 base::Optional<std::string>
GetBase64TriggerScriptsResponseProto() const64 TriggerContext::GetBase64TriggerScriptsResponseProto() const {
65   return GetParameter(kBase64TriggerScriptsResponseProtoParameterName);
66 }
67 
TriggerContextImpl()68 TriggerContextImpl::TriggerContextImpl() {}
69 
TriggerContextImpl(std::map<std::string,std::string> parameters,const std::string & experiment_ids)70 TriggerContextImpl::TriggerContextImpl(
71     std::map<std::string, std::string> parameters,
72     const std::string& experiment_ids)
73     : parameters_(std::move(parameters)),
74       experiment_ids_(std::move(experiment_ids)) {}
75 
76 TriggerContextImpl::~TriggerContextImpl() = default;
77 
GetParameters() const78 std::map<std::string, std::string> TriggerContextImpl::GetParameters() const {
79   return parameters_;
80 }
81 
GetParameter(const std::string & name) const82 base::Optional<std::string> TriggerContextImpl::GetParameter(
83     const std::string& name) const {
84   auto iter = parameters_.find(name);
85   if (iter == parameters_.end())
86     return base::nullopt;
87 
88   return iter->second;
89 }
90 
experiment_ids() const91 std::string TriggerContextImpl::experiment_ids() const {
92   return experiment_ids_;
93 }
94 
HasExperimentId(const std::string & experiment_id) const95 bool TriggerContextImpl::HasExperimentId(
96     const std::string& experiment_id) const {
97   std::vector<std::string> experiments = base::SplitString(
98       experiment_ids_, ",", base::WhitespaceHandling::TRIM_WHITESPACE,
99       base::SplitResult::SPLIT_WANT_NONEMPTY);
100   return std::find(experiments.begin(), experiments.end(), experiment_id) !=
101          experiments.end();
102 }
103 
is_cct() const104 bool TriggerContextImpl::is_cct() const {
105   return cct_;
106 }
107 
is_onboarding_shown() const108 bool TriggerContextImpl::is_onboarding_shown() const {
109   return onboarding_shown_;
110 }
111 
is_direct_action() const112 bool TriggerContextImpl::is_direct_action() const {
113   return direct_action_;
114 }
115 
get_caller_account_hash() const116 std::string TriggerContextImpl::get_caller_account_hash() const {
117   return caller_account_hash_;
118 }
119 
MergedTriggerContext(std::vector<const TriggerContext * > contexts)120 MergedTriggerContext::MergedTriggerContext(
121     std::vector<const TriggerContext*> contexts)
122     : contexts_(contexts) {}
123 
~MergedTriggerContext()124 MergedTriggerContext::~MergedTriggerContext() {}
125 
GetParameters() const126 std::map<std::string, std::string> MergedTriggerContext::GetParameters() const {
127   std::map<std::string, std::string> merged_parameters;
128   for (const TriggerContext* context : contexts_) {
129     for (const auto& parameter : context->GetParameters()) {
130       merged_parameters.insert(parameter);
131     }
132   }
133   return merged_parameters;
134 }
135 
GetParameter(const std::string & name) const136 base::Optional<std::string> MergedTriggerContext::GetParameter(
137     const std::string& name) const {
138   for (const TriggerContext* context : contexts_) {
139     auto opt_value = context->GetParameter(name);
140     if (opt_value)
141       return opt_value;
142   }
143   return base::nullopt;
144 }
145 
experiment_ids() const146 std::string MergedTriggerContext::experiment_ids() const {
147   std::string experiment_ids;
148   for (const TriggerContext* context : contexts_) {
149     std::string context_experiment_ids = context->experiment_ids();
150     if (context_experiment_ids.empty())
151       continue;
152 
153     if (!experiment_ids.empty())
154       experiment_ids.append(1, ',');
155 
156     experiment_ids.append(context->experiment_ids());
157   }
158   return experiment_ids;
159 }
160 
HasExperimentId(const std::string & experiment_id) const161 bool MergedTriggerContext::HasExperimentId(
162     const std::string& experiment_id) const {
163   for (const TriggerContext* context : contexts_) {
164     if (context->HasExperimentId(experiment_id)) {
165       return true;
166     }
167   }
168   return false;
169 }
170 
is_cct() const171 bool MergedTriggerContext::is_cct() const {
172   for (const TriggerContext* context : contexts_) {
173     if (context->is_cct())
174       return true;
175   }
176   return false;
177 }
178 
is_onboarding_shown() const179 bool MergedTriggerContext::is_onboarding_shown() const {
180   for (const TriggerContext* context : contexts_) {
181     if (context->is_onboarding_shown())
182       return true;
183   }
184   return false;
185 }
186 
is_direct_action() const187 bool MergedTriggerContext::is_direct_action() const {
188   for (const TriggerContext* context : contexts_) {
189     if (context->is_direct_action())
190       return true;
191   }
192   return false;
193 }
194 
get_caller_account_hash() const195 std::string MergedTriggerContext::get_caller_account_hash() const {
196   for (const TriggerContext* context : contexts_) {
197     if (!context->get_caller_account_hash().empty())
198       return context->get_caller_account_hash();
199   }
200   return "";
201 }
202 
203 }  // namespace autofill_assistant
204