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