parent_port.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright (c) 2022 Microsoft, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/services/node/parent_port.h"
  5. #include <utility>
  6. #include "base/no_destructor.h"
  7. #include "gin/data_object_builder.h"
  8. #include "gin/handle.h"
  9. #include "gin/object_template_builder.h"
  10. #include "shell/browser/api/message_port.h"
  11. #include "shell/browser/javascript_environment.h"
  12. #include "shell/common/gin_helper/dictionary.h"
  13. #include "shell/common/gin_helper/event_emitter_caller.h"
  14. #include "shell/common/node_includes.h"
  15. #include "shell/common/v8_util.h"
  16. #include "third_party/blink/public/common/messaging/transferable_message_mojom_traits.h"
  17. namespace electron {
  18. gin::WrapperInfo ParentPort::kWrapperInfo = {gin::kEmbedderNativeGin};
  19. ParentPort* ParentPort::GetInstance() {
  20. static base::NoDestructor<ParentPort> instance;
  21. return instance.get();
  22. }
  23. ParentPort::ParentPort() = default;
  24. ParentPort::~ParentPort() = default;
  25. void ParentPort::Initialize(blink::MessagePortDescriptor port) {
  26. port_ = std::move(port);
  27. connector_ = std::make_unique<mojo::Connector>(
  28. port_.TakeHandleToEntangleWithEmbedder(),
  29. mojo::Connector::SINGLE_THREADED_SEND,
  30. base::SingleThreadTaskRunner::GetCurrentDefault());
  31. connector_->PauseIncomingMethodCallProcessing();
  32. connector_->set_incoming_receiver(this);
  33. connector_->set_connection_error_handler(
  34. base::BindOnce(&ParentPort::Close, base::Unretained(this)));
  35. }
  36. void ParentPort::PostMessage(v8::Local<v8::Value> message_value) {
  37. if (!connector_closed_ && connector_ && connector_->is_valid()) {
  38. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  39. blink::TransferableMessage transferable_message;
  40. if (!electron::SerializeV8Value(isolate, message_value,
  41. &transferable_message)) {
  42. // SerializeV8Value sets an exception.
  43. return;
  44. }
  45. mojo::Message mojo_message =
  46. blink::mojom::TransferableMessage::WrapAsMessage(
  47. std::move(transferable_message));
  48. connector_->Accept(&mojo_message);
  49. }
  50. }
  51. void ParentPort::Close() {
  52. if (!connector_closed_ && connector_->is_valid()) {
  53. port_.GiveDisentangledHandle(connector_->PassMessagePipe());
  54. connector_ = nullptr;
  55. port_.Reset();
  56. connector_closed_ = true;
  57. }
  58. }
  59. void ParentPort::Start() {
  60. if (!connector_closed_ && connector_ && connector_->is_valid()) {
  61. connector_->ResumeIncomingMethodCallProcessing();
  62. }
  63. }
  64. void ParentPort::Pause() {
  65. if (!connector_closed_ && connector_ && connector_->is_valid()) {
  66. connector_->PauseIncomingMethodCallProcessing();
  67. }
  68. }
  69. bool ParentPort::Accept(mojo::Message* mojo_message) {
  70. blink::TransferableMessage message;
  71. if (!blink::mojom::TransferableMessage::DeserializeFromMessage(
  72. std::move(*mojo_message), &message)) {
  73. return false;
  74. }
  75. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  76. v8::HandleScope handle_scope(isolate);
  77. auto wrapped_ports =
  78. MessagePort::EntanglePorts(isolate, std::move(message.ports));
  79. v8::Local<v8::Value> message_value =
  80. electron::DeserializeV8Value(isolate, message);
  81. v8::Local<v8::Object> self;
  82. if (!GetWrapper(isolate).ToLocal(&self))
  83. return false;
  84. auto event = gin::DataObjectBuilder(isolate)
  85. .Set("data", message_value)
  86. .Set("ports", wrapped_ports)
  87. .Build();
  88. gin_helper::EmitEvent(isolate, self, "message", event);
  89. return true;
  90. }
  91. // static
  92. gin::Handle<ParentPort> ParentPort::Create(v8::Isolate* isolate) {
  93. return gin::CreateHandle(isolate, ParentPort::GetInstance());
  94. }
  95. // static
  96. gin::ObjectTemplateBuilder ParentPort::GetObjectTemplateBuilder(
  97. v8::Isolate* isolate) {
  98. return gin::Wrappable<ParentPort>::GetObjectTemplateBuilder(isolate)
  99. .SetMethod("postMessage", &ParentPort::PostMessage)
  100. .SetMethod("start", &ParentPort::Start)
  101. .SetMethod("pause", &ParentPort::Pause);
  102. }
  103. const char* ParentPort::GetTypeName() {
  104. return "ParentPort";
  105. }
  106. } // namespace electron
  107. namespace {
  108. void Initialize(v8::Local<v8::Object> exports,
  109. v8::Local<v8::Value> unused,
  110. v8::Local<v8::Context> context,
  111. void* priv) {
  112. v8::Isolate* isolate = context->GetIsolate();
  113. gin_helper::Dictionary dict(isolate, exports);
  114. dict.SetMethod("createParentPort", &electron::ParentPort::Create);
  115. }
  116. } // namespace
  117. NODE_LINKED_BINDING_CONTEXT_AWARE(electron_utility_parent_port, Initialize)