OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/base/template_expressions.h" | 5 #include "ui/base/template_expressions.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
11 #include "net/base/escape.h" | 11 #include "net/base/escape.h" |
12 | 12 |
13 namespace { | 13 namespace { |
14 const char kLeader[] = "$i18n"; | 14 const char kLeader[] = "$i18n"; |
15 const size_t kLeaderSize = arraysize(kLeader) - 1; | 15 const size_t kLeaderSize = arraysize(kLeader) - 1; |
16 const char kKeyOpen = '{'; | 16 const char kKeyOpen = '{'; |
17 const char kKeyClose = '}'; | 17 const char kKeyClose = '}'; |
| 18 |
| 19 // Escape quotes and backslashes ('"\) with backslashes. |
| 20 std::string BackslashEscape(const std::string& in_string) { |
| 21 std::string out; |
| 22 out.reserve(in_string.size() * 2); |
| 23 for (const char c : in_string) { |
| 24 switch (c) { |
| 25 case '\\': |
| 26 out.append("\\\\"); |
| 27 break; |
| 28 case '\'': |
| 29 out.append("\\'"); |
| 30 break; |
| 31 case '"': |
| 32 out.append("\\\""); |
| 33 break; |
| 34 default: |
| 35 out += c; |
| 36 } |
| 37 } |
| 38 return out; |
| 39 } |
| 40 |
18 } // namespace | 41 } // namespace |
19 | 42 |
20 namespace ui { | 43 namespace ui { |
21 | 44 |
22 void TemplateReplacementsFromDictionaryValue( | 45 void TemplateReplacementsFromDictionaryValue( |
23 const base::DictionaryValue& dictionary, | 46 const base::DictionaryValue& dictionary, |
24 TemplateReplacements* replacements) { | 47 TemplateReplacements* replacements) { |
25 for (base::DictionaryValue::Iterator it(dictionary); !it.IsAtEnd(); | 48 for (base::DictionaryValue::Iterator it(dictionary); !it.IsAtEnd(); |
26 it.Advance()) { | 49 it.Advance()) { |
27 if (it.value().IsType(base::Value::Type::STRING)) { | 50 if (it.value().IsType(base::Value::Type::STRING)) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 TemplateReplacements::const_iterator value = replacements.find(key); | 93 TemplateReplacements::const_iterator value = replacements.find(key); |
71 CHECK(value != replacements.end()) << "$i18n replacement key \"" << key | 94 CHECK(value != replacements.end()) << "$i18n replacement key \"" << key |
72 << "\" not found"; | 95 << "\" not found"; |
73 | 96 |
74 std::string replacement = value->second; | 97 std::string replacement = value->second; |
75 if (context.empty()) { | 98 if (context.empty()) { |
76 // Make the replacement HTML safe. | 99 // Make the replacement HTML safe. |
77 replacement = net::EscapeForHTML(replacement); | 100 replacement = net::EscapeForHTML(replacement); |
78 } else if (context == "Raw") { | 101 } else if (context == "Raw") { |
79 // Pass the replacement through unchanged. | 102 // Pass the replacement through unchanged. |
| 103 } else if (context == "Polymer") { |
| 104 // Escape quotes and backslash for '$i18nPolymer{}' use (i.e. quoted). |
| 105 replacement = BackslashEscape(replacement); |
80 } else { | 106 } else { |
81 CHECK(false) << "Unknown context " << context; | 107 CHECK(false) << "Unknown context " << context; |
82 } | 108 } |
83 | 109 |
84 formatted.append(replacement); | 110 formatted.append(replacement); |
85 | 111 |
86 current_pos = key_end + sizeof(kKeyClose); | 112 current_pos = key_end + sizeof(kKeyClose); |
87 } | 113 } |
88 return formatted; | 114 return formatted; |
89 } | 115 } |
90 | 116 |
91 } // namespace ui | 117 } // namespace ui |
OLD | NEW |