diff options
Diffstat (limited to 'chromium/chrome/renderer/extensions/i18n_hooks_delegate_unittest.cc')
-rw-r--r-- | chromium/chrome/renderer/extensions/i18n_hooks_delegate_unittest.cc | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/chromium/chrome/renderer/extensions/i18n_hooks_delegate_unittest.cc b/chromium/chrome/renderer/extensions/i18n_hooks_delegate_unittest.cc new file mode 100644 index 00000000000..0e37101c92c --- /dev/null +++ b/chromium/chrome/renderer/extensions/i18n_hooks_delegate_unittest.cc @@ -0,0 +1,110 @@ +// Copyright 2018 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 "extensions/renderer/i18n_hooks_delegate.h" + +#include "base/strings/stringprintf.h" +#include "extensions/common/extension_builder.h" +#include "extensions/common/message_bundle.h" +#include "extensions/renderer/bindings/api_binding_test_util.h" +#include "extensions/renderer/native_extension_bindings_system.h" +#include "extensions/renderer/native_extension_bindings_system_test_base.h" +#include "extensions/renderer/script_context.h" + +namespace extensions { + +using I18nHooksDelegateTest = NativeExtensionBindingsSystemUnittest; + +// NOTE(devlin): This test lives in //chrome (rather than //extensions) since +// the feature is defined at the chrome level (in +// chrome/common/extensions/api/i18n.json). However, all the custom bindings +// for i18n live at the //extensions level. We should move these to all be in +// the same location. +TEST_F(I18nHooksDelegateTest, TestI18nGetMessage) { + scoped_refptr<const Extension> extension = ExtensionBuilder("foo").Build(); + RegisterExtension(extension); + + v8::HandleScope handle_scope(isolate()); + v8::Local<v8::Context> context = MainContext(); + + ScriptContext* script_context = CreateScriptContext( + context, extension.get(), Feature::BLESSED_EXTENSION_CONTEXT); + script_context->set_url(extension->url()); + bindings_system()->UpdateBindingsForContext(script_context); + + // In practice, messages will be retrieved from the browser process on first + // request. Since this is a unittest, pre-populate the message bundle. + L10nMessagesMap messages = { + {"simple", "simple message"}, + {"one_placeholder", "placeholder $1 end"}, + {"multi_placeholders", "placeholder $1 and $2 end"}, + {"special_characters", "< Hello $1 World >"}}; + GetExtensionToL10nMessagesMap()->emplace(extension->id(), messages); + + auto run_get_message = [context](const char* args) { + SCOPED_TRACE(args); + constexpr char kRunGetMessageFunction[] = + "(function() { return chrome.i18n.getMessage(%s); })"; + v8::Local<v8::Function> function = FunctionFromString( + context, base::StringPrintf(kRunGetMessageFunction, args)); + v8::Local<v8::Value> result = RunFunction(function, context, 0, nullptr); + return V8ToString(result, context); + }; + + // Simple tests. + + EXPECT_EQ(R"("simple message")", run_get_message("'simple'")); + EXPECT_EQ(R"("placeholder foo end")", + run_get_message("'one_placeholder', 'foo'")); + EXPECT_EQ(R"("placeholder foo end")", + run_get_message("'one_placeholder', ['foo']")); + EXPECT_EQ(R"("placeholder foo and bar end")", + run_get_message("'multi_placeholders', ['foo', 'bar']")); + EXPECT_EQ(R"("\u003C Hello \u003Cbr> World >")", + run_get_message("'special_characters', ['<br>'], {}")); + EXPECT_EQ( + R"("\u003C Hello \u003Cbr> World >")", + run_get_message("'special_characters', ['<br>'], {escapeLt: false}")); + EXPECT_EQ( + R"("< Hello \u003Cbr> World >")", + run_get_message("'special_characters', ['<br>'], {escapeLt: true}")); + + // We place the somewhat-arbitrary (but documented) limit of 9 substitutions + // on the call. + EXPECT_EQ("undefined", + run_get_message("'one_placeholder'," + "['one', 'two', 'three', 'four', 'five', 'six'," + " 'seven', 'eight', 'nine', 'ten']")); + + // Oddities. All of these should probably behave differently. These tests are + // more for documentation than for desirable functionality. + + // Non-string values passed in the array of placeholders will be implicitly + // converted to strings... + EXPECT_EQ(R"("placeholder [object Object] end")", + run_get_message("'one_placeholder', [{}]")); + // ... While non-string values passed as a single placeholder are silently + // ignored. + EXPECT_EQ(R"("placeholder end")", run_get_message("'one_placeholder', {}")); + // And values can throw errors (which are silently caught) in string + // conversions, in which case the value is silently ignored. + EXPECT_EQ(R"("placeholder end")", + run_get_message("'one_placeholder'," + "[{toString() { throw new Error('haha'); } }]")); + EXPECT_EQ("undefined", + run_get_message("'one_placeholder'," + "(function() {" + " var x = [];" + " Object.defineProperty(x, 0, {" + " get() { throw new Error('haha'); }" + " });" + " return x;" + " })()")); + EXPECT_EQ( + R"("placeholder foo end")", + run_get_message("'one_placeholder'," + "[{toString() { throw new Error('haha'); } }, 'foo']")); +} + +} // namespace extensions |