| 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 |
| 38 bool IsTargetDescriptorUsed( | 47 bool IsTargetDescriptorUsed( |
| 39 const base::FileHandleMappingVector& file_handle_mapping, | 48 const base::FileHandleMappingVector& file_handle_mapping, |
| 40 int target_fd) { | 49 int target_fd) { |
| 41 for (size_t i = 0; i < file_handle_mapping.size(); i++) { | 50 for (size_t i = 0; i < file_handle_mapping.size(); i++) { |
| 42 if (file_handle_mapping[i].second == target_fd) | 51 if (file_handle_mapping[i].second == target_fd) |
| 43 return true; | 52 return true; |
| 44 } | 53 } |
| 45 return false; | 54 return false; |
| 46 } | 55 } |
| 56 #endif |
| 47 | 57 |
| 48 } // namespace | 58 } // namespace |
| 49 | 59 |
| 50 PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) { | 60 PlatformChannelPair::PlatformChannelPair(bool client_is_blocking) { |
| 51 // Create the Unix domain socket. | 61 // Create the Unix domain socket. |
| 52 int fds[2]; | 62 int fds[2]; |
| 53 // TODO(vtl): Maybe fail gracefully if |socketpair()| fails. | 63 // TODO(vtl): Maybe fail gracefully if |socketpair()| fails. |
| 54 | 64 |
| 55 #if defined(OS_NACL_SFI) | 65 #if defined(OS_NACL_SFI) |
| 56 PCHECK(imc_socketpair(fds) == 0); | 66 PCHECK(imc_socketpair(fds) == 0); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 85 const base::CommandLine& command_line) { | 95 const base::CommandLine& command_line) { |
| 86 std::string client_fd_string = | 96 std::string client_fd_string = |
| 87 command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); | 97 command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); |
| 88 return PassClientHandleFromParentProcessFromString(client_fd_string); | 98 return PassClientHandleFromParentProcessFromString(client_fd_string); |
| 89 } | 99 } |
| 90 | 100 |
| 91 ScopedPlatformHandle | 101 ScopedPlatformHandle |
| 92 PlatformChannelPair::PassClientHandleFromParentProcessFromString( | 102 PlatformChannelPair::PassClientHandleFromParentProcessFromString( |
| 93 const std::string& value) { | 103 const std::string& value) { |
| 94 int client_fd = -1; | 104 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 |
| 95 if (value.empty() || | 113 if (value.empty() || |
| 96 !base::StringToInt(value, &client_fd) || | 114 !base::StringToInt(value, &client_fd) || |
| 97 client_fd < base::GlobalDescriptors::kBaseDescriptor) { | 115 client_fd < base::GlobalDescriptors::kBaseDescriptor) { |
| 98 LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; | 116 LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch; |
| 99 return ScopedPlatformHandle(); | 117 return ScopedPlatformHandle(); |
| 100 } | 118 } |
| 101 | 119 #endif |
| 102 return ScopedPlatformHandle(PlatformHandle(client_fd)); | 120 return ScopedPlatformHandle(PlatformHandle(client_fd)); |
| 103 } | 121 } |
| 104 | 122 |
| 105 void PlatformChannelPair::PrepareToPassClientHandleToChildProcess( | 123 void PlatformChannelPair::PrepareToPassClientHandleToChildProcess( |
| 106 base::CommandLine* command_line, | 124 base::CommandLine* command_line, |
| 107 base::FileHandleMappingVector* handle_passing_info) const { | 125 base::FileHandleMappingVector* handle_passing_info) const { |
| 108 DCHECK(command_line); | 126 DCHECK(command_line); |
| 109 | 127 |
| 110 // Log a warning if the command line already has the switch, but "clobber" it | 128 // Log a warning if the command line already has the switch, but "clobber" it |
| 111 // anyway, since it's reasonably likely that all the switches were just copied | 129 // anyway, since it's reasonably likely that all the switches were just copied |
| 112 // from the parent. | 130 // from the parent. |
| 113 LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) | 131 LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch)) |
| 114 << "Child command line already has switch --" | 132 << "Child command line already has switch --" |
| 115 << kMojoPlatformChannelHandleSwitch << "=" | 133 << kMojoPlatformChannelHandleSwitch << "=" |
| 116 << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); | 134 << command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch); |
| 117 // (Any existing switch won't actually be removed from the command line, but | 135 // (Any existing switch won't actually be removed from the command line, but |
| 118 // the last one appended takes precedence.) | 136 // the last one appended takes precedence.) |
| 119 command_line->AppendSwitchASCII( | 137 command_line->AppendSwitchASCII( |
| 120 kMojoPlatformChannelHandleSwitch, | 138 kMojoPlatformChannelHandleSwitch, |
| 121 PrepareToPassClientHandleToChildProcessAsString(handle_passing_info)); | 139 PrepareToPassClientHandleToChildProcessAsString(handle_passing_info)); |
| 122 } | 140 } |
| 123 | 141 |
| 124 std::string | 142 std::string |
| 125 PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString( | 143 PlatformChannelPair::PrepareToPassClientHandleToChildProcessAsString( |
| 126 HandlePassingInformation* handle_passing_info) const { | 144 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 |
| 127 DCHECK(handle_passing_info); | 151 DCHECK(handle_passing_info); |
| 128 // This is an arbitrary sanity check. (Note that this guarantees that the loop | 152 // This is an arbitrary sanity check. (Note that this guarantees that the loop |
| 129 // below will terminate sanely.) | 153 // below will terminate sanely.) |
| 130 CHECK_LT(handle_passing_info->size(), 1000u); | 154 CHECK_LT(handle_passing_info->size(), 1000u); |
| 131 | 155 |
| 132 DCHECK(client_handle_.is_valid()); | 156 DCHECK(client_handle_.is_valid()); |
| 133 | 157 |
| 134 // Find a suitable FD to map our client handle to in the child process. | 158 // Find a suitable FD to map our client handle to in the child process. |
| 135 // This has quadratic time complexity in the size of |*handle_passing_info|, | 159 // This has quadratic time complexity in the size of |*handle_passing_info|, |
| 136 // but |*handle_passing_info| should be very small (usually/often empty). | 160 // but |*handle_passing_info| should be very small (usually/often empty). |
| 137 int target_fd = base::GlobalDescriptors::kBaseDescriptor; | 161 int target_fd = base::GlobalDescriptors::kBaseDescriptor; |
| 138 while (IsTargetDescriptorUsed(*handle_passing_info, target_fd)) | 162 while (IsTargetDescriptorUsed(*handle_passing_info, target_fd)) |
| 139 target_fd++; | 163 target_fd++; |
| 140 | 164 |
| 141 handle_passing_info->push_back( | 165 handle_passing_info->push_back( |
| 142 std::pair<int, int>(client_handle_.get().handle, target_fd)); | 166 std::pair<int, int>(client_handle_.get().handle, target_fd)); |
| 143 return base::IntToString(target_fd); | 167 return base::IntToString(target_fd); |
| 168 #endif |
| 144 } | 169 } |
| 145 | 170 |
| 146 } // namespace edk | 171 } // namespace edk |
| 147 } // namespace mojo | 172 } // namespace mojo |
| OLD | NEW |