messaging_util_unittest.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright 2017 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. #include "extensions/renderer/messaging_util.h"
  5. #include <memory>
  6. #include "base/strings/stringprintf.h"
  7. #include "extensions/common/api/messaging/message.h"
  8. #include "extensions/common/api/messaging/serialization_format.h"
  9. #include "extensions/common/extension_builder.h"
  10. #include "extensions/renderer/bindings/api_binding_test.h"
  11. #include "extensions/renderer/bindings/api_binding_test_util.h"
  12. #include "extensions/renderer/native_extension_bindings_system_test_base.h"
  13. #include "extensions/renderer/script_context.h"
  14. #include "gin/converter.h"
  15. #include "v8/include/v8.h"
  16. namespace extensions {
  17. using MessagingUtilTest = APIBindingTest;
  18. TEST_F(MessagingUtilTest, TestMaximumMessageSize) {
  19. v8::HandleScope handle_scope(isolate());
  20. v8::Local<v8::Context> context = MainContext();
  21. constexpr char kMessageTooLongError[] =
  22. "Message length exceeded maximum allowed length.";
  23. v8::Local<v8::Value> long_message =
  24. V8ValueFromScriptSource(context, "'a'.repeat(1024 *1024 * 65)");
  25. std::string error;
  26. std::unique_ptr<Message> message = messaging_util::MessageFromV8(
  27. context, long_message, SerializationFormat::kJson, &error);
  28. EXPECT_FALSE(message);
  29. EXPECT_EQ(kMessageTooLongError, error);
  30. }
  31. TEST_F(MessagingUtilTest, TestParseMessageOptionsFrameId) {
  32. v8::HandleScope handle_scope(isolate());
  33. v8::Local<v8::Context> context = MainContext();
  34. struct {
  35. int expected_frame_id;
  36. const char* string_options;
  37. } test_cases[] = {
  38. {messaging_util::kNoFrameId, "({})"},
  39. {messaging_util::kNoFrameId, "({frameId: undefined})"},
  40. // Note: we don't test null here, because the argument parsing code
  41. // ensures we would never pass undefined to ParseMessageOptions (and
  42. // there's a DCHECK to validate it). The null case is tested in the tabs'
  43. // API hooks delegate test.
  44. {0, "({frameId: 0})"},
  45. {2, "({frameId: 2})"},
  46. };
  47. for (const auto& test_case : test_cases) {
  48. SCOPED_TRACE(test_case.string_options);
  49. v8::Local<v8::Value> value =
  50. V8ValueFromScriptSource(context, test_case.string_options);
  51. ASSERT_FALSE(value.IsEmpty());
  52. ASSERT_TRUE(value->IsObject());
  53. messaging_util::MessageOptions options =
  54. messaging_util::ParseMessageOptions(context, value.As<v8::Object>(),
  55. messaging_util::PARSE_FRAME_ID);
  56. EXPECT_EQ(test_case.expected_frame_id, options.frame_id);
  57. }
  58. }
  59. using MessagingUtilWithSystemTest = NativeExtensionBindingsSystemUnittest;
  60. TEST_F(MessagingUtilWithSystemTest, TestGetTargetIdFromExtensionContext) {
  61. v8::HandleScope handle_scope(isolate());
  62. v8::Local<v8::Context> context = MainContext();
  63. scoped_refptr<const Extension> extension = ExtensionBuilder("foo").Build();
  64. RegisterExtension(extension);
  65. ScriptContext* script_context = CreateScriptContext(
  66. context, extension.get(), Feature::BLESSED_EXTENSION_CONTEXT);
  67. script_context->set_url(extension->url());
  68. std::string other_id(32, 'a');
  69. struct {
  70. v8::Local<v8::Value> passed_id;
  71. base::StringPiece expected_id;
  72. bool should_pass;
  73. } test_cases[] = {
  74. // If the extension ID is not provided, the bindings use the calling
  75. // extension's.
  76. {v8::Null(isolate()), extension->id(), true},
  77. // We treat the empty string to be the same as null, even though it's
  78. // somewhat unfortunate.
  79. // See https://crbug.com/823577.
  80. {gin::StringToV8(isolate(), ""), extension->id(), true},
  81. {gin::StringToV8(isolate(), extension->id()), extension->id(), true},
  82. {gin::StringToV8(isolate(), other_id), other_id, true},
  83. {gin::StringToV8(isolate(), "invalid id"), base::StringPiece(), false},
  84. };
  85. for (size_t i = 0; i < std::size(test_cases); ++i) {
  86. SCOPED_TRACE(base::StringPrintf("Test Case: %d", static_cast<int>(i)));
  87. const auto& test_case = test_cases[i];
  88. std::string target;
  89. std::string error;
  90. EXPECT_EQ(test_case.should_pass,
  91. messaging_util::GetTargetExtensionId(
  92. script_context, test_case.passed_id, "runtime.sendMessage",
  93. &target, &error));
  94. EXPECT_EQ(test_case.expected_id, target);
  95. EXPECT_EQ(test_case.should_pass, error.empty()) << error;
  96. }
  97. }
  98. TEST_F(MessagingUtilWithSystemTest, TestGetTargetIdFromWebContext) {
  99. v8::HandleScope handle_scope(isolate());
  100. v8::Local<v8::Context> context = MainContext();
  101. ScriptContext* script_context =
  102. CreateScriptContext(context, nullptr, Feature::WEB_PAGE_CONTEXT);
  103. script_context->set_url(GURL("https://example.com"));
  104. std::string other_id(32, 'a');
  105. struct {
  106. v8::Local<v8::Value> passed_id;
  107. base::StringPiece expected_id;
  108. bool should_pass;
  109. } test_cases[] = {
  110. // A web page should always have to specify the extension id.
  111. {gin::StringToV8(isolate(), other_id), other_id, true},
  112. {v8::Null(isolate()), base::StringPiece(), false},
  113. {gin::StringToV8(isolate(), ""), base::StringPiece(), false},
  114. {gin::StringToV8(isolate(), "invalid id"), base::StringPiece(), false},
  115. };
  116. for (size_t i = 0; i < std::size(test_cases); ++i) {
  117. SCOPED_TRACE(base::StringPrintf("Test Case: %d", static_cast<int>(i)));
  118. const auto& test_case = test_cases[i];
  119. std::string target;
  120. std::string error;
  121. EXPECT_EQ(test_case.should_pass,
  122. messaging_util::GetTargetExtensionId(
  123. script_context, test_case.passed_id, "runtime.sendMessage",
  124. &target, &error));
  125. EXPECT_EQ(test_case.expected_id, target);
  126. EXPECT_EQ(test_case.should_pass, error.empty()) << error;
  127. }
  128. }
  129. } // namespace extensions