OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/edk/embedder/platform_channel_pair.h" | 5 #include "mojo/edk/embedder/platform_channel_pair.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
(...skipping 17 matching lines...) Expand all Loading... |
28 | 28 |
29 #if !defined(SO_PEEK_OFF) | 29 #if !defined(SO_PEEK_OFF) |
30 #define SO_PEEK_OFF 42 | 30 #define SO_PEEK_OFF 42 |
31 #endif | 31 #endif |
32 | 32 |
33 namespace mojo { | 33 namespace mojo { |
34 namespace edk { | 34 namespace edk { |
35 | 35 |
36 namespace { | 36 namespace { |
37 | 37 |
38 #if defined(OS_ANDROID) | |
39 enum { | |
40 // Leave room for any other descriptors defined in content for example. | |
41 // TODO(jcivelli): consider changing base::GlobalDescriptors to generate a | |
42 // key when setting the file descriptor (http://crbug.com/676442). | |
43 kAndroidClientHandleDescriptor = | |
44 base::GlobalDescriptors::kBaseDescriptor + 10000, | |
45 }; | |
46 #else | |
47 bool IsTargetDescriptorUsed( | 38 bool IsTargetDescriptorUsed( |
48 const base::FileHandleMappingVector& file_handle_mapping, | 39 const base::FileHandleMappingVector& file_handle_mapping, |
49 int target_fd) { | 40 int target_fd) { |
50 for (size_t i = 0; i < file_handle_mapping.size(); i++) { | 41 for (size_t i = 0; i < file_handle_mapping.size(); i++) { |
51 if (file_handle_mapping[i].second == target_fd) | 42 if (file_handle_mapping[i].second == target_fd) |
52 return true; | 43 return true; |
53 } | 44 } |
54 return false; | 45 return false; |
55 } | 46 } |
56 #endif | |
57 | 47 |
58 } // namespace | 48 } // namespace |
59 | 49 |
60 PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) { | 50 PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) { |
61 // Create the Unix domain socket. | 51 // Create the Unix domain socket. |
62 int fds[2]; | 52 int fds[2]; |
63 // TODO(vtl): Maybe fail gracefully if |socketpair()| fails. | 53 // TODO(vtl): Maybe fail gracefully if |socketpair()| fails. |
64 | 54 |
65 #if defined(OS_NACL_SFI) | 55 #if defined(OS_NACL_SFI) |
66 PCHECK(imc_socketpair(fds) == 0); | 56 PCHECK(imc_socketpair(fds) == 0); |
(...skipping 28 matching lines...) Expand all Loading... |
95 const base::CommandLine& command_line) { | 85 const base::CommandLine& command_line) { |
96 std::string client_fd_string = | 86 std::string client_fd_string = |
97 command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); | 87 command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); |
98 return PassClientHandleFromParentProcessFromString(client_fd_string); | 88 return PassClientHandleFromParentProcessFromString(client_fd_string); |
99 } | 89 } |
100 | 90 |
101 ScopedPlatformHandle | 91 ScopedPlatformHandle |
102 PlatformChannelPair::PassClientHandleFromParentProcessFromString( | 92 PlatformChannelPair::PassClientHandleFromParentProcessFromString( |
103 const std::string& value) { | 93 const std::string& value) { |
104 int client_fd = -1; | 94 int client_fd = -1; |
105 #if defined(OS_ANDROID) | |
106 base::GlobalDescriptors::Key key = -1; | |
107 if (value.empty() || !base::StringToUint(value, &key)) { | |
108 LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; | |
109 return ScopedPlatformHandle(); | |
110 } | |
111 client_fd = base::GlobalDescriptors::GetInstance()->Get(key); | |
112 #else | |
113 if (value.empty() || | 95 if (value.empty() || |
114 !base::StringToInt(value, &client_fd) || | 96 !base::StringToInt(value, &client_fd) || |
115 client_fd < base::GlobalDescriptors::kBaseDescriptor) { | 97 client_fd < base::GlobalDescriptors::kBaseDescriptor) { |
116 LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; | 98 LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; |
117 return ScopedPlatformHandle(); | 99 return ScopedPlatformHandle(); |
118 } | 100 } |
119 #endif | 101 |
120 return ScopedPlatformHandle(PlatformHandle(client_fd)); | 102 return ScopedPlatformHandle(PlatformHandle(client_fd)); |
121 } | 103 } |
122 | 104 |
123 void PlatformChannelPair::PrepareToPassClientHandleToChildProcess( | 105 void PlatformChannelPair::PrepareToPassClientHandleToChildProcess( |
124 base::CommandLine* command_line, | 106 base::CommandLine* command_line, |
125 base::FileHandleMappingVector* handle_passing_info) const { | 107 base::FileHandleMappingVector* handle_passing_info) const { |
126 DCHECK(command_line); | 108 DCHECK(command_line); |
127 | 109 |
128 // Log a warning if the command line already has the switch, but "clobber" it | 110 // Log a warning if the command line already has the switch, but "clobber" it |
129 // anyway, since it's reasonably likely that all the switches were just copied | 111 // anyway, since it's reasonably likely that all the switches were just copied |
130 // from the parent. | 112 // from the parent. |
131 LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) | 113 LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) |
132 << "Child command line already has switch --" | 114 << "Child command line already has switch --" |
133 << kMojoPlatformChannelHandleSwitch << "=" | 115 << kMojoPlatformChannelHandleSwitch << "=" |
134 << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); | 116 << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); |
135 // (Any existing switch won't actually be removed from the command line, but | 117 // (Any existing switch won't actually be removed from the command line, but |
136 // the last one appended takes precedence.) | 118 // the last one appended takes precedence.) |
137 command_line->AppendSwitchASCII( | 119 command_line->AppendSwitchASCII( |
138 kMojoPlatformChannelHandleSwitch, | 120 kMojoPlatformChannelHandleSwitch, |
139 PrepareToPassClientHandleToChildProcessAsString(handle_passing_info)); | 121 PrepareToPassClientHandleToChildProcessAsString(handle_passing_info)); |
140 } | 122 } |
141 | 123 |
142 std::string | 124 std::string |
143 PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString( | 125 PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString( |
144 HandlePassingInformation* handle_passing_info) const { | 126 HandlePassingInformation* handle_passing_info) const { |
145 #if defined(OS_ANDROID) | |
146 int fd = client_handle_.get().handle; | |
147 handle_passing_info->push_back( | |
148 std::pair<int, int>(fd, kAndroidClientHandleDescriptor)); | |
149 return base::UintToString(kAndroidClientHandleDescriptor); | |
150 #else | |
151 DCHECK(handle_passing_info); | 127 DCHECK(handle_passing_info); |
152 // This is an arbitrary sanity check. (Note that this guarantees that the loop | 128 // This is an arbitrary sanity check. (Note that this guarantees that the loop |
153 // below will terminate sanely.) | 129 // below will terminate sanely.) |
154 CHECK_LT(handle_passing_info->size(), 1000u); | 130 CHECK_LT(handle_passing_info->size(), 1000u); |
155 | 131 |
156 DCHECK(client_handle_.is_valid()); | 132 DCHECK(client_handle_.is_valid()); |
157 | 133 |
158 // Find a suitable FD to map our client handle to in the child process. | 134 // Find a suitable FD to map our client handle to in the child process. |
159 // This has quadratic time complexity in the size of |*handle_passing_info|, | 135 // This has quadratic time complexity in the size of |*handle_passing_info|, |
160 // but |*handle_passing_info| should be very small (usually/often empty). | 136 // but |*handle_passing_info| should be very small (usually/often empty). |
161 int target_fd = base::GlobalDescriptors::kBaseDescriptor; | 137 int target_fd = base::GlobalDescriptors::kBaseDescriptor; |
162 while (IsTargetDescriptorUsed(*handle_passing_info, target_fd)) | 138 while (IsTargetDescriptorUsed(*handle_passing_info, target_fd)) |
163 target_fd++; | 139 target_fd++; |
164 | 140 |
165 handle_passing_info->push_back( | 141 handle_passing_info->push_back( |
166 std::pair<int, int>(client_handle_.get().handle, target_fd)); | 142 std::pair<int, int>(client_handle_.get().handle, target_fd)); |
167 return base::IntToString(target_fd); | 143 return base::IntToString(target_fd); |
168 #endif | |
169 } | 144 } |
170 | 145 |
171 } // namespace edk | 146 } // namespace edk |
172 } // namespace mojo | 147 } // namespace mojo |
OLD | NEW |