OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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/core/browser/legal_message_line.h" | |
6 | |
7 #include "base/i18n/message_formatter.h" | |
8 #include "base/logging.h" | |
9 #include "base/strings/string_util.h" | |
10 #include "base/strings/utf_string_conversions.h" | |
11 #include "base/values.h" | |
12 | |
13 namespace autofill { | |
14 namespace { | |
15 | |
16 // Replace "{0}", "{1}", ... in |template_icu| with corresponding strings | |
17 // from |display_texts|. Sets |out_message| to the resulting string, with | |
18 // start position of each replacement in |out_offsets|. | |
19 // Return false on failure. If false is returned then contents of |out_message| | |
20 // and |out_offsets| are undefined. | |
21 bool ReplaceTemplatePlaceholders( | |
22 const base::string16& template_icu, | |
23 const std::vector<base::string16>& display_texts, | |
24 base::string16* out_message, | |
25 std::vector<size_t>* out_offsets) { | |
26 // Escape "$" -> "$$" for ReplaceStringPlaceholders(). | |
27 // | |
28 // Edge cases: | |
29 // 1. Two or more consecutive $ characters will be incorrectly expanded | |
30 // ("$$" -> "$$$$", which ReplaceStringPlaceholders() then turns into | |
31 // "$$$"). | |
32 // | |
33 // 2. "${" will cause false to be returned. "${0}" will expand to "$${0}". | |
34 // FormatWithNumberedArgs() turns it into "$$$1", which | |
35 // ReplaceStringPlaceholders() then turns into "$$1" without doing the | |
36 // parameter replacement. This causes false to be returned because each | |
37 // parameter is not used exactly once. | |
38 // | |
39 // Both of these cases are noted in the header file, and are unlikely to | |
40 // occur in any actual legal message. | |
41 base::string16 template_icu_escaped; | |
42 base::ReplaceChars(template_icu, base::ASCIIToUTF16("$"), | |
43 base::ASCIIToUTF16("$$"), &template_icu_escaped); | |
44 | |
45 // Replace "{0}" -> "$1", "{1}" -> "$2", ... to prepare |template_dollars| | |
46 // for ReplaceStringPlaceholders(). | |
47 base::string16 template_dollars = | |
48 base::i18n::MessageFormatter::FormatWithNumberedArgs( | |
49 template_icu_escaped, "$1", "$2", "$3", "$4", "$5", "$6", "$7"); | |
50 | |
51 // FormatWithNumberedArgs() returns an empty string on failure. | |
52 if (template_dollars.empty() && !template_icu.empty()) | |
53 return false; | |
54 | |
55 // Replace "$1", "$2", ... with the display text of each parameter. | |
56 *out_message = base::ReplaceStringPlaceholders(template_dollars, | |
57 display_texts, out_offsets); | |
58 | |
59 // Each parameter must be used exactly once. If a parameter is unused or | |
60 // used more than once then it can't be determined which |offsets| entry | |
61 // corresponds to which parameter. | |
62 return out_offsets->size() == display_texts.size(); | |
63 } | |
64 | |
65 } // namespace | |
66 | |
67 // static | |
68 bool LegalMessageLine::Parse(const base::DictionaryValue& legal_message, | |
69 LegalMessageLines* out) { | |
70 const base::ListValue* lines_list = nullptr; | |
71 if (legal_message.GetList("line", &lines_list)) { | |
72 LegalMessageLines lines; | |
73 lines.reserve(lines_list->GetSize()); | |
74 for (size_t i = 0; i < lines_list->GetSize(); ++i) { | |
75 lines.emplace_back(LegalMessageLine()); | |
76 const base::DictionaryValue* single_line; | |
77 if (!lines_list->GetDictionary(i, &single_line) || | |
78 !lines.back().ParseLine(*single_line)) | |
79 return false; | |
80 } | |
81 | |
82 out->swap(lines); | |
83 } | |
84 | |
85 return true; | |
86 } | |
87 | |
88 LegalMessageLine::LegalMessageLine() {} | |
89 | |
90 LegalMessageLine::~LegalMessageLine() {} | |
91 | |
92 bool LegalMessageLine::ParseLine(const base::DictionaryValue& line) { | |
93 DCHECK(text_.empty()); | |
94 DCHECK(links_.empty()); | |
95 | |
96 // |display_texts| elements are the strings that will be substituted for | |
97 // "{0}", "{1}", etc. in the template string. | |
98 std::vector<base::string16> display_texts; | |
99 | |
100 // Process all the template parameters. | |
101 const base::ListValue* template_parameters = nullptr; | |
102 if (line.GetList("template_parameter", &template_parameters)) { | |
103 display_texts.resize(template_parameters->GetSize()); | |
104 links_.reserve(template_parameters->GetSize()); | |
105 | |
106 for (size_t parameter_index = 0; | |
107 parameter_index < template_parameters->GetSize(); ++parameter_index) { | |
108 const base::DictionaryValue* single_parameter; | |
109 std::string url; | |
110 if (!template_parameters->GetDictionary(parameter_index, | |
111 &single_parameter) || | |
112 !single_parameter->GetString("display_text", | |
113 &display_texts[parameter_index]) || | |
114 !single_parameter->GetString("url", &url)) | |
115 return false; | |
116 | |
117 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.
| |
118 } | |
119 } | |
120 | |
121 // Read the template string. It's a small subset of the ICU message format | |
122 // syntax. | |
123 base::string16 template_icu; | |
124 if (!line.GetString("template", &template_icu)) | |
125 return false; | |
126 | |
127 // Replace the placeholders in |template_icu| with strings from | |
128 // |display_texts|, and store the start position of each replacement in | |
129 // |offsets|. | |
130 std::vector<size_t> offsets; | |
131 if (!ReplaceTemplatePlaceholders(template_icu, display_texts, &text_, | |
132 &offsets)) | |
133 return false; | |
134 | |
135 // Fill in range values for all links. | |
136 for (size_t offset_index = 0; offset_index < offsets.size(); ++offset_index) { | |
137 size_t range_start = offsets[offset_index]; | |
138 links_[offset_index].range = gfx::Range( | |
139 range_start, range_start + display_texts[offset_index].size()); | |
140 } | |
141 | |
142 return true; | |
143 } | |
144 | |
145 } // namespace autofill | |
OLD | NEW |