ipc_message_attachment.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright (c) 2015 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 "ipc/ipc_message_attachment.h"
  5. #include "base/files/scoped_file.h"
  6. #include "base/logging.h"
  7. #include "base/notreached.h"
  8. #include "build/build_config.h"
  9. #include "ipc/ipc_mojo_handle_attachment.h"
  10. #include "mojo/public/cpp/system/platform_handle.h"
  11. #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  12. #include <unistd.h>
  13. #include "base/posix/eintr_wrapper.h"
  14. #include "ipc/ipc_platform_file_attachment_posix.h"
  15. #endif
  16. #if BUILDFLAG(IS_MAC)
  17. #include "ipc/mach_port_attachment_mac.h"
  18. #endif
  19. #if BUILDFLAG(IS_WIN)
  20. #include "ipc/handle_attachment_win.h"
  21. #endif
  22. #if BUILDFLAG(IS_FUCHSIA)
  23. #include "ipc/handle_attachment_fuchsia.h"
  24. #endif
  25. namespace IPC {
  26. namespace {
  27. #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  28. base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) {
  29. return attachment->Owns()
  30. ? base::ScopedFD(attachment->TakePlatformFile())
  31. : base::ScopedFD(HANDLE_EINTR(dup(attachment->file())));
  32. }
  33. #endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  34. } // namespace
  35. MessageAttachment::MessageAttachment() = default;
  36. MessageAttachment::~MessageAttachment() = default;
  37. mojo::ScopedHandle MessageAttachment::TakeMojoHandle() {
  38. switch (GetType()) {
  39. case Type::MOJO_HANDLE:
  40. return static_cast<internal::MojoHandleAttachment*>(this)->TakeHandle();
  41. #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  42. case Type::PLATFORM_FILE: {
  43. // We dup() the handles in IPC::Message to transmit.
  44. // IPC::MessageAttachmentSet has intricate lifetime semantics for FDs, so
  45. // just to dup()-and-own them is the safest option.
  46. base::ScopedFD file =
  47. TakeOrDupFile(static_cast<internal::PlatformFileAttachment*>(this));
  48. if (!file.is_valid()) {
  49. DPLOG(WARNING) << "Failed to dup FD to transmit.";
  50. return mojo::ScopedHandle();
  51. }
  52. return mojo::WrapPlatformFile(std::move(file));
  53. }
  54. #endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  55. #if BUILDFLAG(IS_MAC)
  56. case Type::MACH_PORT: {
  57. auto* attachment = static_cast<internal::MachPortAttachmentMac*>(this);
  58. MojoPlatformHandle platform_handle = {
  59. sizeof(platform_handle), MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT,
  60. static_cast<uint64_t>(attachment->get_mach_port())};
  61. MojoHandle wrapped_handle;
  62. if (MojoWrapPlatformHandle(&platform_handle, nullptr, &wrapped_handle) !=
  63. MOJO_RESULT_OK) {
  64. return mojo::ScopedHandle();
  65. }
  66. attachment->reset_mach_port_ownership();
  67. return mojo::MakeScopedHandle(mojo::Handle(wrapped_handle));
  68. }
  69. #elif BUILDFLAG(IS_FUCHSIA)
  70. case Type::FUCHSIA_HANDLE: {
  71. auto* attachment = static_cast<internal::HandleAttachmentFuchsia*>(this);
  72. MojoPlatformHandle platform_handle = {
  73. sizeof(platform_handle), MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE,
  74. static_cast<uint64_t>(attachment->Take())};
  75. MojoHandle wrapped_handle;
  76. if (MojoWrapPlatformHandle(&platform_handle, nullptr, &wrapped_handle) !=
  77. MOJO_RESULT_OK) {
  78. return mojo::ScopedHandle();
  79. }
  80. return mojo::MakeScopedHandle(mojo::Handle(wrapped_handle));
  81. }
  82. #elif BUILDFLAG(IS_WIN)
  83. case Type::WIN_HANDLE:
  84. return mojo::WrapPlatformFile(base::win::ScopedHandle(
  85. static_cast<internal::HandleAttachmentWin*>(this)->Take()));
  86. #endif
  87. default:
  88. break;
  89. }
  90. NOTREACHED();
  91. return mojo::ScopedHandle();
  92. }
  93. // static
  94. scoped_refptr<MessageAttachment> MessageAttachment::CreateFromMojoHandle(
  95. mojo::ScopedHandle handle,
  96. Type type) {
  97. if (type == Type::MOJO_HANDLE)
  98. return new internal::MojoHandleAttachment(std::move(handle));
  99. MojoPlatformHandle platform_handle = {sizeof(platform_handle), 0, 0};
  100. MojoResult unwrap_result = MojoUnwrapPlatformHandle(
  101. handle.release().value(), nullptr, &platform_handle);
  102. if (unwrap_result != MOJO_RESULT_OK)
  103. return nullptr;
  104. #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  105. if (type == Type::PLATFORM_FILE) {
  106. base::PlatformFile file = base::kInvalidPlatformFile;
  107. if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR)
  108. file = static_cast<base::PlatformFile>(platform_handle.value);
  109. return new internal::PlatformFileAttachment(file);
  110. }
  111. #endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  112. #if BUILDFLAG(IS_MAC)
  113. if (type == Type::MACH_PORT) {
  114. mach_port_t mach_port = MACH_PORT_NULL;
  115. if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT)
  116. mach_port = static_cast<mach_port_t>(platform_handle.value);
  117. return new internal::MachPortAttachmentMac(
  118. mach_port, internal::MachPortAttachmentMac::FROM_WIRE);
  119. }
  120. #elif BUILDFLAG(IS_FUCHSIA)
  121. if (type == Type::FUCHSIA_HANDLE) {
  122. zx::handle zx_handle;
  123. if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE)
  124. zx_handle.reset(static_cast<zx_handle_t>(platform_handle.value));
  125. return new internal::HandleAttachmentFuchsia(std::move(zx_handle));
  126. }
  127. #elif BUILDFLAG(IS_WIN)
  128. if (type == Type::WIN_HANDLE) {
  129. base::PlatformFile platform_file = base::kInvalidPlatformFile;
  130. if (platform_handle.type == MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE) {
  131. platform_file =
  132. reinterpret_cast<base::PlatformFile>(platform_handle.value);
  133. }
  134. return new internal::HandleAttachmentWin(
  135. platform_file, internal::HandleAttachmentWin::FROM_WIRE);
  136. }
  137. #endif
  138. NOTREACHED();
  139. return nullptr;
  140. }
  141. } // namespace IPC