| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/common/message_bundle.h" | 5 #include "extensions/common/message_bundle.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <string> | 10 #include <string> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/i18n/rtl.h" | 13 #include "base/i18n/rtl.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/memory/linked_ptr.h" | |
| 16 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 18 #include "base/values.h" | 17 #include "base/values.h" |
| 19 #include "extensions/common/error_utils.h" | 18 #include "extensions/common/error_utils.h" |
| 20 #include "extensions/common/extension_l10n_util.h" | 19 #include "extensions/common/extension_l10n_util.h" |
| 21 #include "extensions/common/manifest_constants.h" | 20 #include "extensions/common/manifest_constants.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 22 |
| 24 namespace extensions { | 23 namespace extensions { |
| 25 | 24 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 const std::string& message, | 66 const std::string& message, |
| 68 bool create_placeholder_subtree, | 67 bool create_placeholder_subtree, |
| 69 base::DictionaryValue* dict) { | 68 base::DictionaryValue* dict) { |
| 70 base::DictionaryValue* message_tree = new base::DictionaryValue; | 69 base::DictionaryValue* message_tree = new base::DictionaryValue; |
| 71 if (create_placeholder_subtree) | 70 if (create_placeholder_subtree) |
| 72 CreatePlaceholdersTree(message_tree); | 71 CreatePlaceholdersTree(message_tree); |
| 73 message_tree->SetString(MessageBundle::kMessageKey, message); | 72 message_tree->SetString(MessageBundle::kMessageKey, message); |
| 74 SetDictionary(name, message_tree, dict); | 73 SetDictionary(name, message_tree, dict); |
| 75 } | 74 } |
| 76 | 75 |
| 77 // Caller owns the memory. | 76 std::unique_ptr<base::DictionaryValue> CreateGoodDictionary() { |
| 78 base::DictionaryValue* CreateGoodDictionary() { | 77 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 79 base::DictionaryValue* dict = new base::DictionaryValue; | 78 CreateMessageTree("n1", "message1 $a$ $b$", true, dict.get()); |
| 80 CreateMessageTree("n1", "message1 $a$ $b$", true, dict); | 79 CreateMessageTree("n2", "message2 $c$", true, dict.get()); |
| 81 CreateMessageTree("n2", "message2 $c$", true, dict); | 80 CreateMessageTree("n3", "message3", false, dict.get()); |
| 82 CreateMessageTree("n3", "message3", false, dict); | |
| 83 return dict; | 81 return dict; |
| 84 } | 82 } |
| 85 | 83 |
| 86 // Caller owns the memory. | 84 std::unique_ptr<base::DictionaryValue> CreateBadDictionary( |
| 87 base::DictionaryValue* CreateBadDictionary(enum BadDictionary what_is_bad) { | 85 enum BadDictionary what_is_bad) { |
| 88 base::DictionaryValue* dict = CreateGoodDictionary(); | 86 std::unique_ptr<base::DictionaryValue> dict = CreateGoodDictionary(); |
| 89 // Now remove/break things. | 87 // Now remove/break things. |
| 90 switch (what_is_bad) { | 88 switch (what_is_bad) { |
| 91 case INVALID_NAME: | 89 case INVALID_NAME: |
| 92 CreateMessageTree("n 5", "nevermind", false, dict); | 90 CreateMessageTree("n 5", "nevermind", false, dict.get()); |
| 93 break; | 91 break; |
| 94 case NAME_NOT_A_TREE: | 92 case NAME_NOT_A_TREE: |
| 95 dict->SetString("n4", "whatever"); | 93 dict->SetString("n4", "whatever"); |
| 96 break; | 94 break; |
| 97 case EMPTY_NAME_TREE: { | 95 case EMPTY_NAME_TREE: { |
| 98 base::DictionaryValue* empty_tree = new base::DictionaryValue; | 96 base::DictionaryValue* empty_tree = new base::DictionaryValue; |
| 99 SetDictionary("n4", empty_tree, dict); | 97 SetDictionary("n4", empty_tree, dict.get()); |
| 100 } | 98 } |
| 101 break; | 99 break; |
| 102 case MISSING_MESSAGE: | 100 case MISSING_MESSAGE: |
| 103 dict->Remove("n1.message", NULL); | 101 dict->Remove("n1.message", NULL); |
| 104 break; | 102 break; |
| 105 case PLACEHOLDER_NOT_A_TREE: | 103 case PLACEHOLDER_NOT_A_TREE: |
| 106 dict->SetString("n1.placeholders", "whatever"); | 104 dict->SetString("n1.placeholders", "whatever"); |
| 107 break; | 105 break; |
| 108 case EMPTY_PLACEHOLDER_TREE: { | 106 case EMPTY_PLACEHOLDER_TREE: { |
| 109 base::DictionaryValue* empty_tree = new base::DictionaryValue; | 107 base::DictionaryValue* empty_tree = new base::DictionaryValue; |
| 110 SetDictionary("n1.placeholders", empty_tree, dict); | 108 SetDictionary("n1.placeholders", empty_tree, dict.get()); |
| 111 } | 109 } |
| 112 break; | 110 break; |
| 113 case CONTENT_MISSING: | 111 case CONTENT_MISSING: |
| 114 dict->Remove("n1.placeholders.a.content", NULL); | 112 dict->Remove("n1.placeholders.a.content", NULL); |
| 115 break; | 113 break; |
| 116 case MESSAGE_PLACEHOLDER_DOESNT_MATCH: | 114 case MESSAGE_PLACEHOLDER_DOESNT_MATCH: |
| 117 base::DictionaryValue* value; | 115 base::DictionaryValue* value; |
| 118 dict->Remove("n1.placeholders.a", NULL); | 116 dict->Remove("n1.placeholders.a", NULL); |
| 119 dict->GetDictionary("n1.placeholders", &value); | 117 dict->GetDictionary("n1.placeholders", &value); |
| 120 CreateContentTree("x", "X", value); | 118 CreateContentTree("x", "X", value); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 handler_.reset(MessageBundle::Create(catalogs_, &error)); | 152 handler_.reset(MessageBundle::Create(catalogs_, &error)); |
| 155 | 153 |
| 156 return error; | 154 return error; |
| 157 } | 155 } |
| 158 | 156 |
| 159 void ClearDictionary() { | 157 void ClearDictionary() { |
| 160 handler_->dictionary_.clear(); | 158 handler_->dictionary_.clear(); |
| 161 } | 159 } |
| 162 | 160 |
| 163 std::unique_ptr<MessageBundle> handler_; | 161 std::unique_ptr<MessageBundle> handler_; |
| 164 std::vector<linked_ptr<base::DictionaryValue> > catalogs_; | 162 std::vector<std::unique_ptr<base::DictionaryValue>> catalogs_; |
| 165 }; | 163 }; |
| 166 | 164 |
| 167 TEST_F(MessageBundleTest, ReservedMessagesCount) { | 165 TEST_F(MessageBundleTest, ReservedMessagesCount) { |
| 168 ASSERT_EQ(5U, ReservedMessagesCount()); | 166 ASSERT_EQ(5U, ReservedMessagesCount()); |
| 169 } | 167 } |
| 170 | 168 |
| 171 TEST_F(MessageBundleTest, InitEmptyDictionaries) { | 169 TEST_F(MessageBundleTest, InitEmptyDictionaries) { |
| 172 CreateMessageBundle(); | 170 CreateMessageBundle(); |
| 173 EXPECT_TRUE(handler_.get() != NULL); | 171 EXPECT_TRUE(handler_.get() != NULL); |
| 174 EXPECT_EQ(0U + ReservedMessagesCount(), handler_->size()); | 172 EXPECT_EQ(0U + ReservedMessagesCount(), handler_->size()); |
| 175 CheckReservedMessages(handler_.get()); | 173 CheckReservedMessages(handler_.get()); |
| 176 } | 174 } |
| 177 | 175 |
| 178 TEST_F(MessageBundleTest, InitGoodDefaultDict) { | 176 TEST_F(MessageBundleTest, InitGoodDefaultDict) { |
| 179 catalogs_.push_back( | 177 catalogs_.push_back(CreateGoodDictionary()); |
| 180 linked_ptr<base::DictionaryValue>(CreateGoodDictionary())); | |
| 181 CreateMessageBundle(); | 178 CreateMessageBundle(); |
| 182 | 179 |
| 183 EXPECT_TRUE(handler_.get() != NULL); | 180 EXPECT_TRUE(handler_.get() != NULL); |
| 184 EXPECT_EQ(3U + ReservedMessagesCount(), handler_->size()); | 181 EXPECT_EQ(3U + ReservedMessagesCount(), handler_->size()); |
| 185 | 182 |
| 186 EXPECT_EQ("message1 A B", handler_->GetL10nMessage("n1")); | 183 EXPECT_EQ("message1 A B", handler_->GetL10nMessage("n1")); |
| 187 EXPECT_EQ("message2 C", handler_->GetL10nMessage("n2")); | 184 EXPECT_EQ("message2 C", handler_->GetL10nMessage("n2")); |
| 188 EXPECT_EQ("message3", handler_->GetL10nMessage("n3")); | 185 EXPECT_EQ("message3", handler_->GetL10nMessage("n3")); |
| 189 CheckReservedMessages(handler_.get()); | 186 CheckReservedMessages(handler_.get()); |
| 190 } | 187 } |
| 191 | 188 |
| 192 TEST_F(MessageBundleTest, InitAppDictConsultedFirst) { | 189 TEST_F(MessageBundleTest, InitAppDictConsultedFirst) { |
| 193 catalogs_.push_back( | 190 catalogs_.push_back(CreateGoodDictionary()); |
| 194 linked_ptr<base::DictionaryValue>(CreateGoodDictionary())); | 191 catalogs_.push_back(CreateGoodDictionary()); |
| 195 catalogs_.push_back( | |
| 196 linked_ptr<base::DictionaryValue>(CreateGoodDictionary())); | |
| 197 | 192 |
| 198 base::DictionaryValue* app_dict = catalogs_[0].get(); | 193 base::DictionaryValue* app_dict = catalogs_[0].get(); |
| 199 // Flip placeholders in message of n1 tree. | 194 // Flip placeholders in message of n1 tree. |
| 200 app_dict->SetString("n1.message", "message1 $b$ $a$"); | 195 app_dict->SetString("n1.message", "message1 $b$ $a$"); |
| 201 // Remove one message from app dict. | 196 // Remove one message from app dict. |
| 202 app_dict->Remove("n2", NULL); | 197 app_dict->Remove("n2", NULL); |
| 203 // Replace n3 with N3. | 198 // Replace n3 with N3. |
| 204 app_dict->Remove("n3", NULL); | 199 app_dict->Remove("n3", NULL); |
| 205 CreateMessageTree("N3", "message3_app_dict", false, app_dict); | 200 CreateMessageTree("N3", "message3_app_dict", false, app_dict); |
| 206 | 201 |
| 207 CreateMessageBundle(); | 202 CreateMessageBundle(); |
| 208 | 203 |
| 209 EXPECT_TRUE(handler_.get() != NULL); | 204 EXPECT_TRUE(handler_.get() != NULL); |
| 210 EXPECT_EQ(3U + ReservedMessagesCount(), handler_->size()); | 205 EXPECT_EQ(3U + ReservedMessagesCount(), handler_->size()); |
| 211 | 206 |
| 212 EXPECT_EQ("message1 B A", handler_->GetL10nMessage("n1")); | 207 EXPECT_EQ("message1 B A", handler_->GetL10nMessage("n1")); |
| 213 EXPECT_EQ("message2 C", handler_->GetL10nMessage("n2")); | 208 EXPECT_EQ("message2 C", handler_->GetL10nMessage("n2")); |
| 214 EXPECT_EQ("message3_app_dict", handler_->GetL10nMessage("n3")); | 209 EXPECT_EQ("message3_app_dict", handler_->GetL10nMessage("n3")); |
| 215 CheckReservedMessages(handler_.get()); | 210 CheckReservedMessages(handler_.get()); |
| 216 } | 211 } |
| 217 | 212 |
| 218 TEST_F(MessageBundleTest, InitBadAppDict) { | 213 TEST_F(MessageBundleTest, InitBadAppDict) { |
| 219 catalogs_.push_back( | 214 catalogs_.push_back(CreateBadDictionary(INVALID_NAME)); |
| 220 linked_ptr<base::DictionaryValue>(CreateBadDictionary(INVALID_NAME))); | 215 catalogs_.push_back(CreateGoodDictionary()); |
| 221 catalogs_.push_back( | |
| 222 linked_ptr<base::DictionaryValue>(CreateGoodDictionary())); | |
| 223 | 216 |
| 224 std::string error = CreateMessageBundle(); | 217 std::string error = CreateMessageBundle(); |
| 225 | 218 |
| 226 EXPECT_TRUE(handler_.get() == NULL); | 219 EXPECT_TRUE(handler_.get() == NULL); |
| 227 EXPECT_EQ("Name of a key \"n 5\" is invalid. Only ASCII [a-z], " | 220 EXPECT_EQ("Name of a key \"n 5\" is invalid. Only ASCII [a-z], " |
| 228 "[A-Z], [0-9] and \"_\" are allowed.", error); | 221 "[A-Z], [0-9] and \"_\" are allowed.", error); |
| 229 | 222 |
| 230 catalogs_[0].reset(CreateBadDictionary(NAME_NOT_A_TREE)); | 223 catalogs_[0] = CreateBadDictionary(NAME_NOT_A_TREE); |
| 231 handler_.reset(MessageBundle::Create(catalogs_, &error)); | 224 handler_.reset(MessageBundle::Create(catalogs_, &error)); |
| 232 EXPECT_TRUE(handler_.get() == NULL); | 225 EXPECT_TRUE(handler_.get() == NULL); |
| 233 EXPECT_EQ("Not a valid tree for key n4.", error); | 226 EXPECT_EQ("Not a valid tree for key n4.", error); |
| 234 | 227 |
| 235 catalogs_[0].reset(CreateBadDictionary(EMPTY_NAME_TREE)); | 228 catalogs_[0] = CreateBadDictionary(EMPTY_NAME_TREE); |
| 236 handler_.reset(MessageBundle::Create(catalogs_, &error)); | 229 handler_.reset(MessageBundle::Create(catalogs_, &error)); |
| 237 EXPECT_TRUE(handler_.get() == NULL); | 230 EXPECT_TRUE(handler_.get() == NULL); |
| 238 EXPECT_EQ("There is no \"message\" element for key n4.", error); | 231 EXPECT_EQ("There is no \"message\" element for key n4.", error); |
| 239 | 232 |
| 240 catalogs_[0].reset(CreateBadDictionary(MISSING_MESSAGE)); | 233 catalogs_[0] = CreateBadDictionary(MISSING_MESSAGE); |
| 241 handler_.reset(MessageBundle::Create(catalogs_, &error)); | 234 handler_.reset(MessageBundle::Create(catalogs_, &error)); |
| 242 EXPECT_TRUE(handler_.get() == NULL); | 235 EXPECT_TRUE(handler_.get() == NULL); |
| 243 EXPECT_EQ("There is no \"message\" element for key n1.", error); | 236 EXPECT_EQ("There is no \"message\" element for key n1.", error); |
| 244 | 237 |
| 245 catalogs_[0].reset(CreateBadDictionary(PLACEHOLDER_NOT_A_TREE)); | 238 catalogs_[0] = CreateBadDictionary(PLACEHOLDER_NOT_A_TREE); |
| 246 handler_.reset(MessageBundle::Create(catalogs_, &error)); | 239 handler_.reset(MessageBundle::Create(catalogs_, &error)); |
| 247 EXPECT_TRUE(handler_.get() == NULL); | 240 EXPECT_TRUE(handler_.get() == NULL); |
| 248 EXPECT_EQ("Not a valid \"placeholders\" element for key n1.", error); | 241 EXPECT_EQ("Not a valid \"placeholders\" element for key n1.", error); |
| 249 | 242 |
| 250 catalogs_[0].reset(CreateBadDictionary(EMPTY_PLACEHOLDER_TREE)); | 243 catalogs_[0] = CreateBadDictionary(EMPTY_PLACEHOLDER_TREE); |
| 251 handler_.reset(MessageBundle::Create(catalogs_, &error)); | 244 handler_.reset(MessageBundle::Create(catalogs_, &error)); |
| 252 EXPECT_TRUE(handler_.get() == NULL); | 245 EXPECT_TRUE(handler_.get() == NULL); |
| 253 EXPECT_EQ("Variable $a$ used but not defined.", error); | 246 EXPECT_EQ("Variable $a$ used but not defined.", error); |
| 254 | 247 |
| 255 catalogs_[0].reset(CreateBadDictionary(CONTENT_MISSING)); | 248 catalogs_[0] = CreateBadDictionary(CONTENT_MISSING); |
| 256 handler_.reset(MessageBundle::Create(catalogs_, &error)); | 249 handler_.reset(MessageBundle::Create(catalogs_, &error)); |
| 257 EXPECT_TRUE(handler_.get() == NULL); | 250 EXPECT_TRUE(handler_.get() == NULL); |
| 258 EXPECT_EQ("Invalid \"content\" element for key n1.", error); | 251 EXPECT_EQ("Invalid \"content\" element for key n1.", error); |
| 259 | 252 |
| 260 catalogs_[0].reset(CreateBadDictionary(MESSAGE_PLACEHOLDER_DOESNT_MATCH)); | 253 catalogs_[0] = CreateBadDictionary(MESSAGE_PLACEHOLDER_DOESNT_MATCH); |
| 261 handler_.reset(MessageBundle::Create(catalogs_, &error)); | 254 handler_.reset(MessageBundle::Create(catalogs_, &error)); |
| 262 EXPECT_TRUE(handler_.get() == NULL); | 255 EXPECT_TRUE(handler_.get() == NULL); |
| 263 EXPECT_EQ("Variable $a$ used but not defined.", error); | 256 EXPECT_EQ("Variable $a$ used but not defined.", error); |
| 264 } | 257 } |
| 265 | 258 |
| 266 TEST_F(MessageBundleTest, ReservedMessagesOverrideDeveloperMessages) { | 259 TEST_F(MessageBundleTest, ReservedMessagesOverrideDeveloperMessages) { |
| 267 catalogs_.push_back( | 260 catalogs_.push_back(CreateGoodDictionary()); |
| 268 linked_ptr<base::DictionaryValue>(CreateGoodDictionary())); | |
| 269 | 261 |
| 270 base::DictionaryValue* dict = catalogs_[0].get(); | 262 base::DictionaryValue* dict = catalogs_[0].get(); |
| 271 CreateMessageTree(MessageBundle::kUILocaleKey, "x", false, dict); | 263 CreateMessageTree(MessageBundle::kUILocaleKey, "x", false, dict); |
| 272 | 264 |
| 273 std::string error = CreateMessageBundle(); | 265 std::string error = CreateMessageBundle(); |
| 274 | 266 |
| 275 EXPECT_TRUE(handler_.get() == NULL); | 267 EXPECT_TRUE(handler_.get() == NULL); |
| 276 std::string expected_error = ErrorUtils::FormatErrorMessage( | 268 std::string expected_error = ErrorUtils::FormatErrorMessage( |
| 277 errors::kReservedMessageFound, MessageBundle::kUILocaleKey); | 269 errors::kReservedMessageFound, MessageBundle::kUILocaleKey); |
| 278 EXPECT_EQ(expected_error, error); | 270 EXPECT_EQ(expected_error, error); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 messages.insert(std::make_pair("message_name", "message_value")); | 420 messages.insert(std::make_pair("message_name", "message_value")); |
| 429 (*GetExtensionToL10nMessagesMap())[extension_id] = messages; | 421 (*GetExtensionToL10nMessagesMap())[extension_id] = messages; |
| 430 | 422 |
| 431 L10nMessagesMap* map = GetL10nMessagesMap(extension_id); | 423 L10nMessagesMap* map = GetL10nMessagesMap(extension_id); |
| 432 ASSERT_TRUE(NULL != map); | 424 ASSERT_TRUE(NULL != map); |
| 433 EXPECT_EQ(1U, map->size()); | 425 EXPECT_EQ(1U, map->size()); |
| 434 EXPECT_EQ("message_value", (*map)["message_name"]); | 426 EXPECT_EQ("message_value", (*map)["message_name"]); |
| 435 } | 427 } |
| 436 | 428 |
| 437 } // namespace extensions | 429 } // namespace extensions |
| OLD | NEW |