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

Side by Side Diff: chrome/browser/extensions/extension_message_handler.cc

Issue 173487: Implemented the rest of loading/parsing logic for extension i18n:... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 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 unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 "chrome/browser/extensions/extension_message_handler.h"
6
7 #include <string>
8
9 #include "base/hash_tables.h"
10 #include "base/scoped_ptr.h"
11 #include "base/string_util.h"
12 #include "base/values.h"
13
14 const wchar_t* ExtensionMessageHandler::kContentKey = L"content";
15 const wchar_t* ExtensionMessageHandler::kMessageKey = L"message";
16 const wchar_t* ExtensionMessageHandler::kPlaceholdersKey = L"placeholders";
17
18 const char* ExtensionMessageHandler::kPlaceholderBegin = "$";
19 const char* ExtensionMessageHandler::kPlaceholderEnd = "$";
20 const char* ExtensionMessageHandler::kMessageBegin = "__MSG_";
21 const char* ExtensionMessageHandler::kMessageEnd = "__";
22
23 // Formats message in case we encounter a bad formed key in the JSON object.
24 // Returns false and sets |error| to actual error message.
Aaron Boodman 2009/08/31 21:42:55 How about just returning the string since the retu
25 static bool BadKeyMessage(const std::string& name, std::string* error) {
26 *error = StringPrintf("Name of a key \"%s\" is invalid. Only ASCII [a-z], "
27 "[A-Z], [0-9] and \"_\" are allowed.", name.c_str());
28 return false;
29 }
30
31 ExtensionMessageHandler::ExtensionMessageHandler() {
Aaron Boodman 2009/08/31 21:42:55 Nit: Since the constructor and destructors are not
32 }
33
34 ExtensionMessageHandler::~ExtensionMessageHandler() {
35 }
36
37 bool ExtensionMessageHandler::Init(const DictionaryValue* default_catalog,
Aaron Boodman 2009/08/31 21:42:55 The naming of these parameters is a bit confusing
38 const DictionaryValue* app_catalog,
39 std::string* error) {
40 dictionary_.clear();
41
42 for (DictionaryValue::key_iterator key_it = app_catalog->begin_keys();
43 key_it != app_catalog->end_keys();
44 ++key_it) {
45 std::string key(WideToUTF8(*key_it));
46 if (!IsValidName(key))
47 return BadKeyMessage(key, error);
48 std::string value;
49 if (!GetMessageValue(*key_it, key, app_catalog, &value, error)) {
Aaron Boodman 2009/08/31 21:42:55 Nit: braces unnecessary here.
50 return false;
51 }
52 dictionary_.insert(make_pair(key, value));
Aaron Boodman 2009/08/31 21:42:55 Nit: I think the syntax dictionary[key] = value is
53 }
54
55 for (DictionaryValue::key_iterator key_it = default_catalog->begin_keys();
56 key_it != default_catalog->end_keys();
57 ++key_it) {
58 std::string key(WideToUTF8(*key_it));
59 if (!IsValidName(key))
60 return BadKeyMessage(key, error);
61 // Add only messages that are not provided by app_catalog.
62 if (dictionary_.find(key) != dictionary_.end())
63 continue;
64 std::string value;
65 if (!GetMessageValue(*key_it, key, default_catalog, &value, error)) {
66 return false;
67 }
68 dictionary_.insert(make_pair(key, value));
69 }
70
71 return true;
72 }
73
74 bool ExtensionMessageHandler::GetMessageValue(
75 const std::wstring& wkey,
76 const std::string& key,
77 const DictionaryValue* main_catalog,
Aaron Boodman 2009/08/31 21:42:55 Nit: the "main_catalog" parameter seems misnamed.
78 std::string* value,
79 std::string* error) const {
Aaron Boodman 2009/08/31 21:42:55 Add a DCHECK that the two keys are the same?
80 // Get the top level tree for given key (name part).
81 DictionaryValue* name_tree;
82 if (!main_catalog->GetDictionary(wkey, &name_tree)) {
83 *error = StringPrintf("Not a valid tree for key %s.", key.c_str());
84 return false;
85 }
86 // Extract message from it.
87 if (!name_tree->GetString(kMessageKey, value)) {
88 *error = StringPrintf("There is no \"%s\" element for key %s.",
89 WideToUTF8(kMessageKey).c_str(),
90 key.c_str());
91 return false;
92 }
93
94 SSMap placeholders;
95 if (!GetPlaceholders(name_tree, key, &placeholders, error)) {
96 return false;
97 }
98 if (!ReplacePlaceholdersInMessage(placeholders, value)) {
99 *error = StringPrintf("Placeholder \"%s\" is missing but used in a "
100 "message %s.", value->c_str(), key.c_str());
101 return false;
102 }
103
104 return true;
105 }
106
107 bool ExtensionMessageHandler::GetPlaceholders(const DictionaryValue* name_tree,
108 const std::string name_key,
109 SSMap* placeholders,
110 std::string* error) const {
111 if (!name_tree->HasKey(kPlaceholdersKey))
112 return true;
113
114 DictionaryValue* placeholders_tree;
115 if (!name_tree->GetDictionary(kPlaceholdersKey, &placeholders_tree)) {
116 *error = StringPrintf("Not a valid \"%s\" element for key %s.",
117 WideToUTF8(kPlaceholdersKey).c_str(),
118 name_key.c_str());
119 return false;
120 }
121
122 for (DictionaryValue::key_iterator key_itr = placeholders_tree->begin_keys();
123 key_itr != placeholders_tree->end_keys();
124 ++key_itr) {
125 DictionaryValue* placeholder;
126 std::string content_key = WideToUTF8(*key_itr);
127 if (!IsValidName(content_key))
128 return BadKeyMessage(content_key, error);
129 if (!placeholders_tree->GetDictionary(*key_itr, &placeholder)) {
130 *error = StringPrintf("Invalid placeholder %s for key %s",
131 content_key.c_str(),
132 name_key.c_str());
133 return false;
134 }
135 std::string content;
136 if (!placeholder->GetString(kContentKey, &content)) {
137 *error = StringPrintf("Invalid \"%s\" element for key %s.",
138 WideToUTF8(kContentKey).c_str(),
139 name_key.c_str());
140 return false;
141 }
142 placeholders->insert(std::make_pair(content_key, content));
143 }
144
145 return true;
146 }
147
148 bool ExtensionMessageHandler::ReplacePlaceholdersInMessage(
149 const SSMap& placeholders,
150 std::string* message) const {
151 return ReplaceVariablesInString(
152 placeholders, kPlaceholderBegin, kPlaceholderEnd, message);
153 }
154
155 bool ExtensionMessageHandler::ReplaceMessagesInString(std::string* text) const {
156 return ReplaceVariablesInString(
157 dictionary_, kMessageBegin, kMessageEnd, text);
158 }
159
160 bool ExtensionMessageHandler::ReplaceVariablesInString(
161 const SSMap& variables,
162 const std::string& var_begin,
163 const std::string& var_end,
164 std::string* message) const {
165 std::string::size_type beg_index = 0;
166 const std::string::size_type var_begin_size = var_begin.size();
167 while (true) {
168 beg_index = message->find(var_begin, beg_index);
169 if (beg_index == message->npos) {
Aaron Boodman 2009/08/31 21:42:55 All these one line early exits can be braceless.
170 return true;
171 }
172 // Advance it immediately to the begining of possible variable name.
173 beg_index += var_begin_size;
174 if (beg_index >= message->size()) {
175 return true;
176 }
177 std::string::size_type end_index = message->find(var_end, beg_index);
178 if (end_index == message->npos) {
179 return true;
180 }
181 // Looking for 1 in substring of ...$1$....
182 const std::string& var_name =
183 message->substr(beg_index, end_index - beg_index);
184 if (!IsValidName(var_name)) {
185 continue;
186 }
187 SSMap::const_iterator it = variables.find(var_name);
188 if (it == variables.end()) {
189 message->assign(var_name);
Aaron Boodman 2009/08/31 21:42:55 Did you mean to replace the entire input string wi
190 return false;
191 }
192 std::string value = it->second;
193 // Replace variable with its value.
194 message->replace(beg_index - var_begin_size,
195 end_index - beg_index + var_begin_size + var_end.size(),
196 value);
197 // And position pointer to after the replacement.
198 beg_index += value.size() - var_begin_size;
199 }
200
201 return true;
202 }
203
204 bool ExtensionMessageHandler::IsValidName(const std::string& name) const {
205 if (name.empty())
206 return false;
207
208 for (std::string::const_iterator it = name.begin(); it != name.end(); ++it) {
209 // Allow only ascii 0-9, a-z, A-Z, and _ in the name.
210 if (!IsAsciiAlpha(*it) && !IsAsciiDigit(*it) && *it != '_')
211 return false;
212 }
213
214 return true;
215 }
216
217 // Dictionary interface.
218
219 bool ExtensionMessageHandler::GetMessage(const std::string& name,
220 std::string* message) const {
221 SSMap::const_iterator it = dictionary_.find(name);
222 if (it != dictionary_.end()) {
223 message->assign(it->second);
224 return true;
225 }
226
227 return false;
228 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698