Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Unified Diff: components/autofill/core/browser/legal_message_line.cc

Issue 1540423004: Add card details and legal message to Android save credit card infobar. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Allow copying LegalMessageLine. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/autofill/core/browser/legal_message_line.cc
diff --git a/components/autofill/core/browser/legal_message_line.cc b/components/autofill/core/browser/legal_message_line.cc
new file mode 100644
index 0000000000000000000000000000000000000000..626bf9325f0c3255af46ec10507374ad7c7938e2
--- /dev/null
+++ b/components/autofill/core/browser/legal_message_line.cc
@@ -0,0 +1,145 @@
+// Copyright 2016 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/legal_message_line.h"
+
+#include "base/i18n/message_formatter.h"
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+
+namespace autofill {
+namespace {
+
+// Replace "{0}", "{1}", ... in |template_icu| with corresponding strings
+// from |display_texts|. Sets |out_message| to the resulting string, with
+// start position of each replacement in |out_offsets|.
+// Return false on failure. If false is returned then contents of |out_message|
+// and |out_offsets| are undefined.
+bool ReplaceTemplatePlaceholders(
+ const base::string16& template_icu,
+ const std::vector<base::string16>& display_texts,
+ base::string16* out_message,
+ std::vector<size_t>* out_offsets) {
+ // Escape "$" -> "$$" for ReplaceStringPlaceholders().
+ //
+ // Edge cases:
+ // 1. Two or more consecutive $ characters will be incorrectly expanded
+ // ("$$" -> "$$$$", which ReplaceStringPlaceholders() then turns into
+ // "$$$").
+ //
+ // 2. "${" will cause false to be returned. "${0}" will expand to "$${0}".
+ // FormatWithNumberedArgs() turns it into "$$$1", which
+ // ReplaceStringPlaceholders() then turns into "$$1" without doing the
+ // parameter replacement. This causes false to be returned because each
+ // parameter is not used exactly once.
+ //
+ // Both of these cases are noted in the header file, and are unlikely to
+ // occur in any actual legal message.
+ base::string16 template_icu_escaped;
+ base::ReplaceChars(template_icu, base::ASCIIToUTF16("$"),
+ base::ASCIIToUTF16("$$"), &template_icu_escaped);
+
+ // Replace "{0}" -> "$1", "{1}" -> "$2", ... to prepare |template_dollars|
+ // for ReplaceStringPlaceholders().
+ base::string16 template_dollars =
+ base::i18n::MessageFormatter::FormatWithNumberedArgs(
+ template_icu_escaped, "$1", "$2", "$3", "$4", "$5", "$6", "$7");
+
+ // FormatWithNumberedArgs() returns an empty string on failure.
+ if (template_dollars.empty() && !template_icu.empty())
+ return false;
+
+ // Replace "$1", "$2", ... with the display text of each parameter.
+ *out_message = base::ReplaceStringPlaceholders(template_dollars,
+ display_texts, out_offsets);
+
+ // Each parameter must be used exactly once. If a parameter is unused or
+ // used more than once then it can't be determined which |offsets| entry
+ // corresponds to which parameter.
+ return out_offsets->size() == display_texts.size();
+}
+
+} // namespace
+
+// static
+bool LegalMessageLine::Parse(const base::DictionaryValue& legal_message,
+ LegalMessageLines* out) {
+ const base::ListValue* lines_list = nullptr;
+ if (legal_message.GetList("line", &lines_list)) {
+ LegalMessageLines lines;
+ lines.reserve(lines_list->GetSize());
+ for (size_t i = 0; i < lines_list->GetSize(); ++i) {
+ lines.emplace_back(LegalMessageLine());
+ const base::DictionaryValue* single_line;
+ if (!lines_list->GetDictionary(i, &single_line) ||
+ !lines.back().ParseLine(*single_line))
+ return false;
+ }
+
+ out->swap(lines);
+ }
+
+ return true;
+}
+
+LegalMessageLine::LegalMessageLine() {}
+
+LegalMessageLine::~LegalMessageLine() {}
+
+bool LegalMessageLine::ParseLine(const base::DictionaryValue& line) {
+ DCHECK(text_.empty());
+ DCHECK(links_.empty());
+
+ // |display_texts| elements are the strings that will be substituted for
+ // "{0}", "{1}", etc. in the template string.
+ std::vector<base::string16> display_texts;
+
+ // Process all the template parameters.
+ const base::ListValue* template_parameters = nullptr;
+ if (line.GetList("template_parameter", &template_parameters)) {
+ display_texts.resize(template_parameters->GetSize());
+ links_.reserve(template_parameters->GetSize());
+
+ for (size_t parameter_index = 0;
+ parameter_index < template_parameters->GetSize(); ++parameter_index) {
+ const base::DictionaryValue* single_parameter;
+ std::string url;
+ if (!template_parameters->GetDictionary(parameter_index,
+ &single_parameter) ||
+ !single_parameter->GetString("display_text",
+ &display_texts[parameter_index]) ||
+ !single_parameter->GetString("url", &url))
+ return false;
+
+ links_.emplace_back(Link{gfx::Range(), GURL(url)});
Peter Kasting 2016/01/14 04:19:25 Nit: Can you just do: links_.emplace_back(gfx::
please use gerrit instead 2016/01/14 17:51:57 Done.
+ }
+ }
+
+ // Read the template string. It's a small subset of the ICU message format
+ // syntax.
+ base::string16 template_icu;
+ if (!line.GetString("template", &template_icu))
+ return false;
+
+ // Replace the placeholders in |template_icu| with strings from
+ // |display_texts|, and store the start position of each replacement in
+ // |offsets|.
+ std::vector<size_t> offsets;
+ if (!ReplaceTemplatePlaceholders(template_icu, display_texts, &text_,
+ &offsets))
+ return false;
+
+ // Fill in range values for all links.
+ for (size_t offset_index = 0; offset_index < offsets.size(); ++offset_index) {
+ size_t range_start = offsets[offset_index];
+ links_[offset_index].range = gfx::Range(
+ range_start, range_start + display_texts[offset_index].size());
+ }
+
+ return true;
+}
+
+} // namespace autofill

Powered by Google App Engine
This is Rietveld 408576698